【问题标题】:Integer compression method整数压缩法
【发布时间】:2018-12-19 21:11:26
【问题描述】:

如何将一行整数压缩成更短的值?

喜欢: 输入:'1 2 4 5 3 5 2 3 1 2 3 4' -> 算法 -> 输出:'X Y Z'

可以反过来取回吗? ('X Y Z' -> '1 2 4 5 3 5 2 3 1 2 3 4') 注意:输入将仅包含 1-5 之间的数字,并且数字的总字符串将为 10-16 有什么办法可以将其压缩为 3-5 个数字?

【问题讨论】:

  • 因为每个“数字”有五种可能性,即每个数字有 2.322 位熵。如果您最多有 16 个这样的数字,那么您在整个序列中最多有 37.15 位熵。正如@user3386109 所指出的,这肯定适合 64 位整数。对此进行编码的一种简单方法是对每个“数字”简单地使用连续的 3 位字段。
  • 在 JS 中你可以像parseInt("013424120123",5).toString(36); 一样得到ad65j。不过,您的数字必须映射到 0-4。对于反向做喜欢parseInt("ad65j",36).toString(5); 并得到13424120123。在左侧添加所需的多个0s。

标签: database algorithm math integer compression


【解决方案1】:

这是一种方法。首先,从每个小数字中减去一个。对于您的示例输入,导致

0 1 3 4 2 4 1 2 0 1 2 3

现在将其视为整数的 base-5 表示。 (您可以选择第一位或最后一位最重要的数字。)以二进制形式计算表示相同含义的数字。现在你有一个整数来“压缩”你的小数字字符串。既然你没有展示你自己的代码,我就停在这里。您应该能够轻松实现这一点。

由于您最多有 16 个小数字,因此该算法的最大结果值为5^16,即152,587,890,625。这适合38 位。如果您需要存储比这更小的数字,请将结果值转换为另一个更大的数字基数,例如 2^162^32。前者会产生 3 个数字,后者会产生 2 个数字。


@SergGr 在评论中指出该方法不显示编码的整数个数。如果没有单独存储,那可能是个问题,因为该方法不区分前导零和编码零。如果您需要压缩中包含的整数数量,有几种方法可以处理这个问题。您可以要求最高有效数字为1(第一个或最后一个取决于最高有效数字的位置。)这会将位数增加一,因此您现在可能需要39 位。

这是一个可变长度编码的玩具示例。假设我们要编码两个字符串:1 2 31 2 3 0 0。结果会有什么不同?让我们考虑两个基数为 5 的数字 32100321。它们代表相同的值,但我们仍然将它们转换为 base-2 保留填充。

1 + 2*5 + 3*5^2 = 86 dec = 1010110 bin
1 + 2*5 + 3*5^2 + 0*5^3 + 0*5^4 = 000001010110 bin

第二行中那些额外的0 意味着最大的 5 位基数为 5 的数字 44444 的基数为 2 表示为 110000110100,因此该数字的二进制表示被填充为相同的大小。

请注意,无需填充第一行,因为最大的 3 位 base-5 数字 444 具有 1111100 的 base-2 表示,即长度相同。对于初始字符串3 2 1,在这种情况下也需要一些填充,因此即使顶部数字不是0,也可能需要填充。

现在让我们将最重要的1 添加到二进制表示中,这将是我们的编码值

1 2 3 => 11010110 binary = 214 dec
1 2 3 0 0 => 1000001010110 binary = 4182 dec

有很多方法可以将这些值解码回来。一种最简单(但不是最有效)的方法是首先通过计算floor(log5(encoded)) 来计算以 5 为基数的位数,然后删除最高位并使用 mod 5 逐位填充数字并除以 5 操作。

显然,这种可变长度编码总是会增加 1 位的开销。

【讨论】:

  • 这听起来像是一个好的开始,但我认为它并没有涵盖要压缩的可变数量的整数。
  • @SergGr:我假设整数的数量是单独存储或计算的。这可能是一个糟糕的假设,所以我会在我的答案中添加一些关于它的内容。感谢您的提示。
  • There are several ways to handle [10-16 total] 是的。 if you need the number of integers included 想一想存储大量 [rows] of integers 的文件。如果用于编码值,则要求一个具有恒定值的符号无助于说明界限,或者 - 测试压缩/编码思想的第一条规则:创建一个工作解码器。处理 10-16 个总数 的一种方法是允许一个额外的 未使用的位置 用于位置 11-15,总共 5^11*6^5=379687500000 个组合 - ≤基数 ≥ 207 或 39 位的五位数字。 (您是如何到达38的?)
  • @greybeard 我认为您错过了 Rory 的建议。首先,从信息的角度来看,很明显,如果您可以使用 M 位编码所有大小为 N 的序列,您可以使用 at 编码所有大小为 N 或更小的序列大多数M+1 位,因为显然小于N 的序列数小于正好N 的序列数。实际上,理论上这个额外的位甚至可能不需要,但在 Rory 的方法中是必需的。我在 Rory 的答案中添加了一个可变长度编码的玩具示例。如果您发现这方面存在一些问题,请立即告诉我。
  • @SergGr: (Let me know?) I think [greybeard] missed what Rory suggests 我声称在固定位置添加固定值符号不会添加信息。你如何解码110101101000001010110100000101011011010110
【解决方案2】:

它的名字是:polidatacompressor.js 但是许可证会花费你,你必须向作者询问价格 LOL

https://github.com/polidatacompressor/polidatacompressor

Ncomp(65535) 将输出:255, 255,当你将它作为字节存储在数据库中时,你得到 2 个字符

另一种方法是在 javascript (1231) 中使用“Hexadecimal aka base16”。toString(16) 在 60% 的情况下为您提供 '4cf',它将 char 压缩为 -1

或者使用base10到base64 https://github.com/base62/base62.js/ 4131 --> 14D 413131 --> 1Jtp

【讨论】:

    猜你喜欢
    • 2015-08-07
    • 2012-09-21
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    相关资源
    最近更新 更多