我使用此代码找到数字的最小除数:
def smallestDisvisor(n):
return factor(n,2)
def factor(n,divisor):
if (square(divisor) - n > 0):
return n
elif (n % divisor == 0):
return divisor
else:
return factor(n,divisor + 1)
print(smallestDisvisor(32452843))
然而,当我以足够大的值运行它时,我得到:
RecursionError: maximum recursion depth exceeded
[Finished in 0.5s with exit code 1]
我不明白递归错误。这段代码是不是实现了迭代过程?
factor(32452843,2) -> factor(32452843,3) -> factor(32452843,4)...
如果没有,我该如何实现此算法的迭代过程?
答案 0 :(得分:2)
正如评论中所述,Python没有尾递归优化。您只是因为堆栈变得太大而无法处理而导致错误。
修改强>
这是迭代获得最小因子的一种方法:
# if you're using python3, import reduce from functools
from functools import reduce
def get_factors(n):
factors = []
i = 2
while i < n:
if (n % i) == 0:
factors.append(i)
if reduce(lambda x,y: x*y, factors) >= n:
return factors
i = i + 1
return factors
这将返回所有因素的列表。要获得最小的,您可以查看第一个元素。由于32452843是素数,因此列表将为空。
答案 1 :(得分:1)
现在我理解了这个问题:使用递归实现迭代过程。
是的,你可以这样做。绊倒你的是默认的堆栈递归限制。由于您对 N 的递归进行 sqrt(N)调用,因此您只能处理数字&lt; = MAX_STACK_RECURSION_DEPTH ^ 2.
您的选择是将深度从默认值1000增加:
import sys
sys.setrecursionlimit(10000)
或使用更高效的算法,例如只考虑主要除数的算法:
def smallestDisvisor(n):
return factor(n, 2, [])
def factor(n, divisor, prime_list):
# See whether any prime divides teh current divisor.
# Increment it until we get a new prime.
while any(divisor % prime == 0 for prime in prime_list):
divisor += 1
if (divisor * divisor > n):
return n
elif (n % divisor == 0):
return divisor
else:
return factor(n, divisor + 1, prime_list + [divisor] )
print(smallestDisvisor(32452843))
回答评论:
呼叫会向堆栈添加一个帧。无论过程的理论性质如何,如果不添加堆栈帧,都无法进行函数调用。这是运行时系统中固有的。如果您希望迭代过程只有一个堆栈帧,那么您必须编写一个迭代实现。