繁体   English   中英

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

[英]Why is my Sieve of Eratosthenes running so slowly?

我正在用Python为Eratosthenes筛子编写素数程序。 尽管它似乎可以运行,但是速度非常慢。 我怎样才能加快速度?

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)

我相信代码中的主要低效率是要维护的素数list 尽管可能并不明显,但调用primes.remove是一项非常昂贵的操作。 它需要遍历list以查找要删除的值,然后需要通过将所有元素移到要查找的元素之后来修改list

例如

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并以这种方式更改值非常有效。

速度很慢,因为您执行的许多操作的次数远远超过了所需的次数。 复合数字N的寿命如下所示:

  • N附加到素数
  • 对于每个数字I (<sqrt(limit))
    • 附加I的所有较大倍数以将其删除
  • 对于每个 删除
    • 如果仍处于素数状态 ,请将其删除。

每个数字都有很多“触动”。 这也是很多小的数字来考虑。

相反,请尝试以下操作:

  • 列出一个布尔值列表(全部为True ),每个潜在素数一个。
  • 将最小值标记为True <sqrt(limit)时:
    • 清除(将False )的所有I大倍数
    • 注意:不要费心检查该值是否已经为False

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM