一、设计目标
实现任意Q符号信源的二进制香农编码,其中Q>10且由用户自行输入,信源的概率分布也由用户输入。展示编码结果、平均码长、信源熵、编码效率。
二、设计步骤
(1)输入模块:实现对Q和信源概率数组(odds)的输入,并对其作出判断:Q是否满足大于10、概率数组长度是否为Q、概率和是否为1;
(2)编码模块:
①对概率进行排序;
②求取各概率P(xi)的香农编码码字长度;
③求取累积Pi概率;
④通过累积概率求取各符号的码字;
(3)输出模块:打印编码结果和编码效率等参数。
三、代码实现
%%shannon code
%%输入Q值并判断
while(1)
Q = input("请输入Q的值(Q>10): ");
if(Q <= 10)
disp('不满足Q>10的条件,请重新输入Q值!');
else
break;
end
end
%%输入Q个元素的概率并判断
%%提供待测数组Q=11:[0.1274 0.1416 0.0199 0.1428 0.0989 0.0152 0.0435 0.0855 0.1497 0.1509 0.0246]
while(1)
odds = input("请以数组形式[]输入Q个元素各自的概率(p>0):");
length_odds = length(odds);
if(length_odds ~= Q)
disp('输入概率个数错误(不为Q),请重新输入!');
elseif(sum(odds) ~= 1)
disp(['概率之和为:',num2str(sum(odds))]);%%帮助概率纠错
disp('输入概率数值有误,请重新输入!');
else
break;
end
end
%%对概率进行排序并求计算累积概率
[sort_odds , sort_index] = sort(odds , 'descend');%%分别为排序后的概率与最初的索引
odds_log2 = -log2([sort_odds]);
length_shannon = ceil(odds_log2);%%求得二进制代码组的长度
p = zeros(1,11);%%累积概率
for i = 2 : Q
p(i) = sum(sort_odds(1 : (i - 1)));
end
%%编码
%%思路:将原本的积累概率乘2^L(即将二进制小数左移L位),可直接取整数部分的二进制值
%%过长的码字从截取最右端L位
shift_p = p.*(2.^length_shannon);%%移位后的值
shift_p_bin = dec2bin(shift_p);%%二进制结果,得到Q*Lmax char数组,可用shift_p_bin(i,:)调用
shannon_code = [];%%编码结果
for j = 1 : Q
l1 = length_shannon(j);
l2 = length(shift_p_bin(j,:));%%待截取码字长度
code = shift_p_bin(j,:);%%待截取码字
shannon_code = [shannon_code , str2num(code(l2-l1+1 : l2))];
end
%%编码结果打印
disp('--------------------------------------');
disp('香农编码结果:');
len_shannon = 0;
for k = 1 : Q
index = sort_index(k);
num = num2str(index);
od = num2str(sort_odds(k));%%字符串形式的概率
co = num2str(shannon_code(k));%%字符串形式的编码
len_shannon = len_shannon + length_shannon(k)*sort_odds(k);
if(length(co) ~= length_shannon(k))
num_0 = length_shannon(k) - length(co);%%需要补充的0的个数
for ii = 1 : num_0
co = ['0',co];
end
end
disp(['第',num,'个符号的概率为:',od,',香农编码为:',co]);
end
%%编码参数计算与展示
l = len_shannon;%%平均码长
H = sum(odds.*log2(1./odds));%%熵
eff = H / (l*log2(2));%%编码效率
disp('--------------------------------------');
disp(['平均码长:',num2str(l)]);
disp(['信源熵:',num2str(H)]);
disp(['编码效率:',num2str(eff)]);
四、运行结果
此处以提供的待测数组为测试对象:
五、总结
(1)Q的取值范围可根据代码最前段自行更改;
(2)概率和是否为1的判断可以删去,因为有时候会无故报错(我也不知道为啥);
(3)作者编程水平有限,希望为读者能提供一定帮助。