BigInteger 的乘法与并行乘法方法

有时,在使用 Java 编程时,我们可能需要处理超出原始类型(如long类型)限制的整数值。BigInteger类允许我们做到这一点。例如,我们需要使用BigInteger类来计算100的阶乘。

BigInteger类提供了两种公共乘法方法,multiply和parallelMultiply。虽然它们的用法相似并且返回相同的数学结果,但在某些情况下,其中一种可能比另一种更可取。

在本教程中,我们将比较BigInteger类的multiply和parallelMultiply方法。

乘法​
BigInteger类的multiply方法将两个BigInteger实例相乘。让我们看一个示例来演示如何使用此方法:

BigInteger bigInteger1 = new BigInteger("131224324234234234234313");
BigInteger bigInteger2 = new BigInteger(
"13345663456346435648234313");
BigInteger result = bigInteger1.multiply(bigInteger2);

创建两个BigInteger实例bigInteger1和bigInteger2后,我们使用multiply( )方法将它们相乘。我们将乘法结果赋给结果变量,该变量也是BigInteger类型。

parallelMultiply方法
BigInteger类的parallelMultiply方法是将两个BigInteger实例相乘的另一种方法。其用法与m​​ultiply方法的用法类似:

BigInteger bigInteger1 = new BigInteger("131224324234234234234313");
BigInteger bigInteger2 = new BigInteger(
"13345663456346435648234313");
BigInteger result = bigInteger1.parallelMultiply(bigInteger2);

此方法自 Java 19 起可用。

实现方式比较
我们先来比较一下这两种方法的实现。BigInteger.java中的公共乘法方法调用了私有乘法方法:

public BigInteger multiply(BigInteger val) {
    return multiply(val, false, false, 0);
}

parallelMultiply方法也调用相同的私有乘法方法:

public BigInteger parallelMultiply(BigInteger val) {
    return multiply(val, false, true, 0);
}

它们之间的区别在于multiply的第三个参数的值。第一个参数为false ,而第二个参数为true 。让我们检查私有multiply方法的签名及其返回类型:

private BigInteger multiply(BigInteger val, boolean isRecursion, boolean parallel, int depth)

第三个参数的名字是parallel,这个参数指定乘法运算是否以并行方式进行。

实际上,乘法通过根据乘数和被乘数的值使用不同的算法来加速乘法过程。它对大数使用Karatsuba 算法,对由几千位组成的大数使用三向 Toom-Cook 算法。

三路 Toom Cook 算法可以将两个大整数拆分为较小的整数,并并行化较小整数的乘法。因此,它降低了计算时间复杂度,从而加快了计算速度。因此,我们可能更喜欢在乘以大数时使用parallelMultiply方法。但是,parallelMultiply方法可能会使用更多的 CPU 和内存来更快地计算乘法。

根据报告的测试结果,使用parallelMultiply计算第100000000 个 斐波那契数列可能比使用multiply快 2.75 倍。