我知道以下不是生成素数列表的最快方法,但是我自己提出问题并且在谷歌搜索之前编写了以下程序。它适用于数字< ~44,000但是在我的2Ghz Core 2 Duo Macbook上运行时会出现分段错误。我现在对替代方法并不感兴趣,但是为什么它给我一个段错误。
能够计算的最后一个素数是42751,然后才会说“分段错误”。
from sys import argv, exit, setrecursionlimit
def isPrime(no, halfNo, x = 3):
# if counted through and all numbers from 3 too x are not factors is prime
if x > halfNo:
print no
return 1
# is x a factor?
if no % x == 0:
return 0
else:
isPrime(no, halfNo, x + 2)
path, limLow, limHigh = argv
limLow = int(limLow)
limHigh = int(limHigh)
setrecursionlimit(limHigh)
# negitive numbers, 0 and 1 are not primes so answer invalid
if limLow < 2:
exit('Invalid input');
# if lower limit is even its not prime so increase by 1
if limLow % 2 == 0:
limLow += 1
while (limLow <= limHigh):
isPrime(limLow, limLow / 2)
limLow += 2
答案 0 :(得分:4)
您可能会从堆栈上过多的重复调用中获得堆栈溢出。在42751,你将有一个21375深度函数调用堆栈。在这种情况下,实际上可能需要改进您的方法。
一个方便的小程序将检查完整性可以这样写(伪代码):
if n < 2 return false;
if n == 2 or n == 3 return true;
if n % 2 == 0 return false;
if n % 3 == 0 return false;
for (i = 6; i < sqrt(n); i += 6) {
if (n % (i - 1) == 0) return false;
if (n % (i + 1) == 0) return false;
}
return true;
此方法的工作原理如下:
答案 1 :(得分:0)
您的程序正在使用递归。每个函数调用都会将寄存器保存到堆栈中,然后跳转到函数的开头。由于您的堆栈大小有限,最终您将耗尽堆栈空间。在这一点上,你是在写你不应该(甚至不允许)的记忆。从而导致分段错误。
答案 2 :(得分:0)
设置一个非常大的递归限制然后递归一堆是导致Python插件崩溃的documented方法之一。
基本上你告诉Python如果你做得太过分,就不要阻止你,然后你的回复太过分了。
答案 3 :(得分:0)
你正在进行递归调用,线性计数为2. CPython不执行尾调用消除,而(IIRC)它使用C堆栈,所以它在这里占用了一些相当严重的堆栈空间。
我无法在64位Mac OS上找到默认的堆栈大小(在32位上它似乎是8MB)但它绝对不是无限的,并且显然不足以容纳每个奇数的堆栈帧直到50000
答案 4 :(得分:0)
我的猜测是你的例行程序的递归部分内存不足。
如果你将它重新编码为一个递增x的循环,那么你会发现它在崩溃之前会更进一步。
答案 5 :(得分:0)
为了后人的缘故,我最后编写的修复错误的代码如下:
import sys
def isPrime( no ):
sqrt = round(no**0.5);
# if counted through and all numbers from 3 too x are not factors is prime
if no % 2 == 0 or no % 3 == 0:
return False
for x in range(6, int(sqrt), 6):
if no % (x - 1) == 0:
return False
if no % (x + 1) == 0:
return False
return True
def primesInRange(limLow, limHigh):
# negitive numbers, 0 and 1 are not primes so answer invalid
if limLow < 2:
raise ValueError('Lower limit must be 2 or more')
# if lower limit is even its not prime so increase by 1
if limLow % 2 == 0:
limLow += 1
primes = []
while (limLow <= limHigh):
if isPrime(limLow): primes.append(limLow)
limLow += 2
return primes
def main():
limLow = int(sys.argv[1])
limHigh = int(sys.argv[2])
print primesInRange(limLow, limHigh)
if __name__ == '__main__':
main()