为什么这两个Python函数返回不同的结果?

3

1-

 def fib1(n):
     a = 0
     b = 1
     while a < n:
        print b
        a = b
        b = a+b

2-

 def fib2(n):
     a, b = 0,1
     while a < n:
         print b
         a,b = b, b+a

执行时:

fib1(10) 我得到了错误的答案:0 1 2 4 8

fib2(10) 我得到了正确的答案:0 1 1 2 3 5 8


抱歉,我是说 def :) 打错字了。 - Moo
之前在这里看到过完全相同的问题。这个问题是从哪里来的? - AK47
3个回答

8

在斐波那契数列中,a = b 覆盖了 a 的值,这意味着对于语句 b = a+ba 不再是正确的值。

然而,在你的第二个例子中,这两件事情同时发生在一行代码 a,b = a, b+a 中,这意味着 a 仍然是正确的值。


我无法理解的是,这些事情如何同时发生?我猜在fib1()和fib2()中,a = b将用新的b = a + b覆盖a的值。 - Moo
1
右手边的操作发生在左手边赋值之前。因此,先计算 B+A 和 B 的值,然后将 b 赋值为 a + b,最后将 a 赋值为 b。 - dustinroepsch
1
例如,当您输入“b = a + b”时,首先会计算并在内存中临时存储a+b的值。 在完成该计算后,该值将被移动到b中。 在这种情况下也是如此,当输入“a,b = b,b + a”时,首先会计算并在内存中临时存储b+a的值,然后计算并在内存中临时存储b的值,最后b = a + b的计算值,并且a = b的计算值。 - dustinroepsch
终于搞定了,确实非常有帮助,谢谢 :) 最后一个问题,为什么fib2()中的第一个返回值是0?我猜应该是1。 - Moo
根据我的运行经验,代码输出的第一个数不是零。我运行 fib2(10) 的输出结果是 1 1 2 3 5 8 13。 - dustinroepsch

0

这里有一个快速的答案:

基本区别在于重新分配ab的值的方式。 在fib1()中,您有

a = b
b = a + b

fib2() 中,你有

a, b = b, b + a

现在,这两个看起来相等的语句实际上是不同的。

原因如下:

fib2() 中,你将元组 (b, b + a) 的值分配给元组 (a, b)。因此,重新分配值是同时进行的。

然而,在 fib1() 中,你首先使用 a = bb 的值赋给 a,然后将值 a + b 赋给 b。由于你已经改变了 a 的值,所以实际上你正在做:

b = a + b = b + b = 2b

换句话说,你正在执行 a,b = b,2b,这就是为什么你得到的是2的倍数而不是斐波那契数列的原因。

0

fib1 包含一个经典的错误。它与交换两个变量的值处于同一领域。想想你如何在 C 或 C++ 中完成这个操作。

int a = 3;
int b = 5;
int temp;
temp = a; /* 3 */
a = b; /* 5 */
b = temp; /* 3, hence swapped */

有一种方法可以不使用temp,尽管涉及中间计算。现在在Python中,如果你打算利用tuple解包特性,你必须涉及一个temp变量。

a = 3
b = 5
temp = a
a = b
b = temp

或者

a = 3
b = 5
a_ = (a+b)/2 - (a-b)/2 # 5.0
b_ = (a+b)/2 + (a-b)/2 # 3.0

最好使用元组拆包,就像在fib2中一样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接