信息论与编码第一次作业
通信系统的各种信源中,离散随机信源是最基本的一种信源,信源输出是单个的符号的消息,
并且消息之间是两两互不相容的。本设计要求深刻理解信源熵的计算方法。
具体内容为:
(1)输入一个文件,首先对文件中的字符总个数进行统计(忽略大小写),然后从文本头开
始查找同一字符个数,并计算其概率最后由得出的字符概率求得信源熵。
答:已知信源熵的计算公式如下:
i
XH
)(
xIxp
(
i
现在在文件 C.TXT 中存入如下字符:
i
()
i
)
xp
(
i
)
log
xp
(
i
)
可知:
Y
yp
)(
,
a
5.0
b
5.0
YH
)(
5.0
log
5.0
5.0
log
5.0
符号/比特1
现在用 C 语言计算其信源熵,结果如下:
(2)比较多个文件的熵,总结熵的特点。
解:现在比较 a.txt、b.txt、c.txt 文件的信源熵,三个文件的内容如下:
用程序计算三个文件的信源熵,结果如下:
文件 a.txt 的信源熵为 3 比特/符号
文件 b.txt 的信源熵为 2 比特/符号
文件 c.txt 的信源熵为 1 比特/符号
总结:由上面的计算结果可知 H(a)>H(b)>H(c),由此可见,当信源的熵越大,该信源的不确定
度越大。
C 语言程序代码如下:
#include
#include
#include
#include
FILE *fp1; //定义文件
char fname[10];//文件名变量
int alpha[26]={0};//用于存储个字符的个数
double H;//信源熵的计算结果
void openfile(void)
{
//函数 1:打开用于输出的文件
printf("输入要读的文件名");
gets(fname);
if((fp1=fopen(fname,"r"))==NULL)
{
printf("不能打开文件,按任意键退出");
getchar();
exit(0);
}
}
int *statis(void)
//函数 2:统计字符
{
char ch;
int j;
int sum1;
while((ch=getc(fp1))!=EOF)//逐个读取文件中的字符
{
if(ch>='A'&&ch<='Z') ch=tolower(ch);//将大写转换为小写
if(ch>='a'&&ch<='z') alpha[ch-'a']++; //统计各个字母的数量
}
fclose(fp1); //关闭文件
//打印统计结果
printf("文件中各个字符的个数如下:\n\n");
for(j=0;j<26;j++) {
if(j>0&&j%4==0) printf("\n");
//每打印四个换行
printf("%c:%d ",(j+'a'),alpha[j]);//打印每个字符对应的个数
}
printf("\n");
for(int x=0;x<26;x++)
{
sum1=sum1+*(alpha+x);
//
}
printf("文件的字符总数为:%d\n",sum1);
return alpha;//将统计结果返回
}
double source_entropy(int *a)//函数 3:计算信源熵
{
double y[26],sum;
for(int i=0;i<26;i++)//统计文件字符的个数
{
sum=sum+a[i];
}
printf("\n");
printf("文件的字符总数等于%.0f\n",sum);
printf("\n 计算每个字符出现的概率如下:\n");
for(int i=0;i<26;i++)
{
if(i>0&&i%4==0) printf("\n");//每打印 4 个换行
y[i]=a[i]/sum;
//计算每个字符出现的概率
printf("%c:%f
",(i+'a'),y[i]);//打印各个字符出现的概率
}
printf("\n");
for(int i=0;i<26;i++)
{
if(y[i]>0) H=H-y[i]*(log(y[i])/log(2));//求信源熵
}
return H;//将计算的信源熵返回
}
//主函数
int main(int argc, char *argv[])
{
double HX;
openfile(); //打开文件
HX=source_entropy(statis());//计算文件的信源熵
printf("\n 文件字符的信源熵为%.2f 比特/符号\n\n",HX);
return 0;
}