信息与编码实验教案.docx
《信息与编码实验教案.docx》由会员分享,可在线阅读,更多相关《信息与编码实验教案.docx(14页珍藏版)》请在冰豆网上搜索。
信息与编码实验教案
信息与编码实验教案
数学与计算科学学院
信息教研室
2009年10月10日
信息编码理论是信息计算科学专业的一门重要的专业基础课,对于提高学生的信息科学基础知识具有重要的作用。
信息编码实验,是为了提高学生的应用技能,融汇计算机编程能力培养与信息编码基础理论的一个重要环节。
实验包括四个:
。
●信源熵的计算
●香农编码
●循环码
●有限域上插值多项式的构造
信息编码实验要求用C语言完成。
实验一、信源熵的计算
实验背景:
根据信源熵的性质,英语的信源熵的最大值为
(比特/符号),但事实上,由于在英语中的字母并非等概出现(表1),实际的离散信源熵大概为
(比特/符号),有些字母之间还有较强的依赖关系,为了进一步逼近实际情况,可对英语信源进行2维、三维等形式的统计,求得实际的熵,其中
(比特/符号),
(比特/符号)。
容易推知,有依赖关系的字母数越多,输出的序列越接近于实际情况,当依赖关系延伸到无穷远时,信源输出的就是真正的英语。
此时可求出马尔可夫信源的极限熵
(比特/符号)。
表127个英语符号出现的概率
符号概率
符号概率
符号概率
空格0.2
S 0.052
Y,W 0.012
E 0.105
H 0.047
G 0.011
T 0.072
D 0.035
B 0.0105
O 0.0654
L 0.029
V 0.008
A 0.063
C 0.023
K 0.003
N 0.059
F,U 0.0225
X 0.002
I 0.055
M 0.021
J,Q,Z 0.001
R 0.054
P 0.0175
实验内容:
1.将一大段英文文章作为要统计的样本文件
2.对样本文件进行一维概率统计,并计算出信源熵及冗余度
3.对样本文件进行二维概率统计,并计算出信源熵及冗余度
在进行统计时,首先要在程序中打开文件,然后对文件中的字符读入程序中,进行统计。
而
在二维统计时,尤其要求对文件的指针操作要熟悉。
如读入“newspaper”时,应该依次读入“neewwssppaappeer”,而如果使用fgetc()等命令读文件时,读入的是“newspape”为了依次读入“neewwssppaappeer”,就要求在每次调入fgetc()等命令后,再将文件指针往后退一步,即要求学生能熟练使用fseek()命令进行指针定位操作。
二维信源熵程序如下:
#include
#include
#include
#defineNULL0
intcharge(charc)
{intn;
if(c>=65&&c<=90)
c=c+32;
if(c>+97&&c<=122)
{n=c-97;
returnn;
}
elsereturn-1;
}
voidmain()
{intcount[26][26]={0};
charzifu1,zifu2;
inti,n,m,j;
intsum=0;
floatq,sum1=0;
FILE*fp;
If((fp=fopen(“file”,“rb”))==NULL)
{printf(“can’topenfile!
\n”);
exit(0);
}
while(!
feof(fp))
{zifu1=fgetc(fp);
n=charge(zifu1);
if(n!
=-1)
{zifu2=fgetc(fp);
m=charge(zifu2);
if(m!
=-1)
{count[n][m]++;
fseek(fp,-1,1);
}
}
}
fclose(fp);
for(i=0;i<26;i++)
for(j=0;j<26;j++)
sum=sum+count[i][j];
printf(“thenumberofallthecodeis%d\n”,sum);
q=(float)sum;
for(i=0;i<26;i++)
for(j=0;j<26;j++)
{if(j%3==0)printf(“\n”);
printf(“%c%c,%4d,%6.5f%%”,i+97,j+97,count[i][j],count[i][j]*100/q);
}
printf(“\n”);
for(i=0;i<26;i++)
for(j=0;j<26;j++)
if(count[i][j])
sum1=sum1+(float)((count[i][j]/q)*log10(1/(double)(count[i][j]/q))/log10((double)
(2)));
printf(“\n信息熵为:
H(x)=%f\n”,sum1);
}
实验要求:
1)自己生成一个英文文件,可以在网上找,也可以自己生成。
为了保证实验数据的可靠性,数据的量要比较大。
为了保证二维信源统计的可靠性,建议文件的英文字符在十万以上。
2)编写一维信源统计程序,得出一维统计频次,计算信源熵及剩余度。
3)编写二维信源统计程序,得出二维统计频次,计算信源熵及剩余度。
4)提交二维信源剩余度的实验报告,及实验体会心得。
实验二、香农编码
实验背景:
Hfffman编码、Fano编码以及Shannon编码是重要的统计编码形式,在信源编码中具有重要的作用。
由于Huffman编码在数据结构课程中已经出现。
因此,选用Shannon编码为主要练习对象。
实验内容:
Shannon码编码步骤为:
1.将信源
的所有符号按概率从大到小排列:
2.对第
个信源符号
取整数码长
为取整运算
3.计算累加概率
4.将
变换成二进制数
,并按步骤2中计算的长度
取
的二进制系数
,组合起来即为
的香农码字
.
程序如下:
#include
#include
#include
doubleP[6]={0.25,0.1,0.2,0.25,0.15,0.05},Pax[6],machang[6];
voidmain()
{doubletemp;
for(inta=1;a<6;a++)
{
for(inti=0;i<6-a;i++)
if(P[i]
{
temp=P[i];
P[i]=P[i+1];
P[i+1]=temp;
}
}
for(inti=0;i<6;i++)
cout<
cout<for(i=0;i<6;i++)
{
Pax[0]=0.0;
Pax[i+1]=Pax[i]+P[i];
}
cout<<"概率累加和为:
"<for(i=0;i<6;i++)
cout<cout<for(i=0;i<6;i++)
{
doublem=log(1/P[i])/log
(2);
if(m-int(m)==0)
machang[i]=log(1/P[i])/log
(2);
else
machang[i]=int(m)+1;
cout<
"<}
for(i=0;i<6;i++)
{
for(intj=0;j{
intn=int(Pax[i]*2);
cout<if((Pax[i]*2-1)>0)
{
Pax[i]=Pax[i]*2-1;
continue;
}
if((Pax[i]*2-1)==0)
Pax[i]=Pax[i]*2-1;
else
Pax[i]=Pax[i]*2;
}
cout<}
}
实验要求:
1)熟练掌握香农编码的原理
2)掌握二进制小数的输出方法
3)如果时间允许,建议完成Huffman编码的程序设计。
4)完成香农编码的实验报告及实验心得体会。
实验三、循环码
实验背景:
循环码是线性分组码的一种,具有较好的数学特征,可以用代数理论对循环码进行研究。
在循环码的编码与校验过程中,
上多项式的除法是重要环节。
在徐士良的《常用算法程序集(C语言描述)》中,有实系数的多项式除法。
对其进行改进,使其系数定义在
上,可很好地实现循环编码及校验的要求。
实验内容:
完成二进制多项式除法的设计,程序中
其中
其中
在循环码中,只需保留多项式相除的余式
即可。
下面的程序中,
,
,最后余式
#include"stdio.h"
jiajian(a,b)
inta,b;
{if(a==1&&b==1)return(0);
if(a==0&&b==1)return
(1);
if(a==1&&b==0)return
(1);
if(a==0&&b==0)return(0);
}
cheng(a,b)
inta,b;
{if(a==1&&b==1)return
(1);
if(a==0&&b==1)return(0);
if(a==1&&b==0)return(0);
if(a==0&&b==0)return(0);
}
chu(a,b)
inta,b;
{if(a==1&&b==1)return
(1);
if(a==0)return(0);
}
voidpdiv(p,m,q,n,s,k,r,l)
intm,n,k,l,p[],q[],s[],r[];
{inti,j,mm,ll,kk;
for(i=0;i<=k-1;i++)s[i]=0;
ll=m-1;
for(i=k;i>=1;i--)
{s[i-1]=chu(p[ll],q[n-1]);
mm=ll;
for(j=1;j{kk=cheng(s[i-1],q[n-j-1]);
p[mm-1]=jiajian(p[mm-1],kk);
mm=mm-1;
}
ll=ll-1;
}
for(i=0;i<=l-1;i++)
{r[i]=p[i];
printf("%d",r[i]);
}
return;
}
main()
{inti;
staticintp[6]={1,1,0,0,0,1};
staticintq[4]={1,1,0,1};
ints[3],r[3];
pdiv(p,6,q,4,s,3,r,3);
}
实验要求:
1)熟练掌握CRC编码的原理
2)领会二进制除法在CRC编码中的作用
3)完成
上多项式的除法的程序设计
4)鼓励学生在以上程序的基础上,完成CRC编码、CRC译码的程序设计
5)提交
上多项式的除法的实验报告、实验心得体会
实验四、有限域上插值多项式的构造
实验背景:
依据
个点
构造
次插值多项式
,实质上是求解
无非线性方程组,当插值点数不是很多的时候,可以在较短的时间内计算出插值多项式
的系数
,使之满足
。
但通常的实数域上的计算,无法解决误差问题,为了避免误差问题,我们将插值多项式定义在有限域上,构造出无误差的插值多项式。
当
为素数时,
为有限域,记
为有限域
上的多项式。
实验内容:
例如:
设
满足
的插值多项式
.
即求解方程组
得
解有限域上范德蒙方程组算法思想:
Step0输入向量组
素数p.
Step1对k=1,2,
n-1,执行
(i)对
执行
;
对
执行
(ii)如果abs(y[i])>p,y[i]%=p;如果y[i]<0;y[i]+=p;
(确保运算的对象范围均在(0,p)上)
(iii)对
执行
Step2对k=1,2,
n-1,执行
(i)
;
对
执行
(ii)如果abs(y[i])>p,y[i]%=p;如果y[i]<0;y[i]+=p;
对
执行
(iii)对
执行
Step3输出范德蒙方程组的解x=b.
///////////////////////////////////////////////////////////////////////////////////////////////////
//看程序之前,请仔细阅读解有限域上范德蒙方程组算法思想,如上
//运算过程确保每一步运算的数均在(0,p)内.
///////////////////////////////////////////////////////////////////////////////////////////////////
#include"stdio.h"
#include"malloc.h"
#include"stdlib.h"
intprime=7;//全局变量,确定上限素数
voidVandermond(intn,int*x,int*y);//函数解范德蒙方程组,解即为所要求的系数
intInverse(intxx);//求逆元
voidmain()//主函数入口
{
intn=3;
intx[3]={1,2,4};
inty[3]={2,6,5};
Vandermond(n,x,y);//调用函数求解系数,并存入数组y中
}
voidVandermond(intn,int*x,int*y)//解范德蒙方程组,以获取系数,并存入原数组y中
{intyy,xx;//定义中间变量,以确保每一步运算中间产生的数均在(0,p)范围内.
inttemp;
//
for(intk=0;kfor(inti=n-1;i>k;--i)
{yy=y[i]-y[i-1];
xx=x[i]-x[i-k-1];
if(yy%xx==0)
{
y[i]=yy/xx;//判断xx是否整除yy,否则取yy乘以其逆元
if(y[i]<0){y[i]%=prime;y[i]+=prime;}
}
else
{
y[i]=yy*Inverse(xx);
if(y[i]>prime)y[i]%=prime;
elseif(y[i]<0){y[i]%=prime;y[i]+=prime;}
}
}
for(k=n-2;k>=0;--k)
for(inti=k;i{
temp=y[i+1]*x[k];
if(temp>prime)temp%=prime;
if(temp<0){temp%=prime;temp+=prime;}
y[i]-=temp;
if(y[i]>prime)y[i]%=prime;
if(y[i]<0){y[i]%=prime;y[i]+=prime;}
}
printf("解为:
");
for(inti=0;ireturn;
}
//求x的逆元
//令i=1,2...p,如果满足x*i%p==1,i即为x的逆元
intInverse(intxx)//求xx逆元
{
inttemp;
if(xx<0){xx%=prime;xx+=prime;}
for(inti=1;i{
temp=xx*i;
if(temp%prime==1)returni;
}
return0;
}
实验要求:
1)理解有限域的概念及有限域上的四则运算
2)用程序实现有限域上的方程组的解法。
3)完成实验报告及实验心得体会。