【问题标题】:Recursive Fibonacci using BigInteger in Java [duplicate]在Java中使用BigInteger的递归斐波那契[重复]
【发布时间】:2017-05-08 03:36:53
【问题描述】:

我正在尝试解决 java 中的项目 euler 25 问题,因为我需要一些东西来存储 10000 位数字,所以我正在使用 BigInteger 类。

所以我正在使用 BigIntegers 处理一些递归斐波那契序列,我正在尝试转换此代码:

public int fibonacci(int n)  {
    if (n == 0)
        return 0;
    else if (n == 1)
        return 1;
    else
        return fibonacci(n - 1) + fibonacci(n - 2);
}

来自此链接:Java recursive Fibonacci sequence

到相同的代码,但使用 BigIntegers。

所以,这就是我目前所拥有的:

public static BigInteger fibonacci(BigInteger index) {
    if (index.compareTo(BigInteger.ZERO) == 0)
        return BigInteger.ZERO;
    else if (index.compareTo(BigInteger.valueOf(1)) == 1)
        return BigInteger.ONE;
    else
        return fibonacci(index.subtract(BigInteger.ONE)).add(fibonacci(index.subtract(BigInteger.valueOf(2))));
}

public static int numberOfDigits(BigInteger fibonacci) {
    return Integer.valueOf(fibonacci.toString().length());
}

public static void main(String[] args) {
    long startTime = System.nanoTime();
    for (BigInteger i = new BigInteger("1"); numberOfDigits(fibonacci(i)) <= 1000; i = i.add(BigInteger.ONE))
        System.out.println(" " + i + "  -  " + fibonacci(i) + "  -  " + numberOfDigits(fibonacci(i)));
    long endTime = System.nanoTime();
    long duration = (endTime - startTime);
    System.out.println("Duration: " + duration/1000000 + " ms");
}

当我运行它时,我得到一个StackOverFlowError,像这样:

Exception in thread "main" java.lang.StackOverflowError
    at java.math.BigInteger.subtract(BigInteger.java:1423)
    at Problem25Part2.fibonacci(Problem25Part2.java:19)
    at Problem25Part2.fibonacci(Problem25Part2.java:19)
    at Problem25Part2.fibonacci(Problem25Part2.java:19)
    at Problem25Part2.fibonacci(Problem25Part2.java:19)

我想它会重复 1000 次。 好吧,我不知道出了什么问题,所以请你们帮帮我吗?谢谢!

【问题讨论】:

  • 只需将程序转换为非递归形式即可。此外,使用 DP 将使该程序更快。正如StackOverflowError 所指出的那样,递归绝对不是这里的方法。
  • 你不应该使用蛮力来解决项目欧拉问题。为什么使用 BigIntegers ?这个问题的重点不是大数,而是找到一种使计算时间可以接受的方法。多想想一种限制计算次数的有效方法,你就不需要任何花哨的类了:)
  • 谢谢你们。认为递归更快,但我现在正在运行它,我看到它的方式更慢。谢谢!

标签: java fibonacci


【解决方案1】:

我认为你有递归的标准问题......这是斐波那契方法的问题,因为你没有地方,当这个方法必须返回最终结果时,所以请检查你的条件和更多关于 BigInteger 中的比较。推荐阅读尾递归

【讨论】:

    【解决方案2】:

    当您使用compare() 时,如果参数高于实际值,则返回 1。

    所以你应该修改这段代码:

    else if (index.compareTo(BigInteger.valueOf(1)) == 1)
    

    为此:

    else if (index.compareTo(BigInteger.valueOf(1)) == 0)
    

    【讨论】:

    • 非常感谢。现在它正在运行。有趣的是,我认为它会比斐波那契的替代方法运行得更快,但似乎要慢得多。
    【解决方案3】:

    Java 不能很好地处理深度递归。您应该改为使用循环。

    另请参阅尾递归的此线程:https://softwareengineering.stackexchange.com/questions/272061/why-doesnt-java-have-optimization-for-tail-recursion-at-all

    【讨论】:

    • 这点很好,一些语言可以处理尾递归而不会占用堆栈。
    【解决方案4】:

    您可以尝试使用动态规划来降低空间复杂度。像这样的东西应该可以工作:

    public static BigInteger fibonacci(BigInteger n) {
        if (n.compareTo(BigInteger.valueOf(3L)) < 0) {
            return BigInteger.ONE;
        }
        //Map to store the previous results
        Map<BigInteger, BigInteger> computedValues = new HashMap<BigInteger, BigInteger>();
        //The two edge cases
        computedValues.put(BigInteger.ONE, BigInteger.ONE);
        computedValues.put(BigInteger.valueOf(2L), BigInteger.ONE);
        return fibonacci(n, computedValues);
    }
    
    private static BigInteger fibonacci(BigInteger n, Map<BigInteger, BigInteger> computedValues) {
        if (computedValues.containsKey(n))
            return computedValues.get(n);
        BigInteger n1 = n.subtract(BigInteger.ONE);
        BigInteger n2 = n.subtract(BigInteger.ONE).subtract(BigInteger.ONE);
        computedValues.put(n1, fibonacci(n1, computedValues));
        computedValues.put(n2, fibonacci(n2, computedValues));
        BigInteger newValue = computedValues.get(n1).add(computedValues.get(n2));
        computedValues.put(n, newValue);
        return newValue;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-03
      • 2019-01-21
      • 2012-02-16
      • 1970-01-01
      • 2014-04-02
      • 2018-06-22
      • 1970-01-01
      相关资源
      最近更新 更多