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("请输入概率值:\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著

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值