我是Python新手,我一直在使用它,但我遇到了问题。这是我的代码:
def collatz(num,ctr):
if(num != 1):
ctr+=1
if(num%2==0):
collatz(num/2,ctr)
else:
collatz(num*3+1,ctr)
return ctr
test=collatz(9,0)
对于我为num
输入的任何数字,例如,我们说9
,0
ctr
,ctr
始终显示为1
1}}。我使用ctr
变量错了吗?
编辑:
我试图打印出函数被递归的次数。所以ctr
将成为每次递归的计数器。
答案 0 :(得分:3)
我更改了你的递归调用,将从递归调用中收到的值设置为ctr。你写它的方式,你丢弃了从递归中得到的值。
def collatz(num,ctr):
if(num != 1):
ctr+=1
if(num%2==0):
ctr=collatz(num/2,ctr)
else:
ctr=collatz(num*3+1,ctr)
return ctr
test=collatz(9,0)
答案 1 :(得分:3)
由于递归调用堆栈的顺序,示例中的变量ctr
将始终为1
。当返回一个ctr
值时,调用堆栈将开始返回先前的ctr
值。基本上,在最后一次递归调用时,将返回ctr
的最高值。但是,由于调用堆栈底部的方法调用返回最后一个值,即将存储在test
中的值,test
将始终为1
。让我们说我将参数输入collatz
,这将导致该方法的五次调用。调用堆栈看起来会像这样下降,
collatz returns ctr --> 5
collatz returns ctr --> 4
collatz returns ctr --> 3
collatz returns ctr --> 2
collatz returns ctr --> 1 //what matters because ctr is being returned with every method call
正如您所看到的,无论调用collatz
多少次,都会始终返回1
,因为调用堆栈底部的调用等于ctr
1
}}
解决方案可以是很多东西,但它实际上取决于你想要完成的目的,而你的问题并没有明确说明。
编辑:如果您希望ctr
最终成为递归调用的次数,则只需将ctr
分配给方法调用的值。它看起来应该是这样的,
def collatz(num,ctr):
if(num != 1):
ctr+=1
if(num%2==0):
ctr = collatz(num/2,ctr)
else:
ttr = collatz(num*3+1,ctr)
return ctr
test=collatz(9,0)
答案 2 :(得分:0)
一个例子:
def collatz(number):
if number % 2 == 0:
print(number // 2)
return number // 2
elif number % 2 == 1:
result = 3 * number + 1
print(result)
return result
n = input("Give me a number: ")
while n != 1:
n = collatz(int(n))
答案 3 :(得分:0)
Python中的函数参数是按值传递的,而不是通过引用传递的。如果将数字传递给函数,函数将接收该数字的副本。如果函数修改了其参数,则在函数外部将不会显示该更改:
def foo(y):
y += 1
print("y=", y) # prints 11
x = 10
foo(x)
print("x=", x) # Still 10
在您的情况下,最直接的解决方法是将ctr转换为全局变量。它非常难看,因为如果你想再次调用collatz函数你需要将全局重置为0,但是我只是为了表明你的逻辑是正确的,除了传递引用位之外。 (请注意,collatz函数现在不返回任何内容,答案在全局变量中。)
ctr = 0
def collatz(num):
global ctr
if(num != 1):
ctr+=1
if(num%2==0):
collatz(num/2)
else:
collatz(num*3+1)
ctr = 0
collatz(9)
print(ctr)
由于Python没有尾调用优化,如果collatz序列超过1000步(如Pythons默认堆栈限制),则当前的递归代码将因堆栈溢出而崩溃。您可以通过使用循环而不是递归来避免此问题。这也可以让我们摆脱那个麻烦的全局变量。在我看来,最终的结果是更惯用的Python:
def collats(num):
ctr = 0
while num != 1:
ctr += 1
if num % 2 == 0:
num = num/2
else:
num = 3*num + 1
return ctr
print(collatz(9))
如果你想坚持使用递归函数,它通常更干净,以避免使用像你试图做的可变赋值。而不是函数是修改状态的“子程序”,而是将它们变成更接近数学函数的东西,它接收一个值并返回仅依赖于输入的结果。如果你这样做,可以更容易推理递归。我将此作为练习,但递归函数的典型“骨架”是使用if语句检查基本情况和递归情况:
def collatz(n):
if n == 1:
return 0
else if n % 2 == 0:
# tip: something involving collatz(n/2)
return #???
else:
# tip: something involving collatz(3*n+1)
return #???
答案 4 :(得分:-3)
变量将从你输入的任何数字开始返回最后一个collatz序列号.colltz猜想说这将永远是1