【问题标题】:Fibonacci sequence for n > 46 Javan > 46 Java 的斐波那契数列
【发布时间】:2016-06-19 17:36:46
【问题描述】:

我有以下代码,它为 n

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?

附:我知道 BigInteger,但不是很擅长,所以我也很欣赏使用 BigInteger 的示例。

【问题讨论】:

  • 使用long 代替int
  • BigInteger 以支持long 范围之外的值。

标签: java fibonacci


【解决方案1】:

您可以将其用于将代码转换为 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。干杯

【讨论】:

    【解决方案2】:

    使用long 而不是int,并记住将值从Math.round() 转换为long(通过写入(long) Math.round(...),就像转换为int 一样)。

    【讨论】:

      【解决方案3】:

      您不能使用int 的原因是因为fib(47)2971215073,它溢出了Java 的签名32 位int (231-1)。您可以使用memoization 优化 来实现它与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;
      }
      

      【讨论】:

      • 为了获得更好的性能,只需执行get() 并检查null,因此n 不必被装箱两次,并且只执行一次哈希查找。
      【解决方案4】:

      如果你使用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;
      }
      

      【讨论】:

        猜你喜欢
        • 2015-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-10
        • 2015-06-05
        相关资源
        最近更新 更多