关于Arithmetic Coding Algorithm的Java实现两大技术疑问
算术编码实现疑问解答
问题1:字符映射与累积频率索引越界问题
你混淆了原始字符的ASCII值和算术编码中使用的符号索引。原论文里的算术编码实现,会先对输入的字符集做一步映射:
- 先统计所有出现的唯一字符,给每个字符分配一个从1开始的连续整数ID(比如47个唯一字符就分配1~47)。
cum_freq数组的长度是唯一字符数+1,其中cum_freq[0]是所有字符的总频率,cum_freq[i]对应第i个映射后符号的累积频率。
所以表达式里的symbol是这个映射后的ID,不是原始字符的ASCII值。比如ASCII为85的'U',如果是字母表里的第20个唯一字符,那它对应的symbol就是20,此时cum_freq[19]是存在的,不会出现索引越界的情况。这一步字符到连续索引的映射是算术编码实现里的必要前置步骤,用来压缩符号空间,避免浪费数组空间。
问题2:解码循环的作用
这个for循环不是简单递增symbol,它是根据累积频率反向查找当前解码对应的符号:
cum是解码过程中计算出的当前区间对应的归一化值,cum_freq是按符号顺序排列的累积频率数组(cum_freq[1]是第一个符号的频率,cum_freq[2]是前两个符号的频率和,以此类推,数值递增)。- 循环从
symbol=1开始,只要cum_freq[symbol] > cum就继续递增,直到找到第一个cum_freq[symbol] ≤ cum的位置。此时的symbol就是当前区间对应的解码符号——因为这个符号满足cum_freq[symbol-1] < cum ≤ cum_freq[symbol],正好对应编码时该符号的区间范围。
内容的提问来源于stack exchange,提问作者Pytho
相关产品推荐
相关产品推荐

