Java 计算乘积a*b²;*c³。。。有效地
计算乘积的最有效方法是什么 a1 b2 c3 d4 e5 假设平方运算的成本大约是乘法的一半?操作数少于100 对于乘法时间与操作数长度的平方成正比的情况(如Java 计算乘积a*b²;*c³。。。有效地,java,math,biginteger,arbitrary-precision,Java,Math,Biginteger,Arbitrary Precision,计算乘积的最有效方法是什么 a1 b2 c3 d4 e5 假设平方运算的成本大约是乘法的一半?操作数少于100 对于乘法时间与操作数长度的平方成正比的情况(如java.math.biginger)是否也有一个简单的算法 第一个(也是唯一的)答案是完美的手术次数 有趣的是,当应用于sizablebigingers时,这一部分根本不重要。即使在没有任何优化的情况下计算abbccddddeeee也需要大约相同的时间 大部分时间都花在最终乘法上(biginger没有实现像Karatsuba、Toom–
java.math.biginger
)是否也有一个简单的算法
第一个(也是唯一的)答案是完美的手术次数 有趣的是,当应用于sizable
biginger
s时,这一部分根本不重要。即使在没有任何优化的情况下计算abbccddddeeee也需要大约相同的时间
大部分时间都花在最终乘法上(biginger
没有实现像Karatsuba、Toom–Cook或FFT这样更智能的算法,因此时间是二次的)。重要的是确保中间被乘数的大小大致相同,即给定大小大致相同的数字p、q、r、s,计算(pq)(rs)通常比((pq)r)s快。对于几十个操作数,速度比似乎约为1:2
更新
在Java8中,
BigInteger
中既有Karatsuba乘法,也有Toom-Cook乘法,我完全不知道这是否是最佳方法(尽管我认为它是渐近最优的),但您可以在O(N)
乘法中完成所有操作。将a*b^2*c^3的参数分组如下:c*(c*b)*(c*b*a)
。在伪代码中:
result = 1
accum = 1
for i in 0 .. arguments:
accum = accum * arg[n-i]
result = result * accum
我认为它是渐近最优的,因为您必须使用N-1
乘法才能将N
输入参数相乘。As:
由于操作数大小的乘法时间是超线性的,因此保持长操作的操作数大小相似(特别是如果唯一可用的Toom Cook是Toom-2(Karatsuba))将是有利的。如果不进行全面优化,将操作数放入队列中,允许按增加(有效)长度的顺序弹出操作数,这看起来是一个不错的选择。
此外,还有一些特殊情况:0,2的幂,一个因子(否则)“平凡”的乘法(“长乘一位数乘法”,因子长度之和为线性)。
平方运算比一般乘法更简单/更快(问题建议假设½),这将建议以下策略:
- 在预处理步骤中,计算按指数加权的尾随零数
如果遇到0,则结果为0
- 删除尾随零,放弃结果值1
如果没有剩余值,结果1
- 查找并合并多次出现的值
- 设置允许提取“最短”号码的队列。对于每一对(数字、指数),插入将相乘的因子
- 可选:组合“琐碎因素”(见上文)并重新插入
我不知道该怎么办。假设长度为12的因子,其中平凡因子和初始因子的长度为1,2,…,10,11,12,…,n。最佳情况下,将1+10、2+9……与12中的7个小因子组合。将最短值相加,从12中得到8的3、6、9、12
- 提取最短的一对因子,乘以并重新插入
一旦只有一个数字,结果就是第一步加上零
(如果因子分解很便宜,那么就必须很早进行,才能从廉价的平方中获得最大的收益。)看起来是一个合理的面试问题。。。基本解决方案(非最优)是简单地分别计算每个成员的幂(乘法的log2(幂))并将结果相乘…有一个O(N log(N)^2)
算法来实现这一点(其中N是最终数字的大小)。但是您需要超越java.math.biginger来实现它。操作数的类型是什么?int?@Adam:事实上,操作数是biginger
s,但目前我不知道有多大。biginger没有实现像Karatsuba、Toom–Cook或FFT这样更智能的算法,所以时间是二次的
java.math.BigInteger的什么实现是这个引用/应用的?看起来这个将在大约O(N^2)
时间内运行。这对于OP.+1来说似乎已经足够好了,也就是说,它不是渐近最优的,因为它可以在O(N log(N)^2)
中完成,尽管使用非常难以实现的算法。在他当前的伪代码就绪的情况下,它在O(N)
时间内运行。他的代码缓存以前的乘法,因此只执行2*n
乘法。如果n
是输入参数的个数,@biginger
上的Sebastian乘法不是常数时间。啊,这很有意义。我不知道这是一个限制。是的,它吸引了很多人。对于java的biginger
,它的操作数大小可以慢到O(N^2)
。