对字符串中包含的大基数10的最佳压缩

时间:2016-02-13 02:13:20

标签: javascript string algorithm compression

我正在为包含基数为10的数字的字符串编写压缩和解压缩函数。我认为,因为它只有10个字符被执行,所以存在一个可以代表大字符串的小得多的字符串。压缩结果以ISO-8859-7编码,因此我可以在结果字符串中使用256个字符

例如,我想取一个表示1000位数字的字符串(例如this one)和#34;压缩它"。这些长度的数量超过了我使用的语言中的数字类型,JavaScript。因此,数字操纵/转换是不可能的。我使用的压缩软件(shoco)不会压缩数字。完全没有。

我该怎么做呢?是否有某种算法可用于压缩数字?我不是在寻找速度,而是寻找大多数数字的最佳压缩,而不仅仅是作为一个例子给出的数字。

2 个答案:

答案 0 :(得分:3)

如果您使用三位数组进行数字处理,您可以用10位代表每个三元组,而且浪费很少。那么你“只需要”从你的10位三元组流中创建一个8位八位字节流,这需要一定量的位移,但并不是非常复杂。

假设您的号码由3位数的倍数组成(您可以用前导零填充它)或者您知道它包含多少位数(在这种情况下,您可以在末尾用尾随零填充它)。如果您将子序列编码为50位单元,则您将拥有足够的代码空间来编码最多15位的数字序列,而不仅仅是15位数字,这将避免需要填充。你可以用一种使用53位浮点作为常用数字类型的语言来勉强逃脱,但它可能或者可能不值得额外的复杂化。

答案 1 :(得分:3)

rici的答案,每三位使用10位,确实是我用于实际应用的。

但是,由于您要求最佳压缩并声明您不关心速度,因此将使用多精度算法生成十进制数的二进制表示。此代码已在GMP library中为您编写。该库经过高度优化且速度非常快,因此您不会看到巨大的速度影响,具体取决于您使用这些数字做了什么。

作为一个例子,你的1000位数字将使用334组10位代码需要418个字节。当编码为单个大的二进制整数时,它将需要416个字节。在2 GHz i7上,使用10位数组进行1000位数转换可获得1.9μs,而使用多精度算术可获得55μs,从而产生一个大整数。

更新

我错过了javascript代码,直到有人在评论中指出它。您可以在javascript中使用Crunch进行多精度算术。

更新2:

正如rici所指出的,上面的比较假定输入的长度对于两种编码都是先验已知的。但是,如果比特流需要嵌入更大的流中并且数字的数量不是先验的,那么必须提供一种方法来确定数字的结束位置。

三位数的10位编码允许使用最终的10位代码作为该标记,因为24个可能的值未被使用。事实上,我们可以使用其中的10个来为数字提供一个数字。 (我们甚至可以通过使用20个值为0..19来添加一个“半”数字,如果在该位置存在则允许前导1。或者我们可以使用它来表示允许负整数。但我离题了。)结果证明适用于1000位数的情况,这是三位数的倍数加一。然后可以使用418字节的结束标记对1000个数字进行编码,与不需要结束标记时相同。 (在比特流中,它实际上可以是417.5字节。)

对于二进制整数,我们可以在其前面加上以位为单位的长度,或者使用位填充来用一系列的一位来标记流的末尾。无论哪种方式,开销大致相同。我们将使用后者来轻松处理任意长度的整数。 1000位整数将占用3322位,或415字节和2位。我们可以选择数据中一位的最大运行长度为11。当11 1连续出现时,将0位填充到流中。如果连续看到12 1,那么你已到达流的末尾(12 1和前面的0被丢弃。)使用11将在末尾添加13位,并允许最多填充一位填充最后一个字节(填充位的平均数为0.81),使总字节数达到417。

因此,由于未使用的10位模式的优势,现在还有增益,四位精确,但现在更少。