GMP有限制吗?

时间:2013-06-29 23:02:13

标签: java python gmp

GMP的所有文件似乎都暗示没有限制。这是真的吗?

我想做一些简单的整数数学(加法,移位,xor,乘法,除法等),但真正庞大的数字达到2 ^ 2 ^ 96(即2 ^ 79,228,162,514,264,337,593,543,950,336,这可能是数量级更多内存比你电脑里的内存)甚至2 ^ 2 ^ 256。如果我遇到了获得GMP和编码的麻烦,那么它会因为要求获得如此非凡的数字而引起我的注意,还是会起作用 - 正如炒作所暗示的那样?

我希望将它与Java一起使用,所以我可能会使用JNI GMP here,但我对语言并不是很挑剔。 Python看起来可以与GMP一起使用。

3 个答案:

答案 0 :(得分:4)

  

GMP有限制吗?

是的。在两个方面。

  • 真的很大的数字需要大量的内存。 @ hexafraction的回答探讨了这一点。

  • 真正大数字的操作需要很长时间。例如,添加两个N位数字需要O(N)次操作。将两个N位数相乘是超线性 1 。 (假设非压缩表示......)

    好的,所以这不是你遇到硬障碍的意义上的限制。但是如果你的程序运行时间不长,那显然是实际限制。

还有一些关于GMP是否进行压缩的讨论。有很多方法可以回答这个问题:

  • 查看GMP源代码。 (@hexafraction说答案是"没有压缩")

  • 尝试实验。编写一个小程序,通过左移1创建(比如说)2 1,000,000,000 ,并使用top或等效项来查看程序使用的内存量。

  • 考虑压缩对算术运算的影响。事实上,最后一种方法可能是最有启发性的。它将告诉您是否可行用于通用(或特殊用途)bignum库以使用压缩。

1 - 天真长乘法是O(N^2),但是有更好的渐近性能的算法。对于2 ^ 2 ^ 96区域内的数字,您应该查看Schönhage–Strassen algorithmFürer's algorithm。一般来说,multiplication algorithms上的维基百科页面是开始阅读的好地方。

使用压缩bignums的算术

让我们假设我们这样做的原因是数字太大而无法以未压缩的形式表示。因此,解压缩操作数,执行操作并压缩结果......不是一个可行的选择。

如果尝试将常规算术算法应用于压缩数字,则需要能够逐步解压缩输入,执行操作并压缩输出。这可行吗?那取决于细节。例如:

  • 添加两个数字,您从最低端开始,并添加相应的位,进位和重复。完整的操作需要一次通过输入数字。如果您的压缩方案是(比如)稀疏的位数组,那么这将起作用,但是如果您使用了运行长度编码,那么您需要编码从最低位到最高位的运行。

  • 乘以两个数字,基本上你会做N次移位和加法序列N次。这也可以逐步完成。但请注意,我们正在对每个移位和添加周期进行增量解压缩/压缩...

  • 划分 ...你会进行N位移位和减法N次。与上述相同。

但有两个问题:

  • 压缩/解压缩会增加所有这些操作的开销。假设您已选择合适的压缩方案,则开销将是每位压缩/解压缩的常数乘数。

  • 第二个问题是压缩方案是否实际上对输入和输出有效,而对于更复杂的操作,中间结果是否有效。

还有其他选择吗?

可能是的。如果你使用行程长度编码,你可以写(比方说)一个加法算法,它采用"运行"考虑到了。例如:

     10000000000000001
    +10000000000000001
  • 添加最左边的数字对

                    10
    
  • 添加零的匹配运行

      0000000000000010
    
  • 添加MSB

    100000000000000010
    

然后你可以从中构建更复杂的操作。

这种方法的优点(如果可以将其拉下)是对于合适的输入,它将降低计算的复杂性。例如,添加现在优于O(N)。 (我认为它实际上应该与行程编码表示的大小成正比...)

但是再一次,这使得操作变得更加复杂,并且只有在运行的平均长度足以补偿时才会有效。对于不能很好地压缩的数字,这将是一种反优化。


总结:

  1. 这种方法的可行性取决于实际数字的可压缩程度。

  2. 通用"大数字"这是一个可行的方法是值得怀疑的。图书馆(如GMP)。我们在数字上下文中遇到的典型大数字是不够可压缩的...以一种有用的方式。如果压缩没有帮助它可能阻碍。

  3. 这可能适用于特殊用途"大号"图书馆,提供这样的图书馆。在适当的情况下,压缩算法应该比普通的bignum算法具有更好的复杂性。

答案 1 :(得分:1)

按设计,是的。它将尝试来存储和操作您提供的任何数字,但在许多情况下,与您类似的问题将变得不合理。

实际上,操作系统和计算机硬件设置了限制。

2 ^ 2 ^ 96需要2 ^ 96位来表示最佳未压缩情况。这相当于仅仅9,904,000,000,000,000 tera 字节。您的计算机无法存储那么多数据。此外,只能索引一个大约40亿的数组,不足以管理这个巨大的数据堆。为了解决这些问题,我们需要一个40亿条目的数组,其中包含40亿个入口数组,其中包含40亿个入口数组。我完全不确定,因为总元素超过40亿,所以我甚至不能确定。

无论如何,你的堆在32位JVM上最大可达4 GB。在这方面,即使你可以存储这么多位,并且你以4 GB /秒的速度运行,也需要78,460,000,000年。

即使数字可以被压缩(它们必须在某种程度上解压缩)以进行操作,您仍然需要考虑到90亿TB数据的Kolmogrov complexity不可能小于整数对于真实世界的数字,太字节。

答案 2 :(得分:0)

虽然mpn级别没有限制,但是mpz_t的大小由int表示,mpz_t在所有平台上都是32位类型(至少由GMP支持);请参见GMP手册中的Integer Internals。这意味着在64位平台上限制为2 ^ 37位(import io your_data = b'\x02\x1b\x92\x1fs\x96\x97\xe8\x01' sd = io.BytesIO() sd.write(your_data) sd.seek(0) # Seek to the beginning # sd can act like a file handle. Pass it to your function. 整数将少于2 ^ 31条64 = 2 ^ 6位的分支)。

注意:by Torbjörn Granlund in April 2012 in the gmp-discuss list提到了2 ^ 37位的限制。