关于javascript:对字符串中包含的以10为底的大数字进行最佳压缩

Optimal compression for a large base 10 number contained in a string

我正在为包含10位数字的字符串编写压缩和解压缩功能。我认为,由于只作用了10个字符,因此存在一个较小的字符串,可以表示较大的字符串。压缩后的结果在ISO-8859-7中进行了编码,因此我可以在结果字符串中使用256个字符

例如,我想要一个代表1000位数字的字符串(例如,这个数字)并"压缩"它。这些长度的数字超出了我使用的语言JavaScript中的数字类型。因此,数字操作/转换是不可能的。我使用的压缩软件(shoco)不压缩数字。完全没有。

我该怎么做?有某种可用于压缩数字的算法吗?我不是在寻找执行速度,而是在寻找大多数数字的最佳压缩效果,而不仅仅是示例中给出的数字。


rici的答案是,每三位数使用10位,这确实是我在实际应用中要使用的答案。

但是,由于您要求最佳压缩并且表示您不关心速度,因此将使用多精度算术生成十进制数的二进制表示形式。该代码已在GMP库中为您编写。该库经过高度优化和相当快,因此您不会看到巨大的速度影响,这取决于您对数字进行的其他处理。

例如,您的1000位数字将使用334组10位的代码来占用418个字节。如果将其编码为一个大的二进制整数,则将需要416个字节。在2 GHz i7上,使用10位集进行1000位转换时,我得到1.9 μs,而使用多精度算术生成一个大整数则需要55 μs。

更新:

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

更新2:

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

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

对于二进制整数,我们可以在其前面加上一个长度(以位为单位),或者使用位填充以一系列的一位标记流的末尾。任一种方式的开销都差不多。我们将使用后者,以使其易于处理任意长度的整数。 1000位整数将占用3322位,即415个字节和两位。我们可以选择数据中一位的最大游程为11长。当连续出现11个1时,会将0位填充到流中。如果连续看到12个1,则您已到达流的末尾(丢弃12个1和前一个0。)使用11将在末尾添加13位,并允许填充最多一位填充最后一个字节(填充位的平均数目为0.81),使总字节数达到417。

所以仍然有增益,准确地说是四位,尽管由于未使用的10位模式的优点而现在有所减少。


如果以三位数字为一组来处理数字,则可以用10位来表示每个三元组,而浪费很少。然后,您只需要从10位三元组流中创建8位八位位组流,这将需要一定量的移位,但并不十分复杂。

假定您的电话号码由3位数字组成的倍数(您可以用前导零填充)或知道其包含多少位(在这种情况下,您可以在末尾添加零以填充数字)。如果将子序列编码为50位单位,则将有足够的代码空间来编码最多15位的数字序列,而不仅仅是15位,这将避免填充。使用以53位浮点作为通用数字类型的语言,您几乎无法摆脱这种情况,但这可能或可能不值得使您感到额外的麻烦。