I'm trying to create a prime sieve in Python.
I start with making a list from 2 to 2000. I want to iterate through all primes with a check, and remove all multiples of the primes from the list.
I've not gotten around the loop for primes yet, but what I do have a method to start with the number 2, and remove all its multiples.
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)
this prints: [...] 1989, 1991, 1993, 1995, 1997, 1999, 2000]
As you can see, the number 2000 is still there, and it should not be.
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
What's wrong with my reasoning?
I'm using PyCharm, is there a way for me to print the value for x at the time of the error?
your list is not 2000 long, you start at 2..
>>> primes=list(range(2,2001))
>>> print len(primes)
1999
So when you do the while loop, it doesn't get up to 2000... :)
You create a list of 1999 elements:
>>> len(range(2,2001))
1999
You then loop over a range()
up to, but not including, that length:
for x in range (p*p, len(primes), p):
Thus x
is never going to be larger than 1998.
Instead of len(primes)
, use an upper limit constant:
limit = 2001
primes=list(range(limit))
# ...
for x in range (p*p, limit, p):
Next problem is that you continue to loop with while p<len(primes):
; you will generate numbers that are no longer part of the primes
list, so they cannot be removed a second time. You can use exception handler to catch the exception:
try:
primes.remove(x)
except ValueError:
# already removed
pass
but you may want to rethink the while
loop condition.
In a range(a,b)
the first value is a
and the last value is b-1
. In your case, that means you are only iterating up to len(primes)-1
, which is less than 2000
.
The value of x at the time of the crash is actually 4. You don't increment p to the next value in the list at the end of the first loop.
Second, you're trying to remove values multiple times from the list. You will (for instance) attempt to remove 12 twice. Once when you're iterating through on 2, once when you're iterating on 3.
Finally, you're going by the length of the list, which is always getting smaller as you remove values from it. Your first time around the loop and your list size is very small indeed.
Reworking your code:
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.