你Math.pow(phi, n)
的太大(Infinity),double 无法存储,请改用 BigDecimal。
流水怎么样:
static BigInteger getFib(int n) {
BigDecimal x1 = new BigDecimal((1 + Math.sqrt(5)) / 2);
BigDecimal x2 = new BigDecimal((1 - Math.sqrt(5)) / 2);
return x1.pow(n).subtract(x2.pow(n))
.divide(new BigDecimal(Math.sqrt(5))).toBigInteger();
}
从公式:
更新:
上述方式不正确,因为 Math.sqrt(5) 没有评论所说的足够精度。我尝试使用 Netown 的方法更精确地计算 sqrt(5),发现这x1.pow(n).subtract(x2.pow(n)).divide(...)
非常耗时,在我的计算机中 n = 200 花了大约 30 秒。
我认为使用缓存的递归方式更快:
public static void main(String[] args) {
long start = System.nanoTime();
System.out.println(fib(2000));
long end = System.nanoTime();
System.out.println("elapsed:"+ (TimeUnit.NANOSECONDS.toMillis(end - start)) + " ms");
}
private static Map<Integer, BigInteger> cache = new HashMap<Integer, BigInteger>();
public static BigInteger fib(int n) {
BigInteger bi = cache.get(n);
if (bi != null) {
return bi;
}
if (n <= 1) {
return BigInteger.valueOf(n);
} else {
bi = fib(n - 1).add(fib(n - 2));
cache.put(n, bi);
return bi;
}
}
对于 n = 2000,它在我的计算机上花费了 7 毫秒。