算术编码和解码程序实现_香农编码MATLAB实现

本文介绍了香农-范诺编码在数据压缩中的应用,这是一种基于符号概率构建前缀码的技术。与哈夫曼编码不同,香农-范诺编码确保码词长度在理想范围内。通过MATLAB实现,详细展示了如何进行香农编码的编码和解码过程。
摘要由CSDN通过智能技术生成

4d3696be655042e344dcbd0b2dd7789c.png

在数据压缩的领域里,香农-范诺编码(英语:Shannon–Fano coding)是一种基于一组符号集及其出现的概率(估量或测量所得),从而构建前缀码的技术。其名称来自于以克劳德·香农和罗伯特·法诺。在理想意义上,它与哈夫曼编码一样,并未实现码词(code word)长度的最低预期;然而,与哈夫曼编码不同的是,它确保了所有的码词长度在一个理想的理论范围

equation?tex=%7B%5Cdisplaystyle+%7B-%5Clog+%7Dp%28x%29%7D 之内。这项技术是香农于1948年,在他介绍信息理论的文章“通信数学理论”中被提出的。

这个方法归功于范诺,他在不久以后以技术报告发布了它。 香农-范诺编码不应该与香农编码混淆,后者的编码方法用于证明Shannon's noiseless coding theorem,或与Shannon–Fano–Elias coding(又被称作Elias coding)一起,被看做算术编码的先驱。

香农-范诺编码,符号从最大可能到最少可能排序,将排列好的信源符号分化为两大组,使两组的概率和近于相同,并各赋予一个二元码符号“0”和“1”。只要有符号剩余,以同样的过程重复这些集合以此确定这些代码的连续编码数字。依次下去,直至每一组的只剩下一个信源符号为止。当一组已经降低到一个符号,显然,这意味着符号的代码是完整的,不会形成任何其他符号的代码前缀。

0e3671ef4832fdf1f3550fb1c1550d8e.png
香农-范诺图解

上面介绍的编码方法即为最原始简单的香农-范诺编码。下面我们用MATLAB来实现香农编码。

p=randsample(100,10);    %随机生成10个数字
p=p/sum(p);              %归一化处理使之成为符号概率
p=sort(p,'descend');     %倒叙排列
len=length(p);
for i=1:len
    P(i)=sum(p(1:i))-p(i);
end
K=ceil(-log2(p));

for i=1:len
    code{i}='';
end

for i=1:len     
  while length(code{i})<K(i)
      if P(i)*2>=1
          code{i}=[code{i},'1'];
          P(i)=2*P(i)-1;
      else
          P(i)=2*P(i);
          code{i}=[code{i},'0'];
      end
  end
end
h=sum(p.*(-log2(p)));k_anv=sum(p.*K);eff=h/k_anv;

fprintf('%s     ','符号概率');fprintf('  %s    ','累加概率');
fprintf('%s   ','码字长度');fprintf('%s     n','香农编码');
for i=1:len
    fprintf('%f     ',p(i));
    fprintf(' %f      ',P(i));
    fprintf(' %d        ',K(i));
    disp(code{i});
end
fprintf('编码效率为%f',eff);

运行结果如下所示

c454fb6d7e356896acb2a1e91c533fec.png
算术编码是一种无损压缩算法,可以将任意长度的数据流压缩为一个较短的编码。而香农编码是一种基于概率的编码方法,可以使得出现概率较高的符号用较短的编码表示,出现概率较低的符号用较长的编码表示。 以下是算术编码香农编码MATLAB实现代码: 算术编码: ```matlab function [code,prob] = arith_encode(source,prob) % 初始化概率表 if nargin < 2 prob = ones(1,256)/256; end % 计算累积概率 cumprob = cumsum(prob); % 计算区间范围 low = 0; range = 1; for i = 1:length(source) symbol = source(i); % 更新区间范围 newlow = low + range*cumprob(symbol); newrange = range*prob(symbol); % 缩小区间范围 low = newlow; range = newrange; end % 输出编码和最终概率表 code = floor(low*2^32); prob(source(end)) = prob(source(end)) + 1; prob = prob/sum(prob); end ``` 香农编码: ```matlab function [code,len] = shannon_encode(source) % 计算概率表 prob = histcounts(source,0:256)/length(source); % 计算累积概率 cumprob = cumsum(prob); % 初始化编码表 code = cell(1,256); for i = 1:256 % 计算编码 if prob(i) > 0 len = ceil(-log2(prob(i))); code{i} = sprintf('%%0%dd',len); code{i} = sprintf(code{i},dec2bin(cumprob(i)*2^len-1,len)); end end % 输出编码和编码长度 len = cellfun(@length,code); end ``` 这两个函数分别实现算术编码香农编码。你可以将需要压缩的数据传入这两个函数,得到对应的编码和编码长度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值