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

时间:2018-08-30 20:05:45

标签: python sieve-of-eratosthenes

我需要生成大量的质数,但是使用Eratosthenes筛子花费的时间太长了。目前,生成小于100,000的素数大约需要3秒,而小于1,000,000的素数大约需要30秒。这似乎表明O(n)的复杂性,但据我所知这是不对的。代码:

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

我缺少明显的东西吗?如何改善筛子的性能?

2 个答案:

答案 0 :(得分:1)

在Python中,循环索引是非常缓慢的操作。通过用数组切片替换循环,以及用Numpy数组替换列表,我们看到了3倍的增长:

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]

要获得更高的速度,一种选择是使用http://localhost:32774/nginx_status。观察外部循环,人们如何立即将其向量化还不是很明显。

第二,如果您移植到numpy vectorization,将会看到极大的提速,这是一个相当无缝的过程。

编辑:通过更改n**2 => math.pow(n,2)之类的内容,您也可能会看到改进,但是与较大的问题(即迭代器)相比,这样的小改进并不重要。

答案 1 :(得分:0)

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

相关问题