【问题标题】:fibonacci works in python but fails in Javafibonacci 在 python 中工作,但在 Java 中失败
【发布时间】:2014-03-02 09:31:01
【问题描述】:

我有这段代码用于计算python 中的fibonacci 数字。它有效并给出了预期的结果。但是当我把它翻译成Java时,它失败了。知道这里出了什么问题吗?

python:

def fib3(n): 
  a,b=0,1
  while n>0:
      a,b=b,a+b
      n-=1
  return a

fib3(12) --> 144

Java

 public static int fib2(int n){
        int a = 0;
        int b =1;
        while(n-- >0){
            a=b;
            b=a+b;

        }
    return a;
}

fib2(12) --> 2048

【问题讨论】:

  • 这可能与 a=b 行在计算下一行 a + b 之前更改了 a 的值有关。
  • 与 python 或 java 无关。同样在 python 中 a = b; b = a+b 将无法按预期工作。

标签: java python fibonacci


【解决方案1】:

问题是你必须从ba 一个值同时 分配给b @ 的总和987654324@ 和b。如果同时交换错了,你就会得到错误的答案。

本着 Python 代码的精神,我提出:

public static int fib(int n) {
    int a = 0, b = 1;
    while (n-->0)
        b = a + (a = b);
    return a;
}

这在添加的同时有效地进行了交换(严格来说不是,但已经足够好了)。请注意,这是定义明确 Java,因为该语言精确地定义了运算符的求值顺序,这与 C 和 C++ 不同(在 C 和 C++ 中,允许与上述代码等效的代码让恶魔飞出你的鼻子由于是未定义的行为)。


好的,如果它确实让你遇到了鼻恶魔的问题,我建议以后不要使用那个编译器。但是你不能保证得到一个正确的 fib() 函数……

【讨论】:

  • 作为记录,如果我在我维护的代码中看到任何类似的技巧,我将其重构为更简单(如果更冗长)的语句。过多的技巧总是重构的好理由!
  • 另外,对于 fib(largevalue),如果您需要速度,通常最好使用基于 Gamma 函数的东西。 (当我需要它时,我总是需要查找它,几乎从来没有。)
【解决方案2】:

在本节中:

a=b;
b=a+b;

您将b 分配给a+b,但a 已经是b。所以真的你加倍b

最简单的解决方案是临时变量:

public static int fib2(int n){
    int a = 0;
    int b =1;
    while(n-- >0){
        int old_a;
        old_a = a;
        a=b;
        b=old_a+b;
    }
    return a;
}

在 python 中,a, b = b, a + b 在将新值分配给变量之前会自动存储一个中间 tuple,而在 Java 中,您需要明确说明它

分解 Python 的指令,a, b = b, a + b 正在执行这个反汇编:

  5          17 LOAD_FAST                1 (b)
             20 LOAD_FAST                0 (a)
             23 LOAD_FAST                1 (b)
             26 BINARY_ADD
             27 ROT_TWO
             28 STORE_FAST               0 (a)
             31 STORE_FAST               1 (b)

在更简单的意义上,保持python,这是过程:

temp_tuple = (b, a + b)
a, b = temp_tuple

【讨论】:

  • 呸!你比我快 13 秒
  • 你能详细说明一下中间元组部分吗?我想这让我很困惑..
  • 当然。我已经用更多信息更新了答案
  • 我没有机会写答案。无论如何,我可以建议 1 编辑吗?在 while 中定义 old_a。它在范围之外没有用处。
  • 答案可能是:从不将 Python 代码复制到 Eclipse,几乎不做语法调整,并认为它可以工作
【解决方案3】:

在 java 中 - 当你写“a=b; b=a+b;”时你本质上是说a应该等于be然后(因为'a'现在等于'b')'b'应该是原来的两倍。 有两种方法可以解决此问题。 1)您可以继续您最初使用的功能,然后在更改“a”之前创建一个 int 'temp' 来存储“a”。 2)你也可以做我想做的事情(这将花费更多的时间,但是对于像斐波那契这样的算法,对于现实世界的应用程序来说通常是一个糟糕的主意)是使用一个会调用自身的递归函数。

它通常如下所示。

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

这可能不是确切的代码,但非常相似。希望对您有所帮助!

【讨论】:

    【解决方案4】:

    代码不等价,依赖python在一行中分配多个原语的能力a,b=b,a+b;你需要一个临时变量 -

    public static int fib2(int n){
      int a = 0;
      int b =1;
      while(n-- >0){
          int t = b; // <-- to hold the original value of b.
          b = a + b;
          a = t;
      }
      return a;
    }
    

    【讨论】:

    • a,b=b,a+b 在 python 中作为 a = b;其次是 b = a+b..正确吗?
    • @eagertoLearn 差不多。第一个表达式 (b) 的结果分配给 a,第二个表达式 (a+b) 分配给 b,但在分配之前计算完成。
    【解决方案5】:
    a = b;
    b = a+b;
    

    这会计算 b = 2*b,因为在您计算 b 的新值时,a 的值会被覆盖。替换为:

    t = b;
    b = a+b;
    a = t
    

    【讨论】:

      【解决方案6】:
      a=b;
      b=a+b;
      

      ... 是问题所在。您需要先保存 a 的旧值,然后再将其添加到 b

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-08
        • 1970-01-01
        • 1970-01-01
        • 2011-10-05
        • 2013-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多