正文

香农编码2006-09-20 20:52:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/rickone/18604.html

分享到:

今天的作业,想到可以直接由浮点数格式中取出尾数得到ShannanCode,麻烦点的地方是需要重新对阶,因为在尾数规格化省掉了一位,最终效率比较高。 #ifndef SHANNAN_CODE_DEF_200609#define SHANNAN_CODE_DEF_200609typedef unsigned long U32;typedef signed char S8;class CShannan{ float *m_p;//消息概率 float *m_sp;//累计概率P float *m_i;//信息量 int *m_length;//码长 U32 *m_code; int m_n;public: static int cpux86();public: CShannan(int n); ~CShannan(); void InputPro(); void OutputCode();};#endif   #include "stdio.h"#include "assert.h"#include "math.h"#include "shannan.h"#ifndef NULL#define NULL 0#endifCShannan::CShannan(int n){ assert(n>0); m_n=n; m_p=new float[n]; m_sp=new float[n]; m_i=new float[n]; m_length=new int[n]; m_code =new U32[n]; assert(m_p!=NULL); assert(m_sp!=NULL); assert(m_i!=NULL); assert(m_length!=NULL); assert(m_code!=NULL);}CShannan::~CShannan(){ if(m_p)  delete[]m_p; if(m_sp)  delete[]m_sp; if(m_i)  delete[]m_i; if(m_length)  delete[]m_length; if(m_code)  delete[]m_code;}int CShannan::cpux86(){ union {  char a[2];  short int b; }test; test.b=1; if(test.a[0]==1)  return 1;//低位在前 return 0;//高位在前 //test needed}void CShannan::InputPro(){ float last=1.0f; int i; for(i=0;i<m_n-1;++i) {  while(1)  {   printf("输入第%d个消息概率:",i+1);   scanf("%f",m_p+i);   if(m_p[i]<last)   {    last-=m_p[i];    break;   }   else   {    printf("错误,输入概率值必须小于%.4f\n",last);   }  } } m_p[m_n-1]=last; printf("第 %3d 个消息概率值为 %.4f\n开始香农编码...\n",m_n,last); //Shannan Code //Sort for(i=0;i<m_n;++i) {  for(int j=i+1;j<m_n;++j)  {   if(m_p[j]>m_p[i])   {    float tmp=m_p[i];    m_p[i]=m_p[j];    m_p[j]=tmp;   }  } } float a=(float)(-1.0/log(2.0)); for(i=0;i<m_n;++i) {  m_sp[i]=i>0?m_sp[i-1]+m_p[i-1]:0.0f;  float inf=(float)(a*log(m_p[i]));  m_i[i]=inf;  m_length[i]=(int)inf;  if((float)m_length[i]<inf)   ++m_length[i]; } //由IEEE-754浮点数存储格式标准,直接由累加概率值中取出CODE for(i=0;i<m_n;++i) {  U32 *d=(U32*)(m_sp+i);  S8 move=(S8)(((((*d) >> 23) & 0xFF) + 0x1) ^ 0x80);//得到移阶码对应的补码,单精度型的偏移量是0x7F   m_code[i]=(((*d) & 0x7FFFFF) | 0x800000) >> (-move-1);//补上隐含位并对阶后的尾数 } //End Code printf("编码完毕!\n");}void CShannan::OutputCode(){ printf("-=-=-=-=-=-=-\n香农编码结果:\n-=-=-=-=-=-=-\n"); printf("消息序号si  消息概率p(si)  累加概率Pi  -log p(si)  代码组长度li  二进制代码组\n"); for(int i=0;i<m_n;++i) {  printf("    s%-5d     %-10.4f    %-8.4f    %-8.4f       %-7d  ",i+1,m_p[i],m_sp[i],m_i[i],m_length[i]);  for(int j=0;j<m_length[i];++j)  {   if((m_code[i] >> (23-j)) & 0x1)    printf("1");   else    printf("0");  }  printf("\n"); }} #include "shannan.h"#include <stdio.h>int main(){ int n; printf("输入消息符号个数N:"); scanf("%d",&n); CShannan scode(n); scode.InputPro(); scode.OutputCode(); return 0;} 运行结果: 输入消息符号个数N:7输入第1个消息概率:0.2输入第2个消息概率:0.1输入第3个消息概率:0.01输入第4个消息概率:0.9错误,输入概率值必须小于0.6900输入第4个消息概率:0.19输入第5个消息概率:0.18输入第6个消息概率:0.15第   7 个消息概率值为 0.1700开始香农编码...编码完毕!-=-=-=-=-=-=-香农编码结果:-=-=-=-=-=-=-消息序号si  消息概率p(si)  累加概率Pi  -log p(si)  代码组长度li  二进制代码组    s1         0.2000        0.0000      2.3219         3        000    s2         0.1900        0.2000      2.3959         3        001    s3         0.1800        0.3900      2.4739         3        011    s4         0.1700        0.5700      2.5564         3        100    s5         0.1500        0.7400      2.7370         3        101    s6         0.1000        0.8900      3.3219         4        1110    s7         0.0100        0.9900      6.6439         7        1111110 参考:单双精度浮点数的IEEE标准格式

阅读(23074) | 评论(5)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册