算术编码Word文件下载.docx
《算术编码Word文件下载.docx》由会员分享,可在线阅读,更多相关《算术编码Word文件下载.docx(8页珍藏版)》请在冰豆网上搜索。
(a)编码器将“当前间隔”分为子间隔,每一个事件一个
(b)—个子间隔的大小与下一个将出现的事件的概率成比例,编码器选择
子间隔对应于下一个确切发生的事件相对应,并使它成为新的“当前间
隔”。
(3)最后输出的“当前间隔”的下边界就是该给定事件序列的算术编码
编码过程
假设信源符号为{A,B,C,D},这些符号的概率分别为{0.1,0.4,0.2,0.3},根据这些概率可把间隔[0,1]分成4个子间隔:
[0,0.1],[0.1,0.5],[0.5,0.7],[0.7,1],其中[x,y]表示半开放间隔,即包含x不包含y。
上
面的信息可综合在表03-04-1中。
F表为信源符号,概率和初始编码间隔
符号
A
B
C
D
概率
0.1
0.4
0.2
0.3
初始编码间隔
[0,
0.1)[0.1,0.5)
[0.5,0.7)
[0.7,1]
如果二进制消息序列的输入为:
CADACDB。
编码时首先输入的符号
是C,找到它的编码范围是[0.5,0.7]。
由于消息中第二个符号A的编码范围是[0,0.1],因此它的间隔就取[0.5,0.7]的第一个十分之一作为新间隔[0.5,0.52]依此类推,编码第3个符号D时取新间隔为[0.514,0.52],编码第4个符号A时,取新间隔为[0.514,0.5146],…。
消息的编码输出可以是最后一个间隔中
的任意数。
整个编码过程如图03-04-1所示。
编码和译码的全过程分别表示在下表。
步骤
输入符号
编码间隔
编码判决
1
[0.5,0.7]
符号的间隔范围[0.5,0.7]
2
[0.5,0.52]
[0.5,0.7]间隔的第一个1/10
3
[0.514,0.52]
[0.5,0.52]间隔的最后一个1/10
4
[0.514,0.5146]
[0.514,0.52]间隔的第一个1/10
[0.5143,
[0.514,0.5146]间隔的第五个1/10开始,
5
0.51442]
二个1/10
6
[0.514384,
[0.5143,0.51442]间隔的最后3个1/10
[0.5143836,[0.514384,0.51442]间隔的4个1/10,从
7B
0.514402]第1个1/10开始
译码过程
间隔
译码符号
译码判决
0.51439在间隔[0.5,0.7)
0.51439在间隔[0.5,0.7)的第1个
1/10
[0.514,
0.51439在间隔[0.5,0.52)的第7个
0.52]
0.51439在间隔[0.514,0.52]的第1个
0.5146]
0.51439在间隔[0.514,0.5146]的第5
个1/10
0.51439在间隔[0.5143,0.51442]的第
7个1/10
[0.51439,
0.51439在间隔[0.51439,0.5143948]
7
0.5143948]
的第1个1/10
8
译码的消息:
CADACDB
五、实验设计:
算术编码是一种无损数据压缩方法,也是一种熵编码的方法。
和其它熵编码方法不同的地方在于,其他的熵编码方法通常是把输入的消息分割为符号,然后
对每个符号进行编码。
而算术编码是直接把整个输入的消息编码为一个数,一个满足(0.0<
n<
1.0)的小数n。
所以用两个基本的参数:
符号的概率和它的编码间隔。
信源符号的概率决定压缩编码的效率,也决定编码过程中信源符号的间隔,而这些间隔包含在0到1之间。
算术编码的算法思想如下:
(1)对一组信源符号按照符号的概率从大到小排序,将[0,1)设为当前分析区间。
按信源符号的概率序列在当前分析区间划分比例间隔。
(2)检索“输入消息序列”,锁定当前消息符号(初次检索的话就是第一个消
息符号)。
找到当前符号在当前分析区间的比例间隔,将此间隔作为新的当前分
析区间。
并把当前分析区间的起点(即左端点)指示的数“补加”到编码输出数里。
当前消息符号指针后移。
(3)仍然按照信源符号的概率序列在当前分析区间划分比例间隔。
然后重复第
二步。
直到“输入消息序列”检索完毕为止
(4)最后的编码输出数就是编码好的数据。
六、实验程序:
#include<
iostream.h>
#include"
math.h"
//定义所需要用到的变量及数组
charS[100],A[10];
floatP[10],f[10],gFs;
//编码程序
voidbianma(inta,inth)
{
inti,j;
floatfr;
floatps=1;
floatFs=0;
Fs中
floatSp[100],b[100],F[100];
//以待编码的个数和字符个数为循环周期,将待编码的字符所对应的概率存入到
for(i=0;
i<
h;
i++)
for(j=0;
j<
a;
j++)
Sp[i]=P[j];
fr=f[j];
//将划分好的[0,1)区间的对应点赋值给
}
不断的进行这个过程,
Fs=Fs+ps*fr;
//从选择的子区间中继续进行下一轮的分割。
直到所有符号编码完毕。
ps*=Sp[i];
//求Ps
cout<
<
"
Fs="
Fs<
endl;
//显示最终的算术编码gFs=Fs;
floatl=log(1/ps)/log
(2);
//计算算术编码的码字长度lif(l>
(int)l)l=(int)l+1;
elsel=int(l);
//将Fs转换成二进制的形式
intd[20];
intm=0;
while(l>
m)
Fs=2*Fs;
if(Fs>
1)
Fs=Fs-1;
d[m]=1;
elseif(Fs<
1)d[m]=0;
else{d[m]=1;
break;
m++;
给二进制数加1
intz=m;
//解决有关算术编码的进位问题
if(m>
=l)
while
(1)
d[m-1]=(d[m-1]+1)%2;
//最后位加
if(d[m-1]==1)break;
s="
;
for(inte=0;
e<
z;
e++)
d[e];
//解码程序
voidjiema(inta,inth)
floatFt,Pt;
floatFs=0,Ps=1;
i++)//以编码个数和符号个数为循环周期,对其进行解码
for(intj=a-1;
j>
-1;
j--)
Ft=Fs;
Pt=Ps;
Ft+=Pt*f[j];
//对进行逆编码
Pt*=P[j];
if(gFs>
=Ft)//对其进行判断,并且将值存入到数组A中
Fs=Ft;
Ps=Pt;
A[j];
voidmain()