Python 素数发生器中的分段故障

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): #

我知道下面不是生成素数列表的最快方法,但是在Google编写以下程序之前,我提出了这个问题。它适用于小于44000的数字,但在我的2Ghz Core 2 Duo Macbook上运行时会出现分段错误。目前我对其他方法并不感兴趣,但我对为什么它会给我一个seg错误感兴趣

它能计算的最后一个素数是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
从系统导入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()