一、算术编码的主要思想
计算输入信源符号序列所对应的区间,然后在区间中任取一点,以其二进制表示适当截断作为序列的编码结果。
二、算术编码的原理
设输入信源序列为
如下图所示,初始时,区间长度为[0,1)。其由F (1)分为[0,𝐹(1))和[𝐹(1),1)两个区间。两个区间的宽度分别为W (0)=P (0)和W (1)=P (1),分别对应信源符号0和1。假设第一个信源符号为0,序列落入区间[0,𝐹(1)) 中。假设信源第二个符号为1,则序列落入的区间则为[𝐹(0)+𝑊(0) P (0) ,𝐹(1))。将上述区间按概率划分成两个区间,宽度分别为P (010) 和P (011) ,区间的分割线为F(01)+W(01) P (0) 。
以此类推,可得到以下递推关系:
最终序列𝒖对应的区间为[𝐹(𝒖),𝐹(𝒖)+𝑃(𝒖))。取该区间的任意值即可得到算术编码的结果。
编码示例:
设离散无记忆信源U={𝑎1,𝑎2,𝑎3,𝑎4},其概率分布为𝑃(𝑎1 )=0.5,𝑃(𝑎2 )=0.25,𝑃(𝑎3 )=0.125,𝑃(𝑎4 )=0.125,试对序列u=𝑎2 𝑎1𝑎1𝑎3𝑎4进行算术编码。
解:
三、算术编码的译码原理
算术编码的译码过程就是一系列的比较过程,主要有两个方法:
1、逐渐逼近算术编码结果最接近的区间,通过确定区间下限来确定算术码中的消息序列。如下图所示:
译码例子:
设离散无记忆信源U={𝑎1,𝑎2,𝑎3,𝑎4},其概率分布为𝑃(𝑎1 )=0.5,𝑃(𝑎2 )=0.25,𝑃(𝑎3 )=0.125,𝑃(𝑎4 )=0.125,已知信源u总共由5个字符组成,其算术编码的结果为0.5537109375,试根据算术编码结果求出原序列u。
解:我们将[0-1)区间按照𝑎1,𝑎2,𝑎3,𝑎4出现的概率分为4段: [0~1/2), [1/2 ~3/4), [3/4 ~7/8), [7/8 ~1)。由于待解码的数据0.5537109375在[1/2,3/4)区间内,因此解出的第一个码值为𝑎2,同时0.5537109375在[1/2,3/4)区间的前50%内因此解出的第二个码值为𝑎1,此时区间变为[1/2,5/8),由于0.5537109375在[1/2,5/8)区间的前50%内,故解出的第三个码值为𝑎1,此时区间变为[1/2,9/16),以此类推直至全部解码。
2、每次确定其所在的区间,然后改变算术码,使得每次比较的算术码都是相对于当前区间的码值。如下图所示:
译码例子:设离散无记忆信源U={𝑎1,𝑎2,𝑎3,𝑎4},其概率分布为𝑃(𝑎1 )=0.5,𝑃(𝑎2 )=0.25,𝑃(𝑎3 )=0.125,𝑃(𝑎4 )=0.125,已知信源u总共由5个字符组成,其算术编码的结果为0.5537109375,试根据算术编码结果求出原序列u。
解:我们将[0-1)区间按照𝑎1,𝑎2,𝑎3,𝑎4出现的概率分为4段: [0~1/2), [1/2 ~3/4), [3/4 ~7/8), [7/8 ~1)。由于待解码的数据0.5537109375在[1/2,3/4)区间内,因此解出的第一个码值为𝑎2,首先去掉𝑎2的下界0.5,得0.0537109375,然后利用𝑎2的范围range=0.25除0.0537109375得到0.21484375。其所在的区间为 [0-1/2),故第二个码字为 𝑎1。去掉𝑎1的下界值0后,得到0.21484375,然后利用𝑎1的范围range=0.5除0.21484375得0.4296875。其所在区间为[0-1/2),故第三个码字为 𝑎1。以此类推直至全部译码。
四、算术编译码的MATLAB实现
流程图如下:
五、遇到的问题及解决
在算术编码中,当序列长度很长时,会出现下溢误差(underflow)。计算机中浮点数都是离散的,有限的。因此计算机无法用有限的浮点数来表示无限的实数。在用浮点数表示实数时,很多数都会存在近似误差。当数值过小时(趋近于0,但大于0),计算机会将其判为0,因此造成underflow。可通过digits和vpa函数提高数值的精度,从而避免下溢误差(underflow)。