我正在尝试使用递归实现Euclid's algorithm for computing the greatest common divisor。下面是相同的代码。
def euclid(a,b):
if a>b:
r=a%b
if (r == 0):
return b
else:
a=b
b=r
euclid(a,b)
print(euclid(20,4)) # Returns 4
print(euclid(20,8)) # Returns None
对于第一个数据集,我得到了正确的结果。但是对于euclid(20,8)
,我得到了None
的回报。
在调试器中进行检查时,确实看到了b
的返回值变为4
,但是由于某种原因,我的代码跳到了euclid(a,b)
并返回了None
。
这里的主要收获是要理解为什么代码不返回4
而是跳转到euclid(a,b)
并返回None
的原因。
请避免提供其他代码解决方案,但我们非常鼓励您指出当前代码行为的原因。
答案 0 :(得分:1)
您实际上并没有在else
路径中返回 任何东西,因此它只是假设您最了解并为您返回None
。
您为4
获得print(euclid(20,4))
的唯一原因是因为4
是20
的因数,所以请不要使用 {{1} }路径。而是立即返回else
。对于其他任何事情,从第一次递归调用b
返回的东西将始终为euclid()
(即使对该函数的较低调用返回了某些内容,您也从第一次调用返回时将其丢弃了)。
您需要None
而不是return euclid(a,b)
。
顺便说一句(这不是回答您的特定问题所必需的,但是它对改进代码的实现有很大帮助),我不是euclid(a,b)
构造的忠实拥护者,因为{ {1}}是完全多余的(如果未返回,则if something then return else …
位是自动的)。
此外,当您只需更改传递到下一个递归级别的内容时,就不需要分配变量。
考虑到这两个因素(并简化了很多步骤),您可以执行以下操作:
else
答案 1 :(得分:1)
该代码有时会返回None
的原因是,在控制流中,您最终会遇到没有return
语句的情况,例如您的第一个a <= b
中的if
或第二个r != 0
中的if
时。在这种情况下,Python的默认行为是返回None
,因为您似乎已经发现了困难的方法。
def euclid(a,b):
if a>b:
r=a%b
if (r == 0):
return b
else: # <--- no `return` in this branch!
a=b
b=r
euclid(a,b)
# else: # <--- no `return` in this branch!
# ...
这是您代码的更新版本,可以解决该问题以及许多其他问题:
if
,因为随后的代码会处理它:计算r
,而递归调用将交换a
和{{1 }},如果是b
,如果是a < b
,那么是a == b
,那么您将直接返回r == 0
b
和a = b
毫无用处,请不要使用它们,只需让您的递归调用直接使用b = r
和b
r
可以用一行写得更清楚if
答案 2 :(得分:0)
您的代码存在缩进错误,并且代码中缺少一个路径(r!= 0)。应该是
def euclid(a,b):
if a>=b:
r=a%b
if (r == 0):
return b
return euclid(b, r)
else:
return euclid(b, a)