1

我正在尝试在 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 的值?

4

4 回答 4

5

你的清单不是 2000 长,你从 2 开始。

>>> primes=list(range(2,2001))
>>> print len(primes)
1999

因此,当您执行 while 循环时,它不会达到 2000 ... :)

于 2013-07-01T20:51:06.963 回答
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循环条件。

于 2013-07-01T20:51:18.577 回答
2

range(a,b)第一个值是a,最后一个值是b-1。在你的情况下,这意味着你只迭代到len(primes)-1,它小于2000

于 2013-07-01T20:54:31.990 回答
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
于 2013-07-01T20:58:31.310 回答