埃拉托色尼筛法问题(Python 语法)
所以我正在阅读关于埃拉托斯特尼筛法的维基百科文章,其中包含一个 Python 实现: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Algorithm_complexity_and_implementation
def eratosthenes_sieve(n):
# Create a candidate list within which non-primes will be
# marked as None; only candidates below sqrt(n) need be checked.
candidates = range(n+1)
fin = int(n**0.5)
# Loop over the candidates, marking out each multiple.
for i in xrange(2, fin+1):
if not candidates[i]:
continue
candidates[2*i::i] = [None] * (n//i - 1)
# Filter out non-primes and return the list.
return [i for i in candidates[2:] if i]
它看起来像非常简单和优雅的实现。我见过其他实现,甚至是 Python 中的实现,并且我了解 Sieve 的工作原理。但是这个实现的特定工作方式,我有点困惑。似乎编写该页面的人都非常聪明。
我知道它会迭代列表,找到素数,然后将多个素数标记为非素数。
但是这行代码到底做了什么:
candidates[2*i::i] = [None] * (n//i - 1)
我发现它从 2*i 到末尾切片候选,按 i 迭代,所以这意味着 i 的所有倍数,从 2*i 开始,然后转到 3*i,然后转到 4*i 直到完成列表。
n//i - 1) 是什么意思?为什么不将其设置为 False?
但是 [None] * ( 问题只有一个答案,但我认为这是问这个问题的地方,我肯定会感激一个清晰的解释。
So I was reading the Wikipedia article on the Sieve of Eratosthenes and it included a Python implementation:
http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Algorithm_complexity_and_implementation
def eratosthenes_sieve(n):
# Create a candidate list within which non-primes will be
# marked as None; only candidates below sqrt(n) need be checked.
candidates = range(n+1)
fin = int(n**0.5)
# Loop over the candidates, marking out each multiple.
for i in xrange(2, fin+1):
if not candidates[i]:
continue
candidates[2*i::i] = [None] * (n//i - 1)
# Filter out non-primes and return the list.
return [i for i in candidates[2:] if i]
It looks like a very simple and elegant implementation. I've seen other implementations, even in Python, and I understand how the Sieve works. But the particular way this implementation works, I"m getting a little confused. Seems whoever was writing that page was pretty clever.
I get that its iterating through the list, finding primes, and then marking multiples of primes as non-prime.
But what does this line do exactly:
candidates[2*i::i] = [None] * (n//i - 1)
I've figured out that its slicing candidates from 2*i to the end, iterating by i, so that means all multiples of i, start at 2*i, then go to 3*i, then go to 4*i till you finish the list.
But what does [None] * (n//i - 1)
mean? Why not just set it to False?
Thanks. Kind of a specific question with a single answer, but I think this is the place to ask it. I would sure appreciate a clear explanation.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
只是一种简洁的编写方式
,其工作原理是将一个
None
列表分配给一个candidates
切片。is just a terse way of writing
which works by assigning an list of
None
s to a slice ofcandidates
.L * N
创建并连接L
的N
(浅)副本,因此[None] * (n//i - 1 )
给出ceil(n / i)
乘以None
的列表。切片赋值 (L[start:end:step] = new_L
) 会用new_L
的项目覆盖切片接触的列表项目。你是对的,人们也可以将这些项目设置为
False
- 我认为这会更好,代码的作者显然认为None
会更好地指示“划掉了”。但是None
也可以工作,因为bool(None) 是 False
和.. if i
本质上是if bool(i)< /代码>。
L * N
creates and concatenatesN
(shallow) copies ofL
, so[None] * (n//i - 1)
gives a list ofceil(n / i)
timesNone
. Slice assignment (L[start:end:step] = new_L
) overwrites the items of the list the slice touches with the items ofnew_L
.You are right, one could set the items to
False
as well - I think this would be preferrable, the author of the code obviously thoughtNone
would be a better indicator of "crossed out". ButNone
works as well, asbool(None) is False
and.. if i
is essentiallyif bool(i)
.