我的Eratosthenes筛是否正确实施?(Python)

我的Eratosthenes筛是否正确实施?(Python),python,sieve-of-eratosthenes,Python,Sieve Of Eratosthenes,我需要生成大量的素数,但是使用埃拉托什筛需要花费太长的时间。目前,生成100000以下的素数大约需要3秒,生成1000000以下的素数大约需要30秒。这似乎表明了一种复杂性,但据我所知,这是不对的。代码: def generate_primes(limit): boolean_list = [False] * 2 + [True] * (limit - 1) for n in range(2, int(limit ** 0.5 + 1)): if boolean_

我需要生成大量的素数,但是使用埃拉托什筛需要花费太长的时间。目前,生成100000以下的素数大约需要3秒,生成1000000以下的素数大约需要30秒。这似乎表明了一种复杂性,但据我所知,这是不对的。代码:

def generate_primes(limit):
    boolean_list = [False] * 2 + [True] * (limit - 1)
    for n in range(2, int(limit ** 0.5 + 1)):
        if boolean_list[n] == True:
            for i in range(n ** 2, limit + 1, n):
                boolean_list[i] = False

我错过了什么明显的东西吗?如何提高sieve的性能?

循环索引在Python中是一个非常慢的操作。通过用数组切片替换循环,用Numpy数组替换列表,我们可以看到增加@3x:

import numpy as np
import timeit

def generate_primes_original(limit):
    boolean_list = [False] * 2 + [True] * (limit - 1)
    for n in range(2, int(limit ** 0.5 + 1)):
        if boolean_list[n] == True:
            for i in range(n ** 2, limit + 1, n):
                boolean_list[i] = False
    return np.array(boolean_list,dtype=np.bool)

def generate_primes_fast(limit):

    boolean_list = np.array([False] * 2 + [True] * (limit - 1),dtype=bool)
    for n in range(2, int(limit ** 0.5 + 1)):
        if boolean_list[n]:
            boolean_list[n*n:limit+1:n] = False
    return boolean_list

limit = 1000

print(timeit.timeit("generate_primes_fast(%d)"%limit, setup="from __main__ import generate_primes_fast"))
# 30.90620080102235 seconds

print(timeit.timeit("generate_primes_original(%d)"%limit, setup="from __main__ import generate_primes_original"))
# 91.12803511600941 seconds

assert np.array_equal(generate_primes_fast(limit),generate_primes_original(limit))
# [nothing to stdout - they are equal]
要获得更高的速度,一个选择是使用。看看外环,我们不知道如何将其矢量化

其次,如果移植到,您将看到显著的速度提升,这应该是一个相当无缝的过程


编辑:您也可以通过更改诸如n**2=>math.pown,2之类的内容看到改进,但与更大的问题(即迭代器)相比,这样的小改进是无关紧要的。

如果您仍然使用Python 2,请使用xrange而不是range以获得更高的速度。

如果您的算法正在运行,它比任何已知的实现都要快,根据维基百科页面,它通常在logn上。但是不清楚为什么会有这个问题。如果布尔列表[n]==True:=>如果布尔列表[n]:除此之外,我不知道如何改进它可能是使用numpy将向量化索引设置为false以避免内部循环?使用整数集而不是列表?@Denziloe也许我误解了它的时间复杂性。我当时的假设是,Eratosthenes的筛子应该运行得更快,我不确定我的itmath实现是否有错误。实际上,pow比使用指数运算符要慢得多。非常感谢。我没想到会有这么大的进步,我会研究一下你给我的另外两个建议。@mypetlion-这很有趣,我不知道。函数调用的开销如此之高总是让我感到惊讶。谢谢@danjedwards123-祝你好运!如果速度非常重要,并且您不想使用编译语言,请尝试查看Julia-它是一种速度非常快的JIT语言,非常适合此用例: