1

随机字符串应该是不可压缩的。

pi = "31415..."
pi.size  # => 10000
XZ.compress(pi).size  # => 4540

随机的十六进制字符串也会被显着压缩。但是,随机字节字符串不会被压缩。

pi 的字符串只包含字节 48 到 57。在整数上加上前缀代码,这个字符串可以被高度压缩。本质上,我通过以字节表示我的 9 个不同字符(或 16 个,在十六进制字符串的情况下)来浪费空间。这是怎么回事?

有人可以向我解释基本方法是什么,或者指出一些来源吗?

4

2 回答 2

4

这是信息密度的问题。压缩是关于删除冗余信息。

在 string"314159"中,每个字符占用 8 位,因此可以有 2 8或 256 个不同的值中的任何一个,但实际上只有 10 个值被使用。即使是非常幼稚的压缩方案也可以使用每个数字 4 位来表示相同的信息;这被称为二进制编码的十进制。更复杂的压缩方案可以做得更好(十进制数字实际上是 log 2 10,或大约 3.32 位),但代价是存储一些允许解压缩的额外信息。

在一个随机的十六进制字符串中,每个 8 位字符都有 4 个有意义的位,因此应该可以压缩近 50%。字符串越长,越接近 50%。如果您事先知道该字符串仅包含十六进制数字,则可以将其精确压缩 50%,但当然这将失去压缩其他任何内容的能力。

在随机字节串中,没有压缩的机会;您需要每个字符的全部 8 位来表示每个值。如果它真的是随机的,尝试压缩它可能会稍微扩展它,因为需要一些额外的信息来表明输出是压缩数据。

解释压缩如何工作的细节超出了这个答案的范围和我的专业知识。

于 2015-05-13T20:04:24.290 回答
0

除了Keith Thompson 的出色回答之外,还有一点与LZMA相关(这是 XZ 格式使用的压缩算法)。数字 pi 不是由单个重复的数字串组成,但也不是完全随机的。它确实包含在较大序列中重复的数字子串。LZMA 可以检测到这些并仅存储重复子字符串的单个副本,从而减少压缩数据的大小。

于 2015-05-13T20:13:02.393 回答