如何让Eratosthenes筛更快?

时间:2015-06-17 10:02:27

标签: python python-3.x primes sieve-of-eratosthenes number-theory

我正在尝试解决Project Euler中的10个问题。它包括找到200万以下所有素数的总和。我根据Eratosthenes的Sieve编写了以下代码。

import time
t0 = time.time()
n=200000
liste=list(range(2,n))
k=2
s=2
while k <=n:
    liste=list(set(liste)-set(range(k,n,k)))
    if liste!=[]:
        k=min(liste)
        s+=k
    else:
        break
print(s)
t1 = time.time()
total = t1-t0
print(total)

我测试了上面的代码n = 200000,但是对于n = 2000000来说它太慢了。我非常感谢能够帮助改进这个计划。

2 个答案:

答案 0 :(得分:0)

为了找到低于200000的素数之和,下面的代码(使用eratosthenes的筛子)工作得更快,你的代码需要将近55秒,而下面的代码只需0.8秒即可执行!

import time
t0 = time.time()
n = 200000
sieve = [True] * (n + 1)
for i in range(2, n + 1) :
  if sieve[i] :
     for mult in range(i + i, n + 1, i) :
        sieve[mult] = False
s=0     
for i in range(2,n + 1):
    if sieve[i] :
        s+=i    
print(s)
t1 = time.time()
total = t1-t0
print(total)

答案 1 :(得分:0)

始终尝试在多个范围内衡量代码的empirical complexity

您的代码很慢,因为您找到了设置差异,并且始终在set和list之间进行转换。您应该始终使用一个集合,并使用

更新它
    sete.difference_update(range(p*p,n,p*2))

要查找min元素,您只需在集合上调用min(sete),无需转换列表。

由于对min元素的搜索效率低,所得到的代码的整体复杂性将接近 n ^ 1.5 ,这不是太亮,但也不是太可怕。特别是,它在ideone.com上以4.9秒完成,找到2000000以下的素数的总和,以及400000的0.5秒(首先仅使用赔率进行额外优化)。