【问题标题】:What is the best way to compress a sequence of about 2 millions numbers (value range is from 1-->28)压缩大约 200 万个数字的序列的最佳方法是什么(值范围是 1-->28)
【发布时间】:2014-02-11 19:41:11
【问题描述】:

我正在尝试压缩整数列表,其中:

  • 没有负数。
  • item的取值范围是[1....28]
  • 列表中总共有 2482113 项。
  • 目前我使用 5 位 来存储每个数字。
  • “出现”统计如下

    • 1 : 1242149
    • 2 : 620038
    • 3 : 309399
    • 4 : 154983
    • 5 : 77816
    • 6 : 38601
    • 7 : 19651
    • 8 : 9790
    • 9 : 4830
    • 10 : 2447
    • 11 : 1253
    • 12 : 597
    • 13 : 303
    • 14 : 130
    • 15 : 73
    • 16 : 23
    • 17 : 17
    • 18 : 4
    • 19 : 4
    • 20:2
    • 21:1
    • 23:1
    • 28:1

所以请告诉我压缩这种数据的最佳方法(估计压缩率 - 如果可能的话 - 非常感谢)。

【问题讨论】:

  • “什么是最佳比例”——我们怎么知道?
  • 如果列表是一成不变的,从技术上讲,您可以用 0 位逃脱:没有要传输的信息,它始终是您刚刚发布的列表。
  • @delnan,你无法摆脱零位。至少,您需要发布列表中的信息。无论如何,该列表仅给出分布,而不是可能也很重要的顺序:-)
  • @paxdiablo 关于分发与顺序的好点,但假设完整列表是恒定且已知的,您可以摆脱零位:将列表硬编码到解密程序中,那么你不需要给它任何输入让它产生列表;-)
  • @delnan,好吧,从技术上讲,程序本身就变成了比特数,但是,因为我看到了笑脸,所以我不会争论这一点:-)

标签: algorithm list integer lossless-compression


【解决方案1】:

对于那种分布(a),您可能想要研究一种可变长度编码方案,例如霍夫曼。与固定的 5 位大小相比,这将为您提供更好的压缩。它们通过使用更少的位来表示更常见的值(并使用更多的位来表示不常见的值)来降低平均位宽度。

举个简单的例子,假设0 位代表数字一,所有其他数字由1 位表示,后跟您当前的 5 位方案。

这意味着您为 1 的每个值(1,242,149 x 4 = 4,968,596 位)节省了 4 位,而为所有其他值(1,239,964 位)“浪费”了一位,净节省了 370 万位。

这是针对您的特定数据集的“硬编码”霍夫曼方案,旨在说明其工作原理,您可能希望对任意数据集更具适应性。

扩展它以包含更多更大的数量会带来额外的改进。我们已经知道最高价值的节省:

Bit pattern  Value   Quantity  Saved bits
0                1  1,242,149   4,968,596  (4 per)
1xxxxx          >1  1,239,964   1,239,964- (1 per)
                                ---------
Net saving                      3,728,632  (extra return 3,728,632)

对于前两个值:

Bit pattern  Value   Quantity  Saved bits
0                1  1,242,149   4,968,596  (4 per)
10               2    620,038   1,860,114  (3 per)
11xxxxx         >2    619,926   1,239,852- (2 per)
                                ---------
Net saving                      5,588,858  (extra return 1,860,226)

前三名:

Bit pattern  Value   Quantity  Saved bits
0                1  1,242,149   4,968,596  (4 per)
10               2    620,038   1,860,114  (3 per)
110              3    309,399     618,798  (2 per)
111xxxxx        >3    310,527     931,581- (3 per)
                                ---------
Net saving                      6,515,927  (extra return 927,069)

前四名:

Bit pattern  Value   Quantity  Saved bits
0                1  1,242,149   4,968,596  (4 per)
10               2    620,038   1,860,114  (3 per)
110              3    309,399     618,798  (2 per)
1110             4    154,983     154,983  (1 per)
1111xxxxx       >4    155,544     622,176- (4 per)
                                ---------
Net saving                      6,980,315  (extra return 464,388)

在这个级别上,每个数字固定 5 位的方案会产生 12,410,565 位。净节省 6,980,315 位,现在总压缩大小为 5,430,250 位,比固定位大小方法节省约 56 位。

您可以看到,随着更多价值的增加,额外的投资回报会迅速减少。除了前四个值之外,您不会使用此硬编码方案保存任何内容,因为每个项目的位节省为零(之后为负数)。真正的自适应编码会为您节省更多(因为它还优化了xxxxx 位),但可能不会太多。


(a) 从外观上看,这是一个非常人为的分布。每个数量大约是前一个数量的一半,使可变长度编码成为理想的解决方案。

【讨论】:

  • 感谢您注意到人为的分布!
  • @paxdiablo:非常感谢您提供如此详细的回答。目前工作比较忙,有时间就研究一下哈夫曼编码,把结果发在这里。
  • @comingstorm: 很抱歉那种“做作”的样子。但我不打算让它看起来像那样。这是我从意义数据源计算出来的结果。
【解决方案2】:

http://en.wikipedia.org/wiki/Huffman_coding 有关压缩信息的信息。

由于列表中的大多数项目的频率大于列表中所有频率较低的项目的频率之和,因此实际上每个项目的效率约为 2 位。

精确压缩提供每个符号平均 2.00915 位。下面的计算揭示了我对编码的选择。

(1242149 + 2 * 620038 + 3 * 309399 + 4 * 154983 + 5 * 77816 + 6 * 38601 + 7 * 19651 + 8 * 9790 + 9 * 4830 + 10 * 2447 + 11 * 1253 + 12 * 597 + 13 * 303 + 14 * 130 + 15 * 73 + 16 * 23 + 17 * 17 * 18 * 4 + 19 * 4 * 20 * 2 + 21 * 1 + 22 * (1+1)) / 2482113.0

请注意,由于您的频率并不总是接近 2 的逆幂,http://en.wikipedia.org/wiki/Arithmetic_coding 可能会获得更好的压缩。

【讨论】:

  • 感谢您回答我的问题。目前工作比较忙,有时间我会检查一下,然后在这里发回结果。
【解决方案3】:

看看Huffman Coding。我不知道确切的细节,但基本原则是根据需要将更少的位分配给更常见的数字,将更多的位分配给不太常见的数字,以便总体而言,每个数字的平均位数更少比您期望的均匀分布(每个字符约 5 位)

【讨论】:

  • +1 用于提供有关算法的更多信息,而不仅仅是维基页面的链接
猜你喜欢
  • 1970-01-01
  • 2016-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多