寻找下一个素数

时间:2013-02-15 12:10:04

标签: python performance

我正在寻找一种快速且节省内存的方法来寻找下一个素数。

输入:整数n

输出第一个素数大于n

Fastest way to list all primes below N处打印小于n的所有素数的代码非常好。我的低效方法目前发现所有素数小于2n,然后通过循环遍历列表来搜索大于n的第一个素数。这是我目前的代码。

import numpy
def primesfrom2to(n):
    """ Input n>=6, Returns a array of primes, 2 <= p < n """
    sieve = numpy.ones(n/3 + (n%6==2), dtype=numpy.bool)
    for i in xrange(1,int(n**0.5)/3+1):
        if sieve[i]:
            k=3*i+1|1
            sieve[       k*k/3     ::2*k] = False
            sieve[k*(k-2*(i&1)+4)/3::2*k] = False
    return numpy.r_[2,3,((3*numpy.nonzero(sieve)[0][1:]+1)|1)]

n=10**7
timeit next(x for x in primesfrom2to(2*n) if x > n)
1 loops, best of 3: 2.18 s per loop

n= 10**8
timeit next(x for x in primesfrom2to(2*n) if x > n)
1 loops, best of 3: 21.7 s per loop

最后一次测试需要近1GB的RAM。这段代码的另一个问题是,如果$ n = 10 ** 10 $,它就会失败。

这个问题可以更快解决吗?有没有办法让它使用更少的内存?

3 个答案:

答案 0 :(得分:2)

最好的办法显然如下。

  1. n开始筛选直至2n以消除小素数的数字。
  2. 在剩余的值上运行一个概率素数测试仪,如Miller-Rabin。
  3. 如果需要,在已报告为prime的第一个数字上运行确定性主要测试。

答案 1 :(得分:1)

我可以想到两种解决方法。我最近尝试过的第一个 - 我在C ++中使用了非常高效的Sieve of Eratosthenes并将其变成C/C++ Extension for Python

它的内存效率高,因为它使用的是位图,而不是实际的int数组,并且它非常快 - 对于高达10 ** 9,它在一个虚拟的核心虚拟机上运行大约20秒(以及将位图导出到实际的整数)。在您的情况下,您只能保留位图,如果现在绝对最大值为n,则可以预先计算素数。

另一种方法是研究一些Primality tests,但不要忘记其中一些是概率性的。

答案 2 :(得分:1)

我肯定会推荐某种筛子或过滤器。

在尝试解决涉及素数的问题时,我在Python中创建了以下内容: https://gist.github.com/anonymous/4960155

我能够在大约15秒钟内通过几百万个素数,IIRC。回来的时候还有一段时间。我很高兴我救了它!