我试图实施一个deflate压缩器,我必须决定是否 使用静态霍夫曼代码压缩块或创建动态代码。
与静态代码相关的长度背后的基本原理是什么?
(这是rfc中包含的表格)
Lit Value Bits
--------- ----
0 - 143 8
144 - 255 9
256 - 279 7
280 - 287 8
我认为静态代码更倾向于简单的ascii文本,而不是它
看起来它喜欢一点点压缩长度
决定是否使用静态代码有什么好的启发式方法?
我正在考虑从一个样本中建立一个概率分布 输入数据并根据导出的概率计算距离(可能是EMD?) 来自静态代码。
答案 0 :(得分:2)
我猜测代码的创建者从压缩数据中获取了大量文字和长度样本,可能包括可执行文件和文本,并且在大集合中找到了典型的代码长度。然后用显示的表格近似它们。然而,作者多年前去世了,所以我们永远不会知道。
您不需要启发式。完成查找匹配字符串的工作后,计算动态和静态表示的块中的位数相对非常快。然后只需选择较小的一个。或者静态的一个(如果相等)(解码得更快)。
答案 1 :(得分:1)
我不了解基本原理,但在选择静态代码长度时有少量 irrationale :
在您的问题的表格中,最大静态代码编号为287,但DEFLATE specification仅允许代码285,这意味着代码长度浪费地分配给两个无效代码。 (甚至不是最长的!)它与距离代码表类似,有32个代码分配了长度,但只有30个有效。
因此,可以进行一些简单的改进,但是,如果没有对数据的一些先验知识,那么通常不可能生产出效率更高的任何东西。 "平坦"该表(没有长度超过9位的代码)将最坏情况的性能降低到每个不可压缩数据字节的1个额外位。
我认为分组背后的主要原理是,通过将组大小保持为8的倍数,可以通过查看5个最重要的位来判断代码属于哪个组,这也告诉您它的长度,以及要添加的值,立即获取代码值本身
00000 00 .. 00101 11 7 bits + 256 -> (256..279)
00110 000 .. 10111 111 8 bits - 48 -> ( 0..144)
11000 000 .. 11000 111 8 bits + 78 -> (280..287)
11001 0000 .. 11111 1111 9 bits - 256 -> (144..255)
因此理论上你可以设置一个包含32个条目的查找表来快速读取代码,但这是一个不常见的情况,可能不值得优化。
只有两种情况(有一些重叠)固定霍夫曼块可能是最有效的:
其中输入大小(以字节为单位)非常小,静态Huffman可以比未压缩更有效,因为Uncompressed使用32位头,而Fixed Huffman只需要7位页脚,加上1位潜在开销每个字节。
在输出大小非常小的情况下(即小型,高度可压缩的数据),静态霍夫曼可以比动态霍夫曼更有效 - 再次因为动态霍夫曼使用一定量的空间来获得额外的头部。 (实际的最小标题大小很难计算,但我说至少64位,可能更多。)
也就是说,从开发人员的角度来看,我发现它们实际上是有用的,因为使用静态霍夫曼块实现与Deflate兼容的功能非常容易,并且从迭代中逐步改进那里有更有效的算法工作。