[英]Make recursive function iterative?
當我運行以下模塊時,它將運行約960次遞歸:
import matplotlib
import pylab
xStart = 1
debug = 'off'
xList = []
calcList = []
def collatzCalc(xStart,calcs):
calc = 0
xCalc = 0
xCalc = xStart
while xCalc > 0:
if debug == 'on':
print(round(xCalc))
print(xList)
print(calcList)
if xCalc == 1:
xList.append(xStart)
calcList.append(calc)
xStart += 1
if debug == 'on':
print(calcs)
print('---------------------------')
calcs += 1
collatzCalc(xStart,calcs)
else:
if xCalc % 2 == 0:
xCalc = xCalc / 2
calc += 1
else:
xCalc = xCalc * 3 + 1
calc += 1
calcs = 0
collatzCalc(xStart,calcs)
它引發以下錯誤:
Traceback (most recent call last):
File "C:\Users\Erin Lynch\Desktop\collatzConjecture.py", line 49, in <module>
collatzCalc(xStart,calcs)
File "C:\Users\Erin Lynch\Desktop\collatzConjecture.py", line 32, in collatzCalc
collatzCalc(xStart,calcs)
File "C:\Users\Erin Lynch\Desktop\collatzConjecture.py", line 14, in collatzCalc
while xCalc > 0:
RuntimeError: maximum recursion depth exceeded in comparison
我知道為什么會這樣,因為我今天讀了有關遞歸限制的信息,但是我想知道的是如何將遞歸公式轉換為迭代公式。 我完全不知道該怎么做,我需要知道如何做的人的幫助。
首先,在這一部分中,第一行是不必要的,因為xCalc
將立即被xStart
覆蓋:
xCalc = 0
xCalc = xStart
其次,如果仔細觀察代碼,就會發現如果xCalc
達到1
,它將永遠循環下去:
def collatzCalc(xStart,calcs):
...
xCalc = xStart
while xCalc > 0:
...
if xCalc == 1:
...
collatzCalc(xStart,calcs)
else:
...
由於xCalc
是一個局部變量 ,其他實例collatzCalc
不能修改這個變量。 該功能將永遠保持循環。 由於您正在檢查Collatz猜想,因此永遠在“最外層”函數中循環是有意義的,但遞歸地進行操作則沒有意義。
我認為這是因為您混淆了該程序的兩個不同部分:
讓我們解決第一個問題,因為它更容易。 要檢查Collatz猜想,您只需要一個簡單的循環:
def checkCollatz(xStart=1, debug=False):
xList = []
calcList = []
while True:
calc = collatzCalc(xStart, debug=debug)
xList.append(xStart)
calcList.append(calc)
if debug:
print(xStart - 1)
print('---------------------------')
xStart += 1
在這里,我已將全局變量( xList
, calcList
, xStart
和debug
)轉換為此最外層函數的局部變量。 (您可能還希望為其選擇更多的描述性名稱。)請注意,我已經完全消除了calcs
變量,因為它看起來與xStart
相同,但總是低一。
現在,要計算Collatz序列,我可以重用您已經擁有的東西(去除checkCollatz
中使用的checkCollatz
):
def collatzCalc(xCalc, debug=False):
calc = 0
while xCalc > 0:
if debug:
print(xCalc)
if xCalc == 1:
return calc
else:
if xCalc % 2 == 0:
xCalc = xCalc // 2
else:
xCalc = xCalc * 3 + 1
calc += 1
因為Collatz序列始終是整數,所以不需要使用round
。 另外,應該使用整數除法( //
)而不是浮點除法( /
),因為/
會將數字強制為浮點數。
請注意,此代碼中根本沒有遞歸。 遞歸已被消除,並轉換為checkCollatz
的循環(請注意,現在有兩個 while
循環,而不是一個)。 您的原始代碼已經大體上是迭代的,因此將其轉換為遞歸代碼並不十分復雜。
作為附帶說明,請注意,通過將函數分成兩個單獨的函數,現在變量變少了很多,代碼更易於閱讀。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.