实现迭代过程:Python

时间:2016-11-15 17:11:30

标签: python recursion

我使用此代码找到数字的最小除数:

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)...

如果没有,我该如何实现此算法的迭代过程?

2 个答案:

答案 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)) 

回答评论:

呼叫会向堆栈添加一个帧。无论过程的理论性质如何,如果不添加堆栈帧,都无法进行函数调用。这是运行时系统中固有的。如果您希望迭代过程只有一个堆栈帧,那么您必须编写一个迭代实现。