n > 46 Java 的斐波那契数列

Fibonacci sequence for n > 46 Java

我有以下代码,它为 n < 47 提供了正确的值。

public static int fib(int n) {
    int nthTerm = 0;
    if (n == 2)
        nthTerm = 1;
    else {
        double goldenRatio = (1 + Math.sqrt(5)) / 2;
        nthTerm = (int) (Math.round(Math.pow(goldenRatio, n)
                - Math.pow(1 - goldenRatio, n)) / Math.sqrt(5));

        if (n % 2 == 1 && n < 45)
            nthTerm++;
    }
    return nthTerm;
}

n > 46 的任何值都超出了 int 范围。我怎样才能使这种方法适用于 n > 46?

P.S。我知道 BigInteger,但不是很擅长,所以我也希望能有一个使用 BigInteger 的示例。

使用 long 而不是 int,并且记得将值从 Math.round() 转换为 long(通过编写 (long) Math.round(...) 就像你投射到 int) .

你不能使用 int 的原因是因为 fib(47)2971215073 溢出了 Java 的签名 32 位 int (231-1). You could use a memoization optimization to implement it with BigInteger喜欢,

private static Map<Integer, BigInteger> memo = new HashMap<>();
static {
    memo.put(0, BigInteger.ZERO);
    memo.put(1, BigInteger.ONE);
}

public static BigInteger fib(int n) {
    if (memo.containsKey(n)) {
        return memo.get(n);
    }
    BigInteger v = fib(n - 2).add(fib(n - 1));
    memo.put(n, v);
    return v;
}

如果使用long,则完美支持1000以上的范围;但是如果你想支持所有可能的值,那么你需要使用 BigInteger.

示例使用 long:

public static long fib(int n) 
{
    long f0 = 1;
    long f1 = 1;

    long c = 2;

    while(c < n)
    {
        long tmp = f0+f1;
        f0 = f1;
        f1 = tmp;
        c++;
    }

    return f1;
}

您可以使用它来将代码转换为 BigInteger。

package your.pack

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * Created on 3/6/16.
 */
public class Fibonacci {

    private static BigDecimal goldenRatio = new BigDecimal((1 + Math.sqrt(5)) / 2);
    private static BigDecimal goldenRatioMin1 = goldenRatio.subtract(BigDecimal.ONE);
    private static BigDecimal sqrt5 = new BigDecimal(Math.sqrt(5));

    private static BigInteger fib(int n) {
        BigInteger nthTerm = new BigInteger("0");
        if (n == 2)
            nthTerm = BigInteger.ONE;
        else {
            BigDecimal minResult = goldenRatio.pow(n).subtract(goldenRatioMin1.pow(n));
            nthTerm = minResult.divide(sqrt5,0).toBigInteger();

            if (n % 2 == 1 && n < 45){
                nthTerm = nthTerm.add(BigInteger.ONE);
            }

        }
        return nthTerm;
    }

    private static int fib2(int n) {
        int nthTerm = 0;
        if (n == 2)
            nthTerm = 1;
        else {
            double goldenRatio = (1 + Math.sqrt(5)) / 2;
            nthTerm = (int) (Math.round(Math.pow(goldenRatio, n)
                    - Math.pow(1 - goldenRatio, n)) / Math.sqrt(5));

            if (n % 2 == 1 && n < 45)
                nthTerm++;
        }
        return nthTerm;
    }

    public static void main(String []args){
        System.out.println(
                fib(47)
        );
    }

}

方法fib2是你的代码,fib是转换成BigInteger。干杯