Fibonacci sequence for n > 46 Java

血红的双手。 提交于 2019-12-02 09:51:33

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!