【问题标题】:Encode an array of integers to a short string将整数数组编码为短字符串
【发布时间】:2013-11-07 04:27:50
【问题描述】:

问题:

我想压缩一个非固定长度的非负整数数组(但它应该是 300 到 400),主要包含 0、一些 1、一些 2。虽然不太可能,但也有可能拥有更大的数字。

例如,这是一个包含 360 个元素的数组:

0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,2,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 ,0,0,0,0,0,0, 0,0,4,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0,1,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0 ,0,0,0,5,2,0,0,0, 0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0。

目标:

我们的目标是将这样的数组压缩成使用字母和数字的最短编码。理想情况下,类似:sd58x7y

我的尝试:

我尝试使用“增量编码”,并使用零来表示任何大于 1 的值。例如:{0,0,1,0,0,0,2,0, 1} 将表示为:2,3,0,1。要解码它,一个人将从左到右读取,并写下“2 个零,一个,3 个零,一个,0 个零,一个(这将添加到前一个,因此有一个 2),1 个零,一个”。

为了消除分隔符(逗号)的需要,从而节省更多空间,我尝试仅使用一个字母数字字符来表示 0 到 35 的增量值(使用 0 到 y),同时将字母 z 保留为“35 PLUS the下一个字符”。我认为这被称为“变量位”或类似的东西。例如,如果一行中有 40 个零,我会将其编码为“z5”。

据我所知...生成的字符串仍然很长(在上面的示例中大约有 20 个字符)。理想情况下,我想要8个字符甚至更短的东西。谢谢你的时间;任何帮助或灵感将不胜感激!

【问题讨论】:

  • 能出现的数字值有上限吗?值 128975 可以存在于某个位置吗?
  • 不,任何大于 5 的值的可能出现实际上是不可能的。因此,虽然 128975 可能存在,但如果它确实存在我会没问题,并将结果字符串设为 100000 个字符长。
  • 您是否可以压缩数据以适应“短”字符串将在很大程度上取决于该数据的稀疏程度。如果您的 360 项数组有 360 个从 0 到 15 的随机值,那么您不太可能将其压缩到 180 字节以下。
  • 一个包含 90% 0 和 10% 1 的列表怎么样?我觉得肯定有一些我不知道的众所周知的方法......
  • 使用 LZW 压缩然后转换为base64 以创建可读的字符串。

标签: algorithm compression


【解决方案1】:

由于您的示例包含长时间运行的零,您的第一步(看起来您已经采取)可能是使用run-lenth encoding (RLE) 来压缩它们。此步骤的输出将是一个整数列表,从零的运行长度计数开始,然后在该值和非零值之间交替。 (0 的零运行长度将指示连续的非零值...)

其次,您可以使用称为universal codes 的一类方法将整数编码为少量位。这些方法通常使用比大整数更少的位数来压缩小整数,并且还提供了对任何大小的整数进行编码的能力(这非常漂亮......)。您可以根据您期望的确切分布调整编码以改进压缩。

您可能还想了解JPEG 样式编码的工作原理。在 DCT 和量化之后,JPEG 熵编码问题看起来和你的差不多。

最后,如果您想进行最大压缩,您可能需要查找arithmetic encoding,它可以将您的数据任意压缩到接近统计最小熵。


以上链接解释了如何压缩成原始比特流。为了将它们转换为一串字母和数字,您需要添加另一个编码步骤,将原始位转换为这样的字符串。正如一位评论者指出的那样,您可能需要查看base64 表示;或者(对于任何可用字母表的最大效率)您可以尝试“反向”使用算术压缩。

关于一般压缩的附加说明:“最短的编码”很大程度上取决于数据源的确切属性。实际上,任何给定的压缩技术都描述了它压缩得最好的数据类型的统计模型。

此外,一旦您根据您期望的数据类型设置了编码,如果您尝试在数据上使用它不同于您期望的类型,结果可能是扩展,而不是压缩。您可以通过提供一种替代的未压缩格式来限制这种扩展,以便在这种情况下使用...

【讨论】:

  • 非常感谢您的启发!今晚我会研究这些话题。
【解决方案2】:

在您的数据中:

14 1s (3.89% of data)
4 2s (1.11%)
1 3s, 4s and 5s (0.28%)
339 0s (94.17%)

假设您的数字不是相互独立的并且您没有任何其他信息,那么您的数据的总熵为每个数字 0.407 位,即总共 146.4212 位(18.3 字节)。所以不可能用 8 个字节编码。

【讨论】:

  • 如果整数在统计上不是独立的,他也许可以改进...
  • @comingstorm 我同意。在我的回答中添加这个警告。
  • 感谢您让我意识到我的目标可能无法实现。也许我应该在生成 400 个整数的数组之前做点什么。
猜你喜欢
  • 2020-07-05
  • 1970-01-01
  • 1970-01-01
  • 2016-02-03
  • 1970-01-01
  • 2012-05-06
  • 2019-04-24
  • 2013-03-26
  • 2015-03-15
相关资源
最近更新 更多