问题
I have the following code which provides the correct values for 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;
}
Any value for n > 46 is out of int range. How could I adapt this approach to work for n > 46?
P.S. I know of BigInteger but am not very adept at it so I would appreciate an example using BigInteger, too.
回答1:
You can use this for transformated code into 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)
        );
    }
}
Method fib2 is your code, fib is the transformed into BigInteger. Cheers
回答2:
Use long instead of using int, and remember to cast the value from Math.round() to long as well (by writing (long) Math.round(...) just as you casted to int) .
回答3:
The reason you can't use int is because fib(47) is 2971215073 which overflows Java's signed 32-bit int (231-1). You could use a memoization optimization to implement it with BigInteger like,
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;
}
    回答4:
If you use long, you support perfectly the range over 1000; but if you want support all possible value then you need use BigInteger.
A example use 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;
}
    来源:https://stackoverflow.com/questions/35822235/fibonacci-sequence-for-n-46-java