为什么我的Eratosthenes筛子运行得这么慢?

时间:2017-10-09 22:54:12

标签: python algorithm primes sieve-of-eratosthenes

我正在为Eratosthenes的Sieve编写Python的素数程序。虽然它似乎有用,但速度很慢。我怎样才能加快速度呢?

primes = []
upperLimit = 1000

for x in range(2,upperLimit):
  primes.append(x)
for y in range(0,int(len(primes)**0.5)):
  remove = []
  for j in range(primes[y]**2,upperLimit,primes[y]):
    remove.append(j)
  for i in remove:
    if i in primes:
      primes.remove(i)

print(primes)

更新: 感谢答案的帮助,我使用布尔值而不是数字重写了代码。现在,低于100000的列表在不到6秒的时间内运行。

i = 2
limit = 100000
primes = [True] * limit
primes[0] = False
while i < limit**0.5:
    if primes[i-1]:
        for x in range(i * 2, limit + 1,i):
            primes[x-1] = False
    i += 1
count = 1
total = []
for i in primes:
    if i:
        total.append(count)
    count += 1
print(total)

2 个答案:

答案 0 :(得分:2)

我认为代码中主要的低效率是您正在维护的素数list。虽然可能并不明显,但调用primes.remove是一项非常昂贵的操作。它需要遍历list以尝试找到您要移除的值,然后需要通过移动所有元素来修改list。对

E.g。

l = [0, 1, 2, 3, 4]
l.remove(5)  # This has to look at all the elements in l, since 6 isn't there
l.remove(0)  # This finds 1 quickly but then has to move every element to the left

更为传统的Eratosthenes筛选方法是使用您正在考虑的所有数字中的数组(Python中的list),其中每个元素都是一个布尔值,表示该数字是否可以是素数

模仿上面的例子:

l = [True, True, True, True, True]
l[0] = False  # Just goes straight to that element and changes its value

以下是如何编写该代码的示例:

primes = [True] * 100000

# We already know 2 is the first prime
primes[0] = False
primes[1] = False

# Fine to stop at sqrt(len(primes)) here as you're already doing    
for i in range(2, len(primes)):
    if primes[i]:
        for j in range(i**2, len(primes), i):
            primes[j] = False

print([n for n, is_prime in enumerate(primes) if is_prime])

您会发现这要快得多,因为索引到list并以这种方式更改值非常有效。

答案 1 :(得分:0)

它很慢,因为你做的很多操作比经常做的更频繁。复合数 N 的生命周期看起来像这样:

  • N 附加到素数
  • 为每个号码(&lt; sqrt(limit))
    • 的所有倍数附加到删除
  • 对于删除中的每个
    • 如果仍在素数,请将其删除。

很多&#34;接触&#34;对于每个号码。这也是需要考虑的很多数字。

相反,试试这个:

  • 列出布尔值(所有 True ),每个潜在素数一个。
  • 最低值 I 标记 True &lt; SQRT(限制):
    • 清除(转错误
    • 的所有大倍数
    • 注意:请勿检查该值是否已 False

此时,您的素数正是那些仍标记为 True

的值