信息论课程设计.docx
《信息论课程设计.docx》由会员分享,可在线阅读,更多相关《信息论课程设计.docx(25页珍藏版)》请在冰豆网上搜索。
信息论课程设计
信息论课程设计
专业:
信息安全
班级:
1001
学号:
3100604017
姓名:
段惠文
报告日期:
2012年6月18
一、任务说明
1、判定唯一可译码
输入:
任意的一个码(即已知码字个数及每个具体的码字)
输出:
判决结果(是/不是)
输入文件:
in1.txt,含至少2组码,每组的结尾为”$”符
输出文件:
out1.txt,对每组码的判断结果
说明:
为了简化设计,可以假定码字为0,1串
参考算法伪代码:
Forall
do
if
是
的前缀then
将相应的后缀作为一个尾随后缀放入集合
中
Endif
Endfor
Loop
Forall
do
Forall
do
if
是
的前缀then
将相应的后缀作为一个尾随后缀放入集合
中
Elseif
是
的前缀then
将相应的后缀作为一个尾随后缀放入集合
中
Endif
Endfor
Endfor
If
then
Returnfalse
ElseifF中未出现新的元素then
Returntrue
Endif
//能走到这里,说明F中有新的元素出现,需继续
Endloop
2、Shannon编码
输入:
信源符号个数q,信源的概率分布P
输出:
每个信源符号对应的Shannon编码的码字
输入文件:
in2.txt,含至少两组输入,每组包含信源符号个数q和q个信源的概率分布值
输出文件:
out2.txt,对每组输入的编码结果
参考算法伪代码:
降序排列
ForI=1toq
将累加概率
(十进制小数)变换成二进制小数
取小数点后
个二进制数字作为第i个消息的码字
Endfor
3.循环码的编码与译码:
要求:
(7,4)非系统循环码,其中,g(x)=x3+x+1,先编码(多项式乘法),再译码
输入文件:
in6.txt,包括至少两组待编码的信息元序列
输出文件:
out6.txt,对每组信息元的编码和再译码结果
二、问题分析、实现原理
1、判定唯一可译码
根据唯一可译码的判别方法,利用数据结构所学的知识,定义字符串数据类型并利用指针进行编程来实现算法。
算法:
1、考察C中所有的码字,若Wi是Wj的前缀,则将对应的后缀作为一个尾随后缀码放入集合Fi+1中;
2、考察C和Fi俩个集合,若Wi∈C是Wj∈F的前缀或Wi∈F是Wj∈C的前缀,则将相应的后缀作为尾随后缀码放入集合Fi+1中;
3、F=∪Fi即为码C的尾随后缀集合;
4、若F中出现了C中的元素,算法终止,返回假(C不是唯一可译码);否则若F中没有出现新的元素,则返回真。
2、Shannon编码
信源符号按概率从大到小顺序排列
对信源符号求累加和,表达式:
Pi=Pi-1+P(Xi)
求自信息量来确定码字长度,自信息量I(xi)=-log(p(xi)),码字长度取大于等于自信息量得最下整数。
将累加和用二进制数表示,并取小数点后对应码长度的数做为码字
3.循环码的编码与译码
1.编码过程
在编码时,首先需要根据给定循环码的参数确定生成多项式g(x),也就是从
的因子中选一个(n-k)次
多项式作为g(x);然后,利用循环码的编码特点,即所有循环码多项式A(x)都可以被g(x)整除,来定义生成多项
式g(x)。
根据上述原理可以得到一个较简单的系统:
设要产生(n,k)循环码,m(x)表示信息多项式,循环码编码方法
则其次数必小于k,而
·m(x)的次数必小于n,用
·m(x)除以g(x),可得余数r(x),r(x)的次数必小于
(n-k),将r(x)加到信息位后作监督位,就得到了系统循环码。
下面就将以上各步处理加以解释。
(1)用
乘m(x)。
这一运算实际上是把信息码后附加上(n-k)个“0”。
例如,信息码为110,它相当
于m(x)=
+x。
当n-k=7-3=4时,
·m(x)=
+
,它相当于1100000。
而希望的到得系统循环码多项
式应当是A(x)=
·m(x)+r(x)。
(2)求r(x)。
由于循环码多项式A(x)都可以被g(x)整除,也就是:
因此,用
·m(x)除以g(x),就得到商Q(x)和余式r(x),即
这样就得到了r(x)。
(3)编码输出系统循环码多项式A(x)为:
2.译码过程
对于接收端译码的要求通常有两个:
检错与纠错。
达到检错目的的译码十分简单,可以由式(8-37),通过
判断接收到的码组多项式B(x)是否能被生成多项式g(x)整除作为依据。
当传输中未发生错误时,也就是接收的码
组与发送的码组相同,即A(x)=B(x),则接收的码组B(x)必能被g(x)整除;若传输中发生了错误,则A(x)≠B(x)
,B(x)不能被g(x)整除。
因此,可以根据余项是否为零来判断码组中有无错码。
需要指出的是,有错码的接收码组也有可能被g(x)整除,这时的错码就不能检出了。
这种错误被称为不可检
错误,不可检错误中的错码数必将超过这种编码的检错能力。
在接收端为纠错而采用的译码方法自然比检错要复杂许多,因此,对纠错码的研究大都集中在译码算法上。
我们知道,校正子与错误图样之间存在某种对应关系。
如同其它线性分组码,循环编码和译码可以分三步进行:
(1)由接收到的码多项式B(x)计算校正子(伴随式)多项式S(x);
(2)由校正子S(x)确定错误图样E(x);
(3)将错误图样E(x)与B(x)相加,纠正错误。
上述第
(1)步运算和检错译码类似,也就是求解B(x)整除g(x)的余式,第(3)步也很简单。
因此,纠错码
译码器的复杂性主要取决于译码过程的第
(2)步。
基于错误图样识别的译码器称为梅吉特译码器,它的原理图如图8-7所示。
错误图样识别器是一个具有(n-k)
个输入端的逻辑电路,原则上可以采用查表的方法,根据校正子找到错误图样,利用循环码的上述特性可以简化识
三.实现源码
1、判定唯一可译码
#include
#include
#include
structstrings
{
char*string;
structstrings*next;
};
structstringsFstr,*Fh,*FP;
//输出当前集合
Voidoutputstr(strings*str)
{
do
{
cout<string<str=str->next;
}while(str);
cout<}
IntMIN(inta,intb)
{returna>b?
b:
a;}
intMAX(inta,intb)
{returna>b?
a:
b;}
#definelength_a(strlen(CP))
#definelength_b(strlen(tempPtr))
//判断一个码是否在一个码集合中,在则返回0,不在返回1
intcomparing(strings*st_string,char*code)
{
while(st_string->next)
{
st_string=st_string->next;
if(!
strcmp(st_string->string,code))
return0;
}
return1;
}
//判断两个码字是否一个是另一个的前缀,如果是则生成后缀码
Voidhouzhui(char*CP,char*tempPtr)
{
if(!
strcmp(CP,tempPtr))
{
cout<<"集合C和集合F中有相同码字:
"<<<<"不是唯一可译码码组!
"<exit
(1);
}
if(!
strncmp(CP,tempPtr,MIN(length_a,length_b)))
{
structstrings*cp_temp;
cp_temp=new(structstrings);
cp_temp->next=NULL;
cp_temp->string=newchar[abs(length_a-length_b)+1];
char*longstr;
longstr=(length_a>length_b?
CP:
tempPtr);//将长度长的码赋给longstr
//取出后缀
for(intk=MIN(length_a,length_b);kcp_temp->string[k-MIN(length_a,length_b)]=longstr[k];
cp_temp->string[abs(length_a-length_b)]=NULL;
//判断新生成的后缀码是否已在集合F里,不在则加入F集合
if(comparing(Fh,cp_temp->string))
{
FP->next=cp_temp;
FP=FP->next;
}
}
}
voidmain()
{
//功能提示和程序初始化准备
cout<<"\t\t唯一可译码的判断!
\n"<structstringsCstr,*Ch,*CP,*tempPtr;
Ch=&Cstr;
CP=Ch;
Fh=&Fstr;
FP=Fh;
charc[]="C:
";
Ch->string=newchar[strlen(c)];
strcpy(Ch->string,c);
Ch->next=NULL;
charf[]="F:
";
Fh->string=newchar[strlen(f)];
strcpy(Fh->string,f);
Fh->next=NULL;
//输入待检测码的个数
IntCnum;
cout<<"输入待检测码的个数:
";
cin>>Cnum;
cout<<"输入待检测码"<for(inti=0;i{
cout<
";
chartempstr[10];
cin>>tempstr;
CP->next=new(structstrings);
CP=CP->next;
CP->string=newchar[strlen(tempstr)];
strcpy(CP->string,tempstr);
CP->next=NULL;
}
outputstr(Ch);
CP=Ch;
while(CP->next->next)
{
CP=CP->next;
tempPtr=CP;
do
{
tempPtr=tempPtr->next;
houzhui(CP->string,tempPtr->string);
}while(tempPtr->next);
}
outputstr(Fh);
structstrings*Fbegin,*Fend;
Fend=Fh;
while
(1)
{
if(Fend==FP)
{
cout<<"是唯一可译码码组!
"<exit
(1);
}
Fbegin=Fend;
Fend=FP;
CP=Ch;
while(CP->next)
{
CP=CP->next;
tempPtr=Fbegin;
for(;;)
{
tempPtr=tempPtr->next;
houzhui(CP->string,tempPtr->string);
if(tempPtr==Fend)
break;
}
}
outputstr(Fh);//输出F集合中全部元素
}
}
2、Shannon编码
#include
#include
#include
#definemax_CL10/*maxsizeoflengthofcode*/
#definemax_PN6/*输入序列的个数*/
typedeffloatdatatype;
typedefstructSHNODE{
datatypepb;/*第i个消息符号出现的概率*/
datatypep_sum;/*第i个消息符号累加概率*/
intkl;/*第i个消息符号对应的码长*/
intcode[max_CL];/*第i个消息符号的码字*/
structSHNODE*next;
}shnolist;
datatypesym_arry[max_PN];/*序列的概率*/
voidpb_scan();/*得到序列概率*/
voidpb_sort();/*序列概率排序*/
voidvaluelist(shnolist*L);/*计算累加概率,码长,码字*/
voidcodedisp(shnolist*L);
voidpb_scan()
{
inti;
datatypesum=0;
printf("input%dpossible!
\n",max_PN);
for(i=0;i{printf(">>");
scanf("%f",&sym_arry[i]);
sum=sum+sym_arry[i];
}
/*判断序列的概率之和是否等于,在实现这块模块时,scanf()对float数的缺陷,故只要满足.99if(sum>1.0001||sum<0.99)
{printf("sum=%f,summust(<0.999pb_scan();
}
}
/*选择法排序*/
voidpb_sort()
{
inti,j,pos;
datatypemax;
for(i=0;i{
max=sym_arry[i];
pos=i;
for(j=i+1;jif(sym_arry[j]>max)
{
max=sym_arry[j];
pos=j;
}
sym_arry[pos]=sym_arry[i];
sym_arry[i]=max;
}
}
voidcodedisp(shnolist*L)
{
inti,j;
shnolist*p;
datatypehx=0,KL=0;/*hx存放序列的熵的结果,KL存放序列编码后的平均码字的结果*/
p=L->next;
printf("num\tgailv\tsum\t-lb(p(ai))\tlenth\tcode\n");
printf("\n");
for(i=0;i{
printf("a%d\t%1.3f\t%1.3f\t%f\t%d\t",i,p->pb,p->p_sum,-3.332*log10(p->pb),p->kl);
j=0;
for(j=0;jkl;j++)
printf("%d",p->code[j]);
printf("\n");
hx=hx-p->pb*3.332*log10(p->pb);/*计算消息序列的熵*/
KL=KL+p->kl*p->pb;/*计算平均码字*/
p=p->next;
}
printf("H(x)=%f\tKL=%f\nR=%fbit/code",hx,KL,hx/KL);/*计算编码效率*/
}
shnolist*setnull()
{shnolist*head;
head=(shnolist*)malloc(sizeof(shnolist));
head->next=NULL;
return(head);
}
shnolist*my_creat(datatypea[],intn)
{
shnolist*head,*p,*r;
inti;
head=setnull();
r=head;
for(i=0;i{p=(shnolist*)malloc(sizeof(shnolist));
p->pb=a[i];
p->next=NULL;
r->next=p;
r=p;
}
return(head);
}
voidvaluelist(shnolist*L)
{
shnolist*head,*p;
intj=0;
inti;
datatypetemp,s;
head=L;
p=head->next;
temp=0;
while(j{
p->p_sum=temp;
temp=temp+p->pb;
p->kl=-3.322*log10(p->pb)+1;
/*编码,*/
{
s=p->p_sum;
for(i=0;ikl;i++)
p->code[i]=0;
for(i=0;ikl;i++)
{
p->code[i]=2*s;
if(2*s>=1)
s=2*s-1;
elseif(2*s==0)
break;
elses=2*s;
}
}
j++;
p=p->next;
}
}
intmain(void)
{
shnolist*head;
system("cls");
pb_scan();
pb_sort();
head=my_creat(sym_arry,max_PN);
valuelist(head);
codedisp(head);
system("pause");
}
3.循环码的编码与译码
#include
#include
#include
voidmain()
{intaa[10000];
inti;
intN;
intb[4][7]={{1,0,0,0,1,0,1},{0,1,0,0,1,1,1},{0,0,1,0,1,1,0},{0,0,0,1,0,1,1}};//定义生成矩阵
inty=0,s=0;
intj,k,m;
inta[4],q[7],rr[10000/4*7];
intp,D=0;
intcc[2500],dd[2500];
inte[8][7]={{1,0,0,0,0,0,0},{0,1,0,0,0,0,0},{0,0,1,0,0,0,0},{0,0,0,1,0,0,0},{0,0,0,0,1,0,0},
{0,0,0,0,0,1,0},{0,0,0,0,0,0,1},{1,1,0,0,0,0,0}};//定义错误图样
intw[10000/4*7];
intH[7][3]={{1,0,1},{1,1,1},{1,1,0},{0,1,1},{1,0,0},{0,1,0},{0,0,1}};
intA=0,M=0,L=8;
intf[3];
intww[10000/4*7];
printf("循环码的编码与译码程序:
\n");
printf("请输入你想产生的二进制个数:
");
scanf("%d",&N);//输入想产生的信源的个数
while(N<4)
{
printf("输入无效,请重新输入");
printf("请输入你想产生的二进制个数:
");
scanf("%d",&N);
}
printf("随机产生的二进制序列为:
\n");
srand((unsigned)time(NULL));//产生一个随机序列,并把它放入a[]中
for(i=0;i{aa[i]=rand()%2;
printf("%d",aa[i]);
}
printf("\n");
printf("编码后变为:
\n");//编码生成码字
for(m=0;m{for(i=y;i<(y+4);i++)
{a[i-y]=aa[i];
}////取出位出来
for(j=0;j<7;j++)
{q[j]=0;
for(k=0;k<4;k++)
q[j]+=a[k]*b[k][j];/////与生成矩阵相乘
}
for(i=s;i<(s+7);i++)
{rr[i]=0;
rr[i]=q[i-s]%2;
printf("%d",rr[i]);////将生成的放入rr[]中
}
y=y+4;////向后移动位
s=s+7;///向后移动位
printf("\n");
}
printf("经过信道后变为:
\n");
srand((unsigned)time(NULL));
for(j=0;j{cc[j]=rand()%100;////产生一个~99的随机数
if(cc[j]<9)////当随机数小于时,一个码字产生个错误
{for(i=D;i<(D+7);i++)
{w[i]=0;
w[i]=(rr[i]+e[7][i-D])%2;
printf("%d",w[i]);}
}
elseif((cc[j]>=9)&&(cc[j]<=30))///当随机数在~30时,一个码字产生一个错误
{dd[j]=rand()%7;
p=dd[j];///随机产生一个~6的数,以确定是码字一个错误的位置
for(i=D;i<(D+7);i++)
{w[i]=0;
w[i]=(rr[i]+e[p][i-D])%2;
printf("%d",w[i]);}
}
else//////当随机数在~99时,不发生错误
{for(i=D;i<(D+7);i++)
{w[i]=0;
w[i]=rr[i];
printf("%d",w[i]);}
}
D=D+7;////向后移动位
printf("%6d",cc[j]);/////进行跟踪,以确定码字