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

接上一篇博客:课设复习之信息论自适应算术编码与译码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();
	}
} 

结果如下:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值