2
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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Aaron
  • 155
  • 3
  • 11

1 Answers1

2

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.
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343