【发布时间】:2015-08-15 03:30:57
【问题描述】:
我已经编写了埃拉托色尼筛法的简单实现,我想知道是否有更有效的方法来执行其中一个步骤。
def eratosthenes(n):
primes = [2]
is_prime = [False] + ((n - 1)/2)*[True]
for i in xrange(len(is_prime)):
if is_prime[i]:
p = 2*i + 1
primes.append(p)
is_prime[i*p + i::p] = [False]*len(is_prime[i*p + i::p])
return primes
我正在使用 Python 的列表切片来更新我的布尔值列表 is_prime。每个元素is_prime[i]对应一个奇数2*i + 1。
is_prime[i*p + i::p] = [False]*len(is_prime[i*p + i::p])
当我找到一个素数p 时,我可以标记与该素数False 的倍数相对应的所有元素,并且由于所有小于p**2 的倍数也是较小素数的倍数,因此我可以跳过标记这些。 p**2的索引是i*p + i。
我担心计算 [False]*len(is_prime[i*p + 1::p]) 的成本,我试图将它与其他两种我无法工作的策略进行比较。
由于某种原因,公式(len(is_prime) - (i*p + i))/p(如果为正)并不总是等于len(is_prime[i*p + i::p])。是因为我算错了切片的长度,还是因为切片的一些微妙之处我没有抓住?
当我在函数中使用以下行时:
print len(is_prime[i*p + i::p]), ((len(is_prime) - (i*p + i))/p)
is_prime[i*p + i::p] = [False]*((len(is_prime) - (i*p + i))/p)
我得到以下输出(案例n = 50):
>>> eratosthenes2(50)
7 7
3 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in eratosthenes2
ValueError: attempt to assign sequence of size 2 to extended slice of size 3
我还尝试将批量更新行替换为以下内容:
for j in xrange(i*p + i, len(is_prime), p):
is_prime[j] = False
但是对于较大的 n 值,这会失败,因为 xrange 不会占用任何大于 long 的值。我放弃了试图将itertools.count 争取到我需要的东西。
是否有更快、更优雅的方式来批量更新列表切片?我可以做些什么来修复我尝试过的其他策略,以便我可以将它们与有效的策略进行比较?谢谢!
【问题讨论】:
标签: python list slice sieve-of-eratosthenes