我对编程很新,我决定做一些练习来提高自己的能力。我坚持练习:"找出200万以下所有素数的总和。"我的代码太慢了。
最初,我试图将其解决为正常的素数问题并最终解决了这个问题:
sum = 2 + 3
for i in range (5, 2000000, 2):
for j in range (3, i, 2):
if i%j == 0:
break
else:
sum += i
print(sum)
这样,所有偶数都将从循环中排除。但它没有解决我的问题。这里的幅度非常大。
所以我试着理解这段代码发生了什么。我在循环中有一个循环,循环内部的循环运行外部循环时间的索引(不完全是因为列表不是从0开始),对吧?因此,当我试图找到20以下的素数时,它会运行外部循环8次,但内部循环60(我不知道这个数学是否正确,正如我所说,我很清楚编程)。但是当我使用2,000,000时,我运行内部循环总共999,993,000,012次,这很疯狂。
我的朋友告诉我关于Eratosthenes的Sieve,我试图创建一个新的代码:
list = [2]
list.extend(range(3, 2000000, 2))
for i in list:
for j in list:
if j%i == 0 and j > i:
list.remove(j)
print(sum(list))
这就是我试图模拟筛子所取得的成果(忽略偶数帮助)。它的速度要快得多(使用其他代码,需要很长时间才能找到200,000以下的质数,而这个新的我可以做到这一点)但是在合理的时间内计算2,000,000,000是不够的。自从我开始编写代码后,代码在后台运行,但仍然没有。我不知道这件事有多少次循环,我现在太累了,无法思考。
我来这里寻求帮助。为什么这么慢?我应该学习/阅读/做些什么来改进我的代码?有没有比这个筛子更有效的其他方法?谢谢你的时间。
答案 0 :(得分:2)
因为list.remove
是O(n)
操作,并且您正在做很多事情。你并没有表现出真正的筛子,只是伪装成试验分裂;你还在做原始代码中所做的所有剩余测试。
Eratosthenes的Sieve通常用一系列标志来实现;在最简单的形式中,每个索引对应相同的数字,除了True
和0
之外,所有索引的值最初为1
。迭代,当您找到True
值时,将所有索引的倍数设置为False
。这意味着工作是顺序加法,而不是乘法,而不是除法(这更加昂贵。