Python 素数发生器中的分段故障
我知道下面不是生成素数列表的最快方法,但是在Google编写以下程序之前,我提出了这个问题。它适用于小于44000的数字,但在我的2Ghz Core 2 Duo Macbook上运行时会出现分段错误。目前我对其他方法并不感兴趣,但我对为什么它会给我一个seg错误感兴趣 它能计算的最后一个素数是42751,在它死之前说“分段错误”Python 素数发生器中的分段故障,python,segmentation-fault,primes,Python,Segmentation Fault,Primes,我知道下面不是生成素数列表的最快方法,但是在Google编写以下程序之前,我提出了这个问题。它适用于小于44000的数字,但在我的2Ghz Core 2 Duo Macbook上运行时会出现分段错误。目前我对其他方法并不感兴趣,但我对为什么它会给我一个seg错误感兴趣 它能计算的最后一个素数是42751,在它死之前说“分段错误” from sys import argv, exit, setrecursionlimit def isPrime(no, halfNo, x = 3): #
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
从系统导入argv,退出,设置递归限制
def iPrime(否,半否,x=3):
#如果从3开始算起,所有的数字都不是x,则因子为素数
如果x>半否:
打印号
返回1
#x是一个因子吗?
如果没有%x==0:
返回0
其他:
iPrime(否,半否,x+2)
路径,limLow,limHigh=argv
limLow=int(limLow)
limHigh=int(limHigh)
设置递归限制(上限)
#负数,0和1不是素数,所以答案无效
如果limLow<2:
退出(“无效输入”);
#如果下限为偶数,则其不是素数,因此增加1
如果下限%2==0:
limLow+=1
while(limLow堆栈上的重复调用太多,可能会导致堆栈溢出。在42751,您将有一个21375深度函数调用堆栈。在这种情况下,可能实际上需要改进您的方法
一个方便的检查素数的小程序可以这样编写(伪代码):
如果n<2返回false;
如果n==2或n==3,则返回true;
如果n%2==0,则返回false;
如果n%3==0,则返回false;
对于(i=6;i
此方法之所以有效,是因为以下原因:
如果n小于2,它就不能是素数
如果n是2或3,它必须是素数
如果n不是2或3,但可被其中之一整除,则它不是素数
除了2和3之外的所有素数都可以写成6k+1或6k-1的形式。如果一个数是素数,它就不能被任何其他素数平均整除。只需要检查n的平方根,因为超过这个数的任何东西都不能平均整除n
您的程序正在使用递归。每个函数调用都会将寄存器保存到堆栈上,然后跳到函数的开头。由于堆栈的大小有限,最终会耗尽堆栈空间。此时,您将在不应该(甚至不允许)的内存上进行写写操作到。从而导致分段错误。设置一个非常大的递归限制,然后递归一个簇是使Python interpeter崩溃的方法之一
本质上,你告诉Python如果你递归太远,不要阻止你,然后你递归太远。你在做一个递归调用,线性计数为2。CPython不做尾部调用消除,而且(IIRC)它使用C堆栈,所以它在这里占用了一些相当大的堆栈空间
我在64位Mac OS上找不到默认的堆栈大小(在32位Mac OS上,它看起来是8MB),但它肯定不是无限大的,而且显然不足以容纳多达50000个奇数的堆栈帧。我的猜测是,在例程的递归部分,内存已经用完了
如果您将其重新编码为循环递增x,那么您会发现它在崩溃之前走得更远。为了子孙后代,我在最后编写的修复错误的代码如下所示
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()
导入系统
def iPrime(否):
sqrt=圆形(编号**0.5);
#如果从3开始算起,所有的数字都不是x,则因子为素数
如果没有%2==0或没有%3==0:
返回错误
对于范围内的x(6,整数(sqrt),6):
如果否(x-1)=0:
返回错误
如果否(x+1)=0:
返回错误
返回真值
def充注量范围(最低、最高):
#负数,0和1不是素数,所以答案无效
如果limLow<2:
raise VALUE ERROR('下限必须为2或更多')
#如果下限为偶数,则其不是素数,因此增加1
如果下限%2==0:
limLow+=1
素数=[]
while(limLow@shynthrir:抱歉,无法抗拒双关语。他因为堆栈溢出而陷入堆栈溢出中。:)我想指出同样的讽刺,虽然我现在认为我会坚持这一点。在那里,我认为使用递归函数是聪明的。那么你会建议一个简单的循环作为我问题的答案吗?编辑我的答案,包括一个很好的小质数检查方法。希望这有帮助。我所说的方法是计算方法(也就是说,我没有使用筛选算法)不是递归函数与循环或其他方法中的方法。很抱歉造成混淆。
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()