Reputation: 175
def primes(n):
sieve = [True] * n
for i in xrange(3,int(n**0.5)+1,2):
if sieve[i]:
sieve[i*i::2*i]=[False]
print [2] + [i for i in xrange(3,n,2) if sieve[i]]
primes(int(raw_input("Please enter an upper limit ")))
The problem occurs on line 5 I know that implementing [False] * ((n-i*i-1)/(2*i)+1)
works but I am not sure why.
Upvotes: 2
Views: 57
Reputation: 1123350
You are trying to replace all elements covered by your slice with one element:
sieve[i*i::2*i] = [False]
That would remove elements from the list, except Python only lets you replace a slice with fewer or more elements if you are not using a stride (it would be allowed if the section was contiguous). Either way, you'd want to replace all those elements with an equal number of elements from the right-hand side, so you can set those positions in the sieve to False
.
To that end, you'll need to adjust the list on the right-hand side to have enough elements to replace every sliced element:
sieve[i*i::2*i] = [False] * (((n - 1 - i*i) // (2 * i)) + 1)
The formula calculates how many elements the slice covers in a 0-based indexing system; n - 1
is the highest index, minus the starting index to give you a number of elements affected, divided by the stride, plus 1 as the stride includes the first element.
Python's xrange()
object (range()
in Python 3), makes the same calculation, and includes a longer explanation:
Else for step > 0, if n values are in the range, the last one is
lo + (n-1)*step, which must be <= hi-1. Rearranging,
n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so
the RHS is non-negative and so truncation is the same as the
floor.
Upvotes: 2