zoukankan      html  css  js  c++  java
  • 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。由于全部的概率值均为正值。若67因此通过累积分布函数就能够得到相应的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("请输入概率值:
    ");
        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著

  • 相关阅读:
    如何在 Windows 7 安裝 SharePoint Server 2010
    SharePoint 2010 WSP包部署过程中究竟发生什么?
    SharePoint 2010 部署 WSP 包
    SharePoint 2010在win7 x64 安装
    在Sharepoint2010中发布VS2010开发的WebPart
    在User Profile Service中配置AD的同步连接
    Sharepoint数据库存储过程
    SharePoint对象模型性能考量
    对SharePoint 2007数据库中一些数据表的使用
    SharePoint Services 数据库表
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7212444.html
Copyright © 2011-2022 走看看