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步(這是蟒蛇默認堆棧限制)。您可以通過使用循環而不是遞歸來避免此問題。這也可以讓我們擺脫那個麻煩的全局變量。最終的結果是有點更地道的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))
如果你想堅持用遞歸函數,其一般清潔避免使用可變分配像你正在嘗試做的。函數不是修改狀態的「子程序」,而是使它們更接近數學函數,它接收一個值並返回僅依賴於輸入的結果。如果你這樣做,遞歸推理可能會容易得多。我將離開這個作爲一個練習,但典型的「骨架」的遞歸函數是有一個如果檢查的基本情況和遞歸的情況下聲明:
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 #???
什麼是預期的結果,你想什麼用這個實現? – harshil9968
'ctr = collatz(num // 2,ctr)'。你也應該使用Python 3,而'/ 2'是浮點除法,'// 2'是整數除法。 –