我使用以下代码解决了Euler项目的问题10,该代码通过强力实施:
def isPrime(n):
for x in range(2, int(n**0.5)+1):
if n % x == 0:
return False
return True
def primeList(n):
primes = []
for i in range(2,n):
if isPrime(i):
primes.append(i)
return primes
def sumPrimes(primelist):
prime_sum = sum(primelist)
return prime_sum
print (sumPrimes(primeList(2000000)))
Run Code Online (Sandbox Code Playgroud)
这三个功能的工作原理如下:
然后我编写了一个新函数primeListRec,它与primeList完全相同,以帮助我更好地理解递归:
def primeListRec(i, n):
primes = []
#print i
if (i != n):
primes.extend(primeListRec(i+1,n))
if (isPrime(i)):
primes.append(i)
return primes
return primes
Run Code Online (Sandbox Code Playgroud)
上面的递归函数有效,但仅适用于非常小的值,如'500'.当我输入'1000'时,该功能导致我的程序崩溃.当我输入类似'2000'的值时,Python给了我这个:
RuntimeError:超出最大递归深度.
我的递归函数出了什么问题?或者是否有一些特定的方法来避免递归限制?
for*_*ran 31
递归不是在Python中做事的最常用的方法,因为它没有尾递归优化,因此使用递归作为迭代的替代是不切实际的(即使在你的例子中函数不是尾递归的,也就是说无论如何都没有帮助.基本上,这意味着如果你希望你的输入很大,你就不应该把它用于复杂度大于线性的东西(对于那些具有对数递归深度的事情来说,这仍然是可以的,比如像QuickSort那样划分和征服算法).
如果你想尝试这种方法,可以使用一种更适合进行函数式编程的语言,如Lisp,Scheme,Haskell,OCaml等; 或尝试使用Stackless Python,它在堆栈使用方面有更广泛的限制,并且还具有尾递归优化:-)
顺便说一句,你的函数的尾递归等价物可能是:
def primeList(n, i=2, acc=None):
return i > n and (acc or []) or primeList(n, i+1, (acc or []) + (isPrime(i) and [i] or []))
Run Code Online (Sandbox Code Playgroud)
另一个"顺便说一句",你不应该构建一个列表,如果你只是为了将值加起来......解决Project Euler的第10个问题的Pythonic方法是:
print sum(n for n in xrange(2, 2000001) if all(n % i for i in xrange(2, int(n**0.5)+1)))
Run Code Online (Sandbox Code Playgroud)
(好吧,也许在不同的行中拆分它会更加Pythonic,但我喜欢一个衬里^ _ ^)