Java 通过DnC计算阶乘
我试图通过分治策略实现阶乘函数。我使用ForkJoin框架对每个递归任务进行fork,以加快计算速度。 但我发现它并没有像我预期的那样加速。 在不使用ForkJoin的情况下,计算50000的阶乘需要28秒,而 我使用ForkJoin时花了25秒。 这是不带forkjoin的代码:Java 通过DnC计算阶乘,java,java-7,fork-join,Java,Java 7,Fork Join,我试图通过分治策略实现阶乘函数。我使用ForkJoin框架对每个递归任务进行fork,以加快计算速度。 但我发现它并没有像我预期的那样加速。 在不使用ForkJoin的情况下,计算50000的阶乘需要28秒,而 我使用ForkJoin时花了25秒。 这是不带forkjoin的代码: public static BigInteger factorial(long p, long q) { if (q < p) { return new BigInteger("1");
public static BigInteger factorial(long p, long q) {
if (q < p) {
return new BigInteger("1");
}
if (p == q) {
return new BigInteger("" + p);
}
BigInteger fact = new BigInteger("1");
fact = fact.multiply(factorial(p, (p + q) / 2)).multiply(factorial((p + q) / 2 + 1, q));
return fact;
}
公共静态BigInteger阶乘(长p,长q){
if(q
这是forkJoin的代码:
public class Factorial extends RecursiveTask<BigInteger>{
private long p, q;
public Factorial(long p, long q) {
this.p = p;
this.q = q;
}
@Override
public BigInteger compute() {
if(q < p) {
return new BigInteger("1");
}
if( p == q) {
return new BigInteger(""+p);
}
Factorial f1 = new Factorial(p, (p+q)/2);
Factorial f2 = new Factorial((p+q)/2 + 1, q);
f2.fork();
return f1.compute().multiply(f2.join());
}
}
公共类阶乘扩展递归任务{
私人长p,q;
公因子(长p,长q){
这个,p=p;
这个。q=q;
}
@凌驾
公共BigInteger计算(){
if(q
我哪里做错了?我不认为这是Fork/Join的结果。请帮忙 Fork/Join可以并行计算。它是:给你一个恒定的增益(通过示例将时间除以4)。这取决于您拥有的实际CPU(例如,200个线程将只共享相同的4个CPU) 相比之下,阶乘(典型的算法)是
O(N!)
这意味着它增长得非常快
如果您为每一步创建一个新分支,那么分支和连接的开销将补偿并行化带来的收益
所以重要的是用另一种算法来计算阶乘,这种算法不是O(N!)
。如果应用动态规划(继续中间结果),可以将其转换为O(N)
我不知道你试图模仿的算法,我应该做的是画一个矩阵或是一些成对的计算,以便在我第二次需要它们时重用它们
查看您的代码,我可以看到每个阶乘方法执行都会引发两个子执行:
(p+q)/2,q
和p,(p+q)/2+1
。。。或者类似的。如果每次阶乘方法都找到一个结果,并将其保存在一个映射中[Pair->BigDecimal]
,则可以在方法的开头查询此缓存。使此映射成为类的成员(或通过参数传递),以便不同的方法调用共享该映射
factorial(p,q) {
if (there is result for (p,q) in the map)
return it
else
{
normal computation (provokes two child invocations)
save result into cache
}
}
如果您需要计算大量的阶乘,那么您应该在您需要的范围内计算阶乘,然后重用它。您不能以有效的方式同时执行阶乘计算。有关使用BigInteger的性能提示:将新的BigInteger(“1”)替换为常量;用
biginger.valueOf(p)
替换新的biginger(“+p)。这会更快,并尽可能重用以前创建的实例。@Maurício对于较大的n值,使用并行算法计算n!现在是已知最快的。请参阅