NumberFormatException:无限或NaN

Kar*_*eem 4 java fibonacci numberformatexception

我有一个方法,取n并返回第n个斐波纳契数.在方法实现中,我使用BigDecimal获取第n个Fibonacci数,然后我使用方法toBigInteger()将数字作为BigInteger对象获取,这肯定是因为我在我的应用程序中处理大量数字.

我一直得到正确的结果,直到我通过1475作为我的方法的参数.NumberFormatException: Infinite or NaN在没有任何明确理由的情况下,我遇到了这种情况.

你能解释一下我为什么会得到这个例外吗?

这是我的方法:

BigInteger getFib(int n){
     double phi = (1 + Math.sqrt(5))/2;
     double squareRoot = (Math.sqrt(5)) + (1/2);
     BigDecimal bd = new BigDecimal(Math.floor(Math.pow(phi, n)/(squareRoot)));
     return bd.toBigInteger();
}
Run Code Online (Sandbox Code Playgroud)

Bla*_*ker 5

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();
}
Run Code Online (Sandbox Code Playgroud)

从公式:在此输入图像描述

更新: 上面的方法不正确,因为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;
    }
}
Run Code Online (Sandbox Code Playgroud)

它在我的计算机上花费7毫秒,n = 2000.