java-计算BigInteger的乘积[]

上下文:我正在尝试使用Java中的BigInteger类(对于n> 100,000)来计算非常大的n的阶乘,到目前为止,我正在做什么:

>使用Erasthones筛产生所有小于或等于n的素数
>查找将提高到哪些能力.
>将所有数字加到各自的幂.
>使用分治法递归方法将它们全部相乘.

根据我在互联网上所做的研究,这比简单地将所有k乘以n渐近地快.但是,我注意到,实现过程中最慢的部分是我将所有素数乘以的部分.我的问题是:

>是否有更快的方法来计算大量数字的乘积?
>我的实施可以改善吗?

码:

public static BigInteger product(BigInteger[] numbers) {
    if (numbers.length == 0)
        throw new ArithmeticException("There is nothing to multiply!");
    if (numbers.length == 1)
        return numbers[0];
    if (numbers.length == 2)
        return numbers[0].multiply(numbers[1]);

    BigInteger[] part1 = new BigInteger[numbers.length / 2];
    BigInteger[] part2 = new BigInteger[numbers.length - numbers.length / 2];
    System.arraycopy(numbers, 0, part1, 0, numbers.length / 2);
    System.arraycopy(numbers, numbers.length / 2, part2, 0, numbers.length - numbers.length / 2);

    return product(part1).multiply(product(part2));
}

>请注意,BigInteger使用karatsuba算法进行乘法.
>我知道关于计算阶乘有很多问题.但是我的工作是计算没有太多资源的BigIntegers乘积. (我见过有人说“使用分而治之方法”,但我不记得在哪里,也没有见到任何实现.

解决方法:

一种提高性能的方法是执行以下操作:

>对您需要相乘的数字数组进行排序
>创建两个新列表:a和b.
>对于输入列表中您需要相乘的每个数字,它可能会出现多次.假设数字v_i出现了n_i次.然后将v_i加到a n_i / 2次(向下舍入).如果n_i为奇数,请将v_i也添加一次.
>要计算结果,请执行以下操作:

BigInteger A = product(a);
BigInteger B = prudoct(b);
return a.multiply(a).multiply(b);

要查看其工作原理,请考虑您的输入数组为[2,2,2,2,2,3,3,3].因此,有四个2和三个3.数组a和b将分别为

a = [2, 2, 3]
b = [3]

然后,您将递归调用以计算这些乘积.请注意,我们将要乘数的数量从7减少到4,几乎减少了两倍.这里的窍门是,对于多次出现的数字,我们只能计算其中一半的乘积,然后将其乘以2的幂.非常类似于如何在O(log n)时间中计算数字的幂.

上一篇:c#-将所有低序位设置为0,直到剩下两个1(用于存储为字节数组的数字)


下一篇:求大数