BigInteger
类中的multiply
、divide
和pow
方法目前的复杂度是什么?文档中(以及其他任何地方)都没有提到计算复杂度。
BigInteger
类中的multiply
、divide
和pow
方法目前的复杂度是什么?文档中(以及其他任何地方)都没有提到计算复杂度。
BigInteger
代码,我认为 multiply(..)
方法具有O(n^2) 的时间复杂度(实际上这个方法是 multiplyToLen(..)
)。其他方法的代码有些复杂,但你可以自己看一下。O(N^2)
算法更有效率的算法来实现乘法和除法。O(N^2)
长乘法算法、Karatsuba算法或三路Toom-Cook算法。后两者的时间复杂度分别为O(N^1.58)
和O(N^1.46)
。O(N^2)
长除法算法或Burnikel-Ziegler算法。后者是指一个2N位数除以一个N位数的除法,时间复杂度为2K(N) + O(NlogN)
,其中K(N)
是两个N位数的Karatsuba乘法时间。Java 8的源代码中提到了一些复杂性的细节。 javadocs不提及复杂度的原因是它在理论上和实际上都是具体实现的。 (正如某些操作的复杂度在Java 7和8之间有明显不同的表现。)文档中没有提及计算复杂性(也没有在其他地方提到)。
进行测量。使用逐渐增加的操作数进行操作,并在图表上绘制时间。 不要忘记热身JVM(多次运行)以获得有效的基准结果。
如果操作是线性O(n),二次方O(n ^ 2),多项式或指数,应该很明显。
编辑:虽然您可以给出算法的理论界限,但实际上可能并不那么有用。首先,复杂度并不给出因素。一些线性或亚二次算法只是因为它们消耗了太多的时间和资源而不适合手头的问题(例如Coppersmith-Winograd矩阵乘法)。 然后,您的计算可能具有所有仅通过实验才能检测到的技巧。有准备算法,它们没有解决问题,只是加速了真正的求解器(矩阵条件)。有次优的实现。随着长度的增加,您的速度可能会急剧下降(缓存丢失,内存移动等)。因此,为了实际目的,我建议进行实验。
最好的方法是每次将输入的长度加倍,然后比较时间。而且,你可以找出一个算法是否具有n^1.5或n^1.8的复杂度。只需将输入长度乘以四倍,如果是1.5,则只需要一半的时间,而不是两倍。如果你将长度增加256倍,那么对于1.8,你再次获得了近乎一半的时间。
BigInteger
自Java 1.1版本就存在了。 - Joachim Sauer