假设我们有一个非常大的阶乘,例如(10 ^ 7)!,是否有一种有效的方法来计算其精确数字? (Wolfram alpha结果说(10 ^ 7)!有65,657060位数)
当然,我不能一个接一个地使用这个值来使用天真的实现,因为评估结果会太慢。
我认为这个问题的解决方案最终可能会出现在
中我更喜欢1.而不是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);
}
}