GMP有任何限制吗?
是的,有。在两个方面。
非常大的数字需要大量内存。@hexafraction 的回答探讨了这一点。
对非常大的数字进行操作需要很长时间。例如,添加两个 N 位数需要O(N)
操作。将两个 N 位数相乘是超线性1。(假设非压缩表示......)
好的,所以从你遇到硬障碍的意义上说,这不是一个限制。但是,如果您的程序需要很长时间才能运行,那显然是一个实际限制。
关于GMP是否进行压缩也有一些讨论。有很多方法可以回答这个问题:
查看 GMP 源代码。(@hexafraction 说答案是“不压缩”)
尝试一个实验。编写一个小程序,通过左移 1来创建(比如说)2 1,000,000,000top
,并使用或等价物来查看程序使用了多少内存。
考虑压缩对算术运算的影响。事实上,最后一种方法可能是最有启发性的。它将告诉您通用(或特殊用途)bignum 库使用压缩是否可行。
1 - 天真的长乘法是O(N^2)
,但有更好的算法具有更好的渐近性能。对于 2^2^96 范围内的数字,您应该查看Schönhage–Strassen 算法或Fürer 算法。一般来说,乘法算法的维基百科页面是开始阅读的好地方。
使用压缩大数的算术
让我们假设我们这样做的原因是数字太大而无法以未压缩的形式表示。所以解压缩操作数,进行操作并压缩结果......不是一个可行的选择。
如果您尝试将普通算术算法应用于压缩数字,则需要能够逐步解压缩输入、执行操作并压缩输出。这可行吗?好吧,这取决于细节。例如:
但是有两个问题:
那么有替代方案吗?
好吧,可能是的。如果您使用运行长度编码,则可以编写(例如)一个加法算法,将“运行”考虑在内。例如:
10000000000000001
+10000000000000001
添加最左边的数字对
10
添加零的匹配运行
0000000000000010
添加 MSB
100000000000000010
然后你可以从中建立更复杂的操作。
这种方法的优点(如果你能做到的话)是对于合适的输入,它将降低计算的复杂性。例如,加法现在比O(N)
. (我认为它实际上应该与运行长度编码表示的大小成正比......)
但是再一次,这使得操作更加复杂,并且只有在运行的平均长度足够大来补偿时才会有效。对于压缩得不够好的数字,这将是一种反优化。
总之:
这种方法的可行性取决于实际数字的可压缩性。
值得怀疑的是,这在通用“大数字”库(如 GMP)中是一种可行的方法。我们在数字上下文中遇到的典型大数不能充分压缩......以一种有帮助的方式。如果压缩没有帮助,它可能会阻碍。
如果存在这样的库,这在特殊用途的“大数字”库中可能是可行的。在适当的情况下,压缩算法应该比普通的 bignum 算法具有更好的复杂性。