【问题标题】:Fibonacci sequence using BigInteger Does not yield an answer使用 BigInteger 的斐波那契数列不产生答案
【发布时间】:2021-05-17 00:26:42
【问题描述】:

我想找到斐波那契数列的第 100 个元素,我最初尝试使用 int 存储数字的值,但它溢出并切换到负值,就像 long 一样。
然后我遇到了 @987654324 @ 我确实使用简单的 for 循环和 array 来存储结果并访问以前的元素得到了解决方案。
现在我尝试使用 recursion 解决同样的问题要终止。我在这里错过了什么吗?还是不建议将 BigInteger 与递归一起使用?

这里是代码:

import java.math.BigInteger;

class Test {
  public static void main(String[] args) {
    BigInteger n = BigInteger.valueOf(100);
    System.out.println(fib(n));
  }

  public static BigInteger fib(BigInteger n) {
    if (n.compareTo(BigInteger.valueOf(1)) == 0 || n.compareTo(BigInteger.valueOf(1)) == -1)
      return n;
    return fib(n.subtract(BigInteger.valueOf(1))).add(fib(n.subtract(BigInteger.valueOf(2))));
  }
}

【问题讨论】:

  • 直到 100 非常长,而且您的方法性能不是最好的,因为您要多次计算大量值
  • 您是如何确定程序没有终止的?你打电话给fib 354224848179261915075 次,显然这需要一段时间。
  • 看看如何让它更快here
  • @MrakVladar:好吧,如果我们假设 fib 只需要一个时钟周期来执行(这是一个非常乐观的假设,因为在 Core i9 上,long 的简单 ADD已经占用了大约十几个时钟周期),我们进一步假设您有 4GHz CPU,那么fib(100) 将需要大约 2800 年。
  • if (n.compareTo(BigInteger.valueOf(1)) <= 0) 而不是if (n.compareTo(BigInteger.valueOf(1)) == 0 || n.compareTo(BigInteger.valueOf(1)) == -1)compareTo 对于“小于”结果不保证返回 -1,只有 一些 负数。

标签: java recursion fibonacci


【解决方案1】:

在 cmets 中,您提到您认为程序不会终止的假设是基于它运行了 5 分钟以上的事实。这不是你如何证明不终止。

如果您在一定时间内观察到程序终止,那么您可以得出结论,它确实会终止。但是,如果您没有观察到它在一定时间内终止,那么您可以准确地说什么关于它是否终止。如果你等待的时间长一点它可能会终止,如果你等待的时间更长它可能会终止,甚至理论上它可能会终止但比宇宙的热寂还要长。

在您的具体情况下,算法是完全正确的,并且总是终止。它根本不是一个非常有效的算法:对于计算 fib(n)fib 被调用 fib(n) 次,因为你一遍又一遍地计算相同的数字。

如果我们假设您可以在每个时钟周期执行一次fib(这是一个乐观的假设,因为对fib 的一次调用执行一个条件、两次减法、一次加法和两次对fib 的调用情况下,一个加法可能已经需要多个时钟周期,具体取决于 CPU),我们进一步假设你有一个 100 核 CPU,你的代码实际上是并行执行的,你有 100 个 CPU,每个 CPU 的时钟频率为100 GHz,并且您有一个由 100 台计算机组成的集群,那么仍然需要您大约一个小时。

在一些更现实的假设下,您的程序完成所需的时间更多的是数万年。

由于您的代码没有并行化,为了让您的代码在更真实的 4 GHz CPU 上在 5 分钟内完成,它需要执行 fib 几乎 300 百万每个时钟周期

对代码的预期性能进行一些非常粗略的猜测通常会有所帮助。如您所见,您无需成为 Java 或 JVM 或编译器或优化或计算机组织或 CPU 设计或性能工程方面的专家。你不需要知道你的代码究竟被编译成什么。您不需要知道整数ADD 需要多少个时钟周期。因为即使当你做出一些完全过分荒谬的假设时,你仍然可以很容易地看到你的代码不可能在几分钟内完成,或者偶数小时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-18
    • 2015-04-25
    • 1970-01-01
    • 2014-03-02
    • 1970-01-01
    • 2015-06-05
    相关资源
    最近更新 更多