算术编码与解码

  • 格式:docx
  • 大小:19.72 KB
  • 文档页数:3

下载文档原格式

  / 9
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

算术编码与解码

1、编码过程

算术编码方法是将被编码的一则消息或符号串(序列)表示成0和1之间的一个间隔(Interval),即对一串符号直接编码成[0,1]区间上的一个浮点小数。符号序列越长,编码表示它的间隔越小,表示这一间隔所需的位数就越多。信源中的符号序列仍然要根据某种模式生成概率的大小来减少间隔。可能出现的符号概率要比不太可能出现的符号减少范围小,因此,只正加较少的比特位。

在传输任何符号串之前,0符号串的完整范围设为[0,1]。当一个符号被处理时,这一范围就依据分配给这一符号的那一范围变窄。算术编码的过程,实际上就是依据信源符号的发生概率对码区间分割的过程。

输入:一个字符串

输出:一个小数

考虑某条信息中可能出现的字符仅有a b c 三种,要压缩保存的信息为bccb。

假设对a b c 三者在信息中的出现概率一无所知(采用自适应模型),暂时认为三者的出现概率相等,也就是都为1/3,将0 - 1 区间按照概率的比例分配给三个字符,即a 从0.0000 到0.3333,b 从0.3333 到0.6667,c 从0.6667 到 1.0000。用图形表示就是:

+-- 1.0000 | Pc = 1/3 | | +-- 0.6667 | Pb = 1/3 | | +-- 0.3333 | Pa = 1/3 | | +-- 0.0000

对于第一个字符b,选择b 对应的区间0.3333 - 0.6667。这时由于多了字符b,三个字符的概率分布变成:Pa = 1/4,Pb = 2/4,Pc = 1/4。再按照新的概率分布比例划分0.3333 - 0.6667 这一区间,划分的结果可以用图形表示为:

+-- 0.6667 Pc = 1/4 | +-- 0.5834 | | Pb = 2/4 | | | +-- 0.4167 Pa = 1/4 | +-- 0.3333

接着字符c,上一步中得到的 c 的区间0.5834 - 0.6667。新添了c 以后,三个字符的概率分布变成Pa = 1/5,Pb = 2/5,Pc = 2/5。用这个概率分布划分区间0.5834 - 0.6667:

+-- 0.6667 | Pc = 2/5 | | +-- 0.6334 | Pb = 2/5 | | +-- 0.6001 Pa = 1/5 | +-- 0.5834

现在输入下一个字符c,三个字符的概率分布为:Pa = 1/6,Pb = 2/6,Pc = 3/6。划分c 的区间0.6334 - 0.6667:

+-- 0.6667 | | Pc = 3/6 | | | +-- 0.6501 | Pb = 2/6 | | +-- 0.6390 Pa = 1/6 | +-- 0.6334

输入最后一个字符b,因为是最后一个字符,不用再做进一步的划分了,上一步中得到的 b 的区间为0.6390 - 0.6501,好,让我们在这个区间内随便选择一个容易变成二进制的数,例如0.64,将它变成二进制0.1010001111,去掉前面没有太多意义的0 和小数点,我们可以输出1010001111,这就是信息被压缩后的结果,我们完成了一次最简单的算术压缩过程。我的代码:

publicstaticvoidBianMa(String info,StringDeal sd){

int i = 0, j = 0;

//定义上下限

double low = 0, high = 1;

double count = sd.getCount();

//定义初始各字符频率

double[] zifu = new double[(int)(count)];

for(i = 0;i < zifu.length;i++){

zifu[i] = 1;

}

String deal = sd.getDeal();

for(i = 0;i < info.length();i++){

//得到频率范围

double cha = high - low;

double sa = 0;

for(j = 0; j < deal.length(); j++){

//sa表示频率上限分子

sa += zifu[j];

//sb表示频率下限分子

double sb = sa - zifu[j];

if(info.charAt(i) == deal.charAt(j)){

//得到新的上限

high = low + sa/count * cha;

//得到新的下限

low = low + sb/count*cha;

zifu[j]++;

}

} //重置sa为0

sa = 0;

//频率分母

count++; }

shu = (low+high)/2;

System.out.println(shu);

}

2、解码过程

解码是编码的逆过程,对应每个频率范围,若输入位于某各字符的频率范围之内,则将该字符记录,并得到新的上下限。

我的代码:

publicstaticvoid JieMa(StringDeal sd,double shu){

//定义上下限

double low = 0, high = 1;

double count = sd.getCount();

int j = 0, i =0;

String deal = sd.getDeal();

//定义一个初始字符串存储译码结果

String info = "";

//字符初始字符量设置为1

double[] zifu = newdouble[(int)(count)];

for(i = 0;i < zifu.length;i++){

zifu[i] = 1;

}

while((low+high)/2 != shu){

//定义上下限