• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

cynchanpin

  • 博客园
  • 联系
  • 订阅
  • 管理

View Post

Shannon-Fano-Elias编码的C语言实现

Shannon-Fano-Elias编码

一.理论分析

Shannon-Fano-Elias编码是利用累积分布函数来分配码字。

不失一般性,假定取X={1,2,…m}。如果对于全部的x,有p(x)>0。定义累积分布函数F(X)为 1
其函数图形见下图所看到的。修正的累积分布函数为2当中3表示小于x的全部字符的概率和加上字符x概率的一般得到的值。由于随机变量是离散的,故累积分布函数所含的阶梯高度为p(x)。函数4的值恰好与x相应的那个阶梯的中点。
5

我们如今要确定6的唯一性,这样才干保证能够相应到相应的x。由于全部的概率值均为正值。若6则7因此通过累积分布函数就能够得到相应的X。但普通情况下8为十进制小数。要表示为二进制小数须要非常多比特位,(在编码实现的过程中要注意此处。若是C语言实现,要注意存储二进制比特位的数组的长度。此处极易发生数组越界)这在现实的编码中是并不可行的。因此我们须要取一个精度,究竟精确到哪一位呢?9取到l(x)位就可以。

二.编码实现

Shannon-Fano-Elias编码是用C语言来实现的。
code数组的长度建议定的大一些,此处极易发生数组越界(这都是血的教训啊….)
主要的结构体例如以下:

typedef struct  
{
    double px;   //px概率值
    double Fx;   //fx函数值
    double Fbax; //Fba(X)的值
    int   lx;   //编码的长度
    int code[A]; //存储二进制比特
}SFE;

1.初始化结构体,输入p(x)

void init_code(int code[],int i)
{
    int j;
    for (j=0;j<A;j++)
        code[j] = 0;
}



void init_px(SFE SFEA[],int length)//初始化px
{
    printf("请输入概率值:\n");
    int i;
    for(i=1;i<=length;i++)
    {
        scanf("%lf",&SFEA[i].px);
        init_code(SFEA[i].code,i);

    }
}

2.计算fx累积分布函数

void count_fx(SFE SFEA[],int length)//计算fx累积分布函数
{
    double sum =0;
    int i,j;
    for (i=1;i<=length;i++)
    {
        for (j=1;j<=i;j++)
        {
            sum = sum + SFEA[j].px;

        }
        SFEA[i].Fx = sum;
        sum = 0;

    }

}

3.计算10

void count_fbax(SFE SFEA[],int length)//计算fbax的函数值
{
    int i,j;
    double sum = 0;
    for (i=1;i<=length;i++)
    {
        if (i==1)
        {
            SFEA[i].Fbax = SFEA[i].px/2.0;
        }
        else
        {
            for (j=1;j<i;j++)
            {
                sum = sum + SFEA[j].px;
            }
            SFEA[i].Fbax = sum + SFEA[i].px/2.0;
            sum = 0;

        }
    }

}

4.计算lx的长度。lx向上取整

void count_lx(SFE SFEA[],int length)//计算lx的长度,lx向上取整
{
    int i;
    for (i=1;i<=length;i++)
    {
        SFEA[i].lx = ceil(log(1/SFEA[i].px)/log(2))+1;
    }
}

5.转化为二进制比特位

void decimal(double m,int code[])
{
    int *p = code;
    if(m>ZERO)
    {
        m=m*NUM;

        *p = (long)m;
        p++;
        decimal(m-(long)m,p);
    }
}




void f_binary(SFE SFEA[],int length)
{
    int i;
    for (i=1;i<=length;i++)
    {
         decimal(SFEA[i].Fbax,SFEA[i].code);
    }
}

整个编码过程至此结束,由于数组操作比較多。所以要注意防止数组越界。

三.编码结果分析
1.先给出一个样例,其十进制小数均能够转化为有限位数的二进制小数。
11

2.这个样例中二进制小数表示可能为无线位数的小数,開始的时候我将code数组的大小定义为20,运行完1中都非常正常,到了这个样例,一直不停的发生数组越界,原因是由于,此例中二进制表示可能有无穷位数字。如果先转化二进制。再编码表示的话,code数组的长度要足够长。当然,你也能够仅仅存储到l(x)位。

这样就不用那么大的空间了。


12

源码下载地址:shannon-fanon-elias编码C语言实现

Reference:
信息论基础.Thomas M.Cover Joy A.Thomas著

posted on 2017-07-20 17:32  cynchanpin  阅读(1143)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3