课设复习之信息论基于上下文的自适应算术编码与译码

    xiaoxiao2023-10-17  156

    接上一篇博客:课设复习之信息论自适应算术编码与译码https://blog.csdn.net/hfuter2016212862/article/details/90522250

    在随机理论中,把在某时刻的事件受在这之前事件的影响,其影响范围有限的随机过程,称为马尔可夫过程。一个事件受在它之前的事件的影响的深远程度,通常用在它之前的事件作为条件的概率来表达。受前一个事件的影响,简称为马尔可夫过程;受前两个事件的影响,称为二阶马尔可夫过程;受前三个事件的影响,称为三阶马尔可夫过程。

    题目3:

    设信源可能输出的符号是a, b, c 三个字母,构成一个二阶Markov信源,且各阶条件概率如下,试编写程序可以对任意字母序列(如abbcabcb)进行基于上下文的自适应算术编码,并进行相应的译码。

    零阶条件概率:

           p(a)=1/3;     p(b)=1/3;      p(c)=1/3;

    一阶条件概率:

           p(a/a)=1/2;   p(b/a )=1/4;  p(c/a)=1/4;

           p(a/b)=1/4;   p(b/b)=1/2;  p(c/b)=1/4;

           p(a/c)=1/4;   p(b/c)=1/4;   p(c/c)=1/2;

    二阶条件概率:

           p(a/aa)=3/5; p(b/aa)=1/5; p(c/aa)=1/5;

           p(a/ab)=1/4; p(b/ab)=1/4; p(c/ab)=1/2;

           p(a/ac)=1/4; p(b/ac)=1/4; p(c/a2)=1/2;

           p(a/ba)=1/2; p(b/ba)=1/4; p(c/ba)=1/4;

           p(a/bb)=1/5; p(b/bb)=3/5; p(c/bb)=1/5;

           p(a/bc)=1/4; p(b/bc)=1/4; p(c/bc)=1/2;       

           p(a/ca)=1/2; p(b/ca)=1/4; p(c/ca)=1/4;

           p(a/cb)=1/2; p(b/cb)=1/4; p(c/cb)=1/4;

           p(a/cc)=1/5; p(b/cc)=1/5; p(c/cc)=3/5;

    理论上仍应该采用分组方法解决,精度问题仍存在,课设时未要求此题目分组,有兴趣的读者可以参考上篇博客试试。

    自适应算术编码与译码: 

    全局变量如下: 

    #include<iostream.h> #include<iomanip.h> #include<math.h> #include<string.h> double proc1[3]={1.0/3,1.0/3,1.0/3}; double proc2[3][3]={1.0/2,1.0/4,1.0/4, 1.0/4,1.0/2,1.0/4, 1.0/4,1.0/4,1.0/2}; double proc3[3][3][3]={3.0/5,1.0/5,1.0/5, 1.0/4,1.0/4,1.0/2, 1.0/4,1.0/4,1.0/2, 1.0/2,1.0/4,1.0/4, 1.0/5,3.0/5,1.0/5, 1.0/4,1.0/4,1.0/2, 1.0/2,1.0/4,1.0/4, 1.0/2,1.0/4,1.0/4, 1.0/5,1.0/5,3.0/5};//概率 double result,length=1,interval_begin=0,interval_end=1;//译码所选取的数 int cord[1000],dcord[1000],cordlength;//编码、译码及长度 char str[1000];//输入符号字符串 int strlength=0;

    读取数据代码如下:

    bool readdata(){ cout<<"***********基于上下文自适应算术编码***********"<<endl; cout<<"请输入字符串(a-c):"<<endl; cin>>str; strlength=strlen(str); for(int i=0;i<strlength;i++) if(str[i]>'c'||str[i]<'a') return 1; return 0; }

    自适应算术编码:

    void encode(){ cout<<"编码:"<<endl; int i,j,n1,n2,n3; for(i=0;i<strlength;i++){ if(i==0){ n1=str[0]-'a'; for(j=0;j<n1;j++) interval_begin+=proc1[j]*length; interval_end=interval_begin+proc1[n1]*length; } if(i==1){ n2=str[1]-'a'; for(j=0;j<n2;j++) interval_begin+=proc2[n1][j]*length; interval_end=interval_begin+proc2[n1][n2]*length; } if(i>=2){ n1=str[i-2]-'a'; n2=str[i-1]-'a'; n3=str[i]-'a'; for(j=0;j<n3;j++) interval_begin+=proc3[n1][n2][j]*length; interval_end=interval_begin+proc3[n1][n2][n3]*length; } length=interval_end-interval_begin; } result=interval_begin*0.01+interval_end*0.99; cordlength=int(log(1.0/length)/log(2))+1; cout<<"编码选取的数为:"<<setprecision(16)<<result<<endl; cout<<"编码位数为:"<<cordlength<<endl; double temp; for(i=0;i<cordlength;i++){ temp=result*2; cord[i]=(int)temp; result=temp-cord[i]; } cout<<"输出符号编码为:"; for(i=0;i<cordlength;i++) cout<<cord[i]; cout<<endl; }

    自适应算术译码:

    void decode(){ cout<<"译码:"<<endl; result=0; double a=1; int i,j,k=0,l=0; for(i=0;i<cordlength;i++){ for(j=0;j<=i;j++) a=a*2; result=result+cord[i]/a; a=1; } cout<<"译码选取的数为:"<<setprecision(16)<<result<<endl; length=1; interval_begin=0; for(i=0;i<strlength;i++){ if(i==0){ a=proc1[0]*length; while((result-interval_begin)>a){ k++; a=a+proc1[k]*length; } dcord[i]=k; str[i]=k+'a'; interval_begin+=a-proc1[k]*length; length=length*proc1[k]; } if(i==1){ a=proc2[dcord[0]][0]*length; while((result-interval_begin)>a){ k++; a=a+proc2[dcord[0]][k]*length; } dcord[i]=k; str[i]=k+'a'; interval_begin+=a-proc2[dcord[0]][k]*length; length=length*proc2[dcord[0]][k]; } if(i>=2){ a=proc3[dcord[i-2]][dcord[i-1]][0]*length; while((result-interval_begin)>a){ k++; a=a+proc3[dcord[i-2]][dcord[i-1]][k]*length; } dcord[i]=k; str[i]=k+'a'; interval_begin+=a-proc3[dcord[i-2]][dcord[i-1]][k]*length; length=length*proc3[dcord[i-2]][dcord[i-1]][k]; } k=0; } cout<<"译码结果为:"; for(i=0;i<strlength;i++) cout<<char(dcord[i]+97); cout<<endl; }

    调用主函数如下:

    void main() { if(readdata()) cout<<"字符输入错误!"<<endl; else{ encode(); decode(); } }

    结果如下:

     

     

    最新回复(0)