【问题标题】:Why can a textual representation of pi be compressed?为什么可以压缩 pi 的文本表示?
【发布时间】:2015-05-13 19:47:26
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 由我们来猜测您使用的是什么编程语言和压缩算法?
  • @RobbyCornelissen 我认为算法是 XZ - 它在代码中。
  • 为什么字符串是不可压缩的?它只是一系列位,就像文件一样。为什么任何压缩算法都能够压缩文件位而不是字符串位?
  • 注意 π 比较特殊,实际上可以无限压缩。例如。 int a=10000,b,c=2800,d,e,f[2801],g;main(){for(;b-c;)f[b++]=a/5;for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);}。但是 xz 无法检测到这一点。

标签: string random compression pi xz


【解决方案1】:

这是信息密度的问题。压缩就是去除冗余信息。

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

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

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

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

【讨论】:

  • 我想到了这样的事情(我现在在我的问题中使用了前九个整数的前缀代码作为示例。)我接受了你的回答,因为它非常清楚地解释了我最初的困惑。但我仍然对压缩程序的实际作用感兴趣。
  • @Geert:我推荐The Data Compression Book,它提供了许多不同压缩算法的详细信息和实现。很多年前我读过那本书,它真的很有帮助。
  • @Geert:stackoverflow.com/help/dont-ask:“如果你能想象一本书能回答你的问题,那你就问得太多了。”关于数据压缩的书籍有很多
【解决方案2】:

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

【讨论】:

  • 我怀疑这是否真的节省了空间。任何时候压缩器只存储重复的子字符串一次,它会节省 N-1 个子字符串副本的空间,但代价是额外的元数据空间。原则上,如果 pi 的数字在数学上是随机的,那么压缩显着低于 log2(10) 位/数字应该是不可能的。
  • 撇开您可以计算它们的事实不谈,π 的数字在面值上是随机的。查找匹配的字符串不会压缩序列。
猜你喜欢
  • 2011-10-19
  • 1970-01-01
  • 1970-01-01
  • 2014-12-07
  • 1970-01-01
  • 1970-01-01
  • 2016-02-04
  • 1970-01-01
相关资源
最近更新 更多