基于Python实现的费诺编码


前言:学习信息论与编码时想实现费诺编码,遇到点困难,上网搜索无果,却突然开窍,所以写一篇仅供各位朋友参考。

基于Python实现的费诺编码

(一)费诺编码原理及过程

1.原理

费诺码是按照累加概率(如不知参考下列例子就一目了然)尽可能相等的原则对信源符号进行分组,对于二元码,每次分为两组;对于n元码,则每次分为n组,并且给不同的组分配一个不同地码元符号。
注:本文章过程叙述、例子及具体实现代码为二元码

2.过程

若采用二元码,则编码步骤为:
(1)将信源符号按其出现的概率大小从大到小依次排列。
(2)将依次排列的信源符号分为两组,使两个组的概率之和尽可能近似相等,并将各组分别赋予一个二进制码元“0”和“1”。
(3)将每一组的信源符号再分为两组,使划分后的两个组的概率之和尽可能近似相等,并将各组分别赋予一个二进制码元“0”和“1”。
(4)如此重复,直至每个组只剩下一个信源符号为止。

Talk is cheap. Show me the code.

import math
def Group(probabilitySpace,encodeSpaceDictionary):    	
	if(len(probabilitySpace)==1):#当分组只有一个时不应再继续分组和编码,退出        
		return    
	#通过累加概率尽可能相等原则找到分组最佳位置    
	groupProbability=1    
	findPosition=-1    
	for i in range(len(probabilitySpace)):        
		tempSum1=0        
		tempSum2=0        
		for j in range(i):            
			tempSum1=tempSum1+probabilitySpace[j]                
			for j in range(i,len(probabilitySpace)):            
				tempSum2=tempSum2+probabilitySpace[j]        
				if(abs(tempSum1-tempSum2)<groupProbability):           
					groupProbability=abs(tempSum1-tempSum2)            
					findPosition=i    
	#通过累加概率尽可能相等原则找到分组最佳位置    
	#编码                
	str0,str1="0","1"    
	for i in range(len(probabilitySpace)):
		if(i<findPosition):
			tempDictionaryElement={probabilitySpace[i]:encodeSpaceDictionary[probabilitySpace[i]]+str0}
			encodeSpaceDictionary.update(tempDictionaryElement)
		else:
			tempDictionaryElement={probabilitySpace[i]:encodeSpaceDictionary[probabilitySpace[i]]+str1}
			encodeSpaceDictionary.update(tempDictionaryElement)   
	#编码
	#分组
	leftGroup=[]
	rightGroup=[]
	for j in range(findPosition):
		leftGroup.append(probabilitySpace[j])
	for j in range(findPosition,len(probabilitySpace)):
		rightGroup.append(probabilitySpace[j])
	#分组
	#递归分组编码
	Group(leftGroup,encodeSpaceDictionary)
	Group(rightGroup,encodeSpaceDictionary)
	#递归分组编码
	return(encodeSpaceDictionary)#返回编码空间
def Fano(probabilitySpace=[0.2,0.19,0.18,0.17,0.15,0.1,0.01]):
	probabilitySpace.sort()
	probabilitySpace.reverse()
	encodeSpaceDictionary={}#编码空间
	#初始化编码空间
	for i in range(len(probabilitySpace)):
		tempDictionaryElement={probabilitySpace[i]:""}
		encodeSpaceDictionary.update(tempDictionaryElement)
	#初始化编码空间
	Result=Group(probabilitySpace,encodeSpaceDictionary)
	i=1
	for p in Result:
		print("消息符号a{}对应码字为:{}".format(i,Result[p]))
		i+=1
	#求平均码长
	averageL=0
	listResult=list(Result)
	for p in listResult:
		averageL=averageL+len(Result[p])*p
		print("平均码长为:{:.3}比特/符号".format(averageL))
	#求平均码长
	#求编码效率
	H=0
	for i in range(len(probabilitySpace)):
		H=H+probabilitySpace[i]*math.log2(probabilitySpace[i])
		H=-H
		print("编码效率为:{:.3%}".format(H/averageL))
	#求编码效率
	return(Group(probabilitySpace,encodeSpaceDictionary))
def typeInFano():
	while(True):
		try:
			mode=eval(input("是否输入概率空间?(否为默认概率空间)->({}:是 or {}:否):".format(1,2)))
			if mode==1 or mode==2:
				break
			else:
				print("!!!请按格式输入.")
		except:print("!!!请按格式输入.")
		if(mode==1):
			print("!!!输入'.'结束")
			i=1
			typeIn=[]
			while(True):
				while(True):
					try:
						tempTypeIn=input("请输入第{}个参数:".format(i))
						if(tempTypeIn=="."):
							break
							typeIn.append(eval(tempTypeIn))
							i=i+1                
					except:
						print("!!!请输入数字或'.'")
						sum=0
				for i in range(len(typeIn)):
					sum=sum+typeIn[i]
					if(sum!=1):
						print("!!!概率空间和不为1请重新输入.")
						i=1
					else:
						Fano(typeIn)
						break
		if(mode==2):
			Fano()
if __name__=="__main__":    
	typeInFano()

测试结果

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值