我正在尝试用Python创建一个主筛。
我从制作一个从2到2000的列表开始。我想用支票迭代所有素数,并从列表中删除所有素数的倍数。
我还没有绕过素数循环,但是我有一个方法从数字2开始,并删除它的所有倍数。
primes=list(range(2,2001))
p=2
while p<len(primes):
for x in range (p*p, len(primes), p):
primes.remove(x)
print(primes)
这张照片:[...] 1989,1991,1993,1995,1997,1999,2000]
正如你所看到的,数字2000仍然存在,而且不应该是。
Traceback (most recent call last):
File "C:/Users/Are/PycharmProjects/Project Euler/10.py", line 8, in <module>
primes.remove(x)
ValueError: list.remove(x): x not in list
我的推理出了什么问题?
我正在使用PyCharm,有没有办法让我在出错时打印x的值?
答案 0 :(得分:5)
你的清单不是2000年,你从2开始......
>>> primes=list(range(2,2001))
>>> print len(primes)
1999
因此,当你执行while循环时,它不会达到2000 ......:)
答案 1 :(得分:4)
您创建了1999个元素的列表:
>>> len(range(2,2001))
1999
然后循环遍历range()
,但不包括该长度:
for x in range (p*p, len(primes), p):
因此x
永远不会比1998年更大。
而不是len(primes)
,使用上限常量:
limit = 2001
primes=list(range(limit))
# ...
for x in range (p*p, limit, p):
下一个问题是您继续使用while p<len(primes):
循环;您将生成不再 primes
列表中的一部分的数字,因此无法再次删除它们。您可以使用异常处理程序来捕获异常:
try:
primes.remove(x)
except ValueError:
# already removed
pass
但您可能想重新考虑while
循环条件。
答案 2 :(得分:2)
在range(a,b)
中,第一个值为a
,最后一个值为b-1
。
在您的情况下,这意味着您只是迭代到len(primes)-1
,小于2000
。
答案 3 :(得分:1)
崩溃时x的值实际为4.您不会将p递增到第一个循环结束时列表中的下一个值。
其次,您尝试从列表中多次删除值。您将(例如)尝试删除12次。一旦你在2上迭代,一旦你在3上迭代。
最后,您按照列表的长度进行操作,当您从中移除值时,该列表的长度始终会变小。你第一次绕过循环,你的列表大小确实非常小。
重新编写代码:
primes=list(range(2,2001))
p=2
while p<2000:
for x in range (p*p, 2001, p):
if x in primes:
primes.remove(x)
while 1:
p = p + 1
if p in primes or p > 2000:
break
print primes