优化素数查找功能

时间:2012-07-31 13:39:13

标签: python primes

经过10分钟的工作,我写了一个功能如下。它返回一个低于参数的所有素数的列表。我已经使用了所有已知的编程和数学技巧,以尽可能快地完成此功能。为了找到低于一百万的所有素数,它需要大约2秒。

您是否认为有进一步优化的可能性?有什么想法吗?

def Primes(To):
  if To<2:
    return []
  if To<3:
    return [2]
  Found=[2]
  n=3
  LastSqr=0
  while n<=To:
     k=0
     Limit=len(Found)
     IsPrime=True
     while k<Limit:
         if k>=LastSqr: 
            if Found[k]>pow(n,0.5): 
               LastSqr=k
               break
         if n%Found[k]==0:
            IsPrime=False
            break
         k+=1
     if IsPrime:
        Found.append(n)
     n+=1
  return Found

3 个答案:

答案 0 :(得分:5)

你可以使用几种技巧来加快速度,使用基本的mosstothenes筛子。一种是使用Wheel Factorization来跳过计算已知不是素数的数字。例如,除了2和3之外,所有素数都与1或5 mod 6一致。这意味着你根本不需要处理每6个数中的4个。

在下一个级别,所有素数都与1,7,11,13,17,19,23或29,mod 30一致。你可以丢掉每30个数字中的22个。

以下是Erastothenes筛子的一个简单实现,它不计算或存储偶数:

def basic_gen_primes(n):
    """Return a list of all primes less then or equal to n"""
    if n < 2:
        return []

    # The sieve.  Each entry i represents (2i + 1)
    size = (n + 1) // 2
    sieve = [True] * size

    # 2(0) + 1 == 1 is not prime
    sieve[0] = False

    for i, value in enumerate(sieve):
        if not value:
            continue

        p = 2*i + 1

        # p is prime.  Remove all of its multiples from the sieve
        # p^2 == (2i + 1)(2i + 1) == (4i^2 + 4i + 1) == 2(2i^2 + 2i) + 1
        multiple = 2 * i * i + 2 * i 
        if multiple >= size:
            break

        while multiple < size:
            sieve[multiple] = False
            multiple += p 

    return [2] + [2*i+1 for i, value in enumerate(sieve) if value]

如上所述,您也可以使用更具异国情调的筛子。

答案 1 :(得分:4)

您只能检查奇数。那你为什么不用n + = 2而不是n + = 1?

答案 2 :(得分:2)

谷歌和维基百科可以获得更好的算法。如果你只是寻找小素数,这可能足够快。但是对于大质数,真正的算法要快得多。

http://en.wikipedia.org/wiki/Quadratic_sieve

从该页面开始。

将n增加2而不是1。 ?