目录
实验目的: (2)
实验要求: (2)
程序算法: (2)
程序运行结果: (4)
程序操作步骤: (5)
试验中遇到的困难及解决方法: (5)
实验心得及体会: (5)
实验目的:
1.进一步熟悉使用C++编程语言及软件。
2.进一步认识shannon编码过程,并能在学习中灵活运用。
实验要求:
要求:
(a) 允许使用的编程语言:C、C++、Basic、Pascal、Fortran、Java、Perl
、Tk/Tcl
(b) 输入:信源符号个数q、信源符号s0,...,sq−1,信源概率分布p0,...,pq−1。
(c) 输出:信源符号与码字的对应关系表(编码表)。
(d) 源程序格式整齐清晰,注释简单明了。
程序算法:
(a) 将q 个信源符号按其概率的递减次序排列:
p(s0) > p(s1) > ... > p(sq−1)
(b) 计算出各个信源符号的累加概率:
(c) 按下式计算第i 个消息的二元代码组的码长li:
(d) 将累加概率F(si)(十进制小数)变换成二进制小数。
根据码长li 取小
数点后li 个二进制符号作为第i 个消息的码字。
程序代码:
#include <iostream>
#include <math.h>
using namespace std;
void InsertSort(double r[],char m[] ,int n)//直接插入排序算法按照概率从大到小排列符号和相应概率
{
for(int i=1;i<n;i++)
{
r[n]=r[i]; //设置哨兵
m[n]=m[i]; //设置哨兵
for(int j=i-1;(r[n]>r[j])&&(j>=0);j--)//寻找插入位置
{
r[j+1]=r[j];//记录后移
m[j+1]=m[j];//记录后移
}
r[j+1]=r[n];
m[j+1]=m[n];
}
}
void Leijia(double p[], int s)//将当前概率及之前概率相加{
for(int r=1;r<s;r++)
p[r]=p[r-1]+p[r];
}
void main()
{
int geshu,erjinzhi[100][100];
int z=0,g=0;
double gailv[100],L[100];
char fuhao[100];
cout<<"请输入需要编码的字符个数(小于100)"<<endl; cin>>geshu;
cout<<"请按照先后顺序输入符号"<<endl;
for(int i=0;i<geshu;i++)
cin>>fuhao[i];
cout<<"请输入各相应符号的概率"<<endl;
for(int j=0;j<geshu;j++)
cin>>gailv[j];
InsertSort( gailv,fuhao, geshu);
for(z=0;z<geshu;z++)
{
L[z]=-log(gailv[z])/log(2);
L[z]=ceil(L[z]);//向上取整求所需要的位数
}
Leijia( gailv, geshu);
for( z=0;z<geshu;z++)//求相应的二进制编码
{
gailv[z]=gailv[z]-floor(gailv[z]);
for( g=0;g<L[z];g++)
{
if((gailv[z]*2)>=1)
{
erjinzhi[z][g]=1;
gailv[z]=(gailv[z]*2)-1;
}
else
{
erjinzhi[z][g]=0;
gailv[z]=gailv[z]*2;
}
}
}
cout<<"各信源符号及相应码字分别为"<<endl; for(z=0;z<geshu;z++)
{
cout<<fuhao[z]<<'\t';
for( g=0;g<L[z];g++)
cout<< erjinzhi[z][g];
cout<<endl;
}
}
程序运行结果:
程序操作步骤:
1.按照提示输入所要编码的符号个数并回车
2.按顺序输入要求个数的符号并回车
3.按顺序输入各符号相应的概率并回车
4.即可得到各符号相应的shannon编码
试验中遇到的困难及解决方法:
本次试验相对而言比较简单,但由于长时间没有联系C++语言有些生疏。
再进行按照概率从大到小顺序排列时刚开始只注意到了排列概率因此导致概率与符号不对应,因此修改了插入排序算法,将概率和相应符号同时进行排列。
求对数时没有注意对数底应为2(虽然以e为底也正确,但是基本上运算都是以2为底),于是加上了除以log(2)。
实验心得及体会:
通过本次试验我进一步熟悉使用C++编程语言及软件,充分理解认识shannon编码过程,对我今后的学习有一定的帮助。