Python 如何在这个素数筛中减少for循环的时间?
下面所示的埃拉托斯烯筛的实施效率非常低。我对寻找最有效的方法不感兴趣;我只想把我已经做得更好 我知道有很多不同的方法可以做到这一点;我只是从头开始实施筛选,我的问题是,我想知道我能做些什么,使这个特定实现的某个特定部分更高效Python 如何在这个素数筛中减少for循环的时间?,python,performance,for-loop,sieve-of-eratosthenes,Python,Performance,For Loop,Sieve Of Eratosthenes,下面所示的埃拉托斯烯筛的实施效率非常低。我对寻找最有效的方法不感兴趣;我只想把我已经做得更好 我知道有很多不同的方法可以做到这一点;我只是从头开始实施筛选,我的问题是,我想知道我能做些什么,使这个特定实现的某个特定部分更高效 def筛(x): l=[] 对于范围(x+1)内的i: l、 附加(i) l、 删除(0) l、 删除(1) 克隆=l[:] 测试=0 对于l中的i: 当测试
def筛(x):
l=[]
对于范围(x+1)内的i:
l、 附加(i)
l、 删除(0)
l、 删除(1)
克隆=l[:]
测试=0
对于l中的i:
当测试
如果您将上述代码粘贴到中并逐步执行,您将注意到在第200步之前已完成查找所有素数;对于循环,它主要浪费时间遍历外部
的长度。操作上的问题是:在这个特定的实现中,如何减少它在for
循环中花费的时间?为了提高效率,我做了最多的工作,就是用一个对checker
的赋值来替换clone[test]
的四个实例(好吧,每个循环都有一个赋值)。首先,将元素标记为已删除(在已知位置有一个赋值)比使用列表更有效。删除
(需要搜索列表并在删除元素后移动每个元素)。然后您可以在结束时一次过滤掉所有索引。因此,就像您已经做的一样,从0到x的索引从素数开始:
l = [True] * (x + 1)
然后将一些标记为非素数:
l[0] = False
l[1] = False
然后可以简化内部循环,每次向前移动固定数量的元素:
for i in range(2, x + 1):
if not l[i]:
continue
for j in range(i * i, x + 1, i):
l[j] = False
从i*i
开始,因为当循环命中s
时,形式为s*i
的i
中任何较小的倍数都已被覆盖。这也具有不涉及除法运算的优点
使用指示给定索引是否为素数的布尔值列表创建素数列表,然后:
return [i for i in range(x + 1) if l[i]]
这一切并没有减少外循环的迭代次数,但它应该已经快得多了,使用简化版,可能更容易看到当i*i
大于列表时,如何停止,也可以跳过检查每一个偶数。如果代码有效,您只需要改进建议,它应该放在代码审查上。不过请注意,他们会要求您提供一个main
来显示它是如何运行的。我可以请求移动它吗?我需要标记它吗?如果我这样做,我会失去我的代表吗?我会投票结束这个问题,因为它属于打开的主题