有效计算非常大因子的数字的方法

时间:2014-07-31 15:20:58

标签: java factorial

假设我们有一个非常大的阶乘,例如(10 ^ 7)!,是否有一种有效的方法来计算其精确数字? (Wolfram alpha结果说(10 ^ 7)!有65,657060位数)

当然,我不能一个接一个地使用这个值来使用天真的实现,因为评估结果会太慢。

我认为这个问题的解决方案最终可能会出现在

  1. 如何在不计算阶乘
  2. 的情况下找到阶乘的数字
  3. 如何更有效地计算阶乘(最好是BigInteger或BigDecimal)
  4. 我更喜欢1.而不是2.因为我只想知道阶乘的位数。 有什么建议吗?

2 个答案:

答案 0 :(得分:3)

添加您将乘以的所有数字的日志应该可以解决问题:

public long facDigits(long n) {
    double logFacN = 0;
    for (long i = 2; i <= n; i++) {
        logFacN += Math.log10(i);
    }
    return (long) logFacN + 1;
}

public void test() {
    double tenToThe7th = Math.pow(10, 7);
    long digits = facDigits((long) tenToThe7th);
    System.out.println("Digits in " + tenToThe7th + "! = " + digits);
}

打印

Digits in 1.0E7! = 65657060

这里的逻辑是,当您在计算阶乘时乘以x,实际上您正在添加log10(x)数字,所以我在这里添加它们。

答案 1 :(得分:0)

@OldCurmudgeon 的解决方案很好,但您可以尝试使用 Kamentsky 的公式:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int numOfTests = Integer.parseInt(in.readLine());

        in.lines()
                .limit(numOfTests)
                .map(n -> Integer.parseInt(n))
                .forEach(n -> System.out.println(KamenetskyFormula(n)));
    }

    private static long KamenetskyFormula(int n) {
        if (n < 2) {
            return 1;
        }
        double x = n * Math.log10(n / Math.E) + Math.log10(2 * Math.PI * n) / 2.0;
        return (long) (Math.floor(x) + 1);
    }
}

连接到Count number of digits in factorial - performance issue