Reputation: 520
Could someone walk me line-by line through this prime sieve? I'm attempting to develop my own sieve but most of the faster ones contain syntax that I don't understand (like the lines i've made comments on). Sorry if this is sort of a newbie question -- also if you have any links that could help me with sieve writing they'd be greatly appreciated.
def rwh_primes1(n):
""" Returns a list of primes < n """
sieve = [True] * (n/2) # What does the '[True]' mean?
for i in xrange(3,int(n**0.5)+1,2):
if sieve[i/2]: # The same complaint as in line 3, I don't understand the variable 'sieve'
sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1) # how is sieve used here - it seems to be as a list but i'm unsure
return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]] # 'sieve' is confusing me here yet again.
Upvotes: 0
Views: 123
Reputation: 44634
I'll put the meaning of each line of code in italics, and add my comments in normal-face text.
sieve = [True] * (n/2)
Declare a new local variable sieve
and initialise it to the value [True] * (n/2)
. What does that expression mean? [True]
is a single-element list containing only the Boolean value True
. Multiplying a list by a number repeats the list, so sieve
is now an n/2
-element list of all-True
values.
for i in xrange(3, int(n**0.5)+1, 2):
Start counting in steps of 2, starting at 3 and ending at sqrt(n). This particular choice of range is an optimisation of the Sieve algorithm: we could count all the way from 1 to n in steps of 1, but that'd be less efficient.
if sieve[i/2]:
Look at the i/2
th element of the sieve
list. If it's True
, then continue down the if
branch. The author is using i/2
to compensate for the fact that the code is counting in steps of 2. This way you can work with a shorter list and use less memory.
sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1)
Update every i-th element of sieve
to False
, starting at i*i/2. sieve[i*i/2::i]
is called slice notation - because it appears on the left-hand side of an assignment this code will update that slice of sieve
. The right-hand side is a repeat of the list-times-number trick. It computes an all-False
list of the correct length.
return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]]
This code just turns the True
/False
values in sieve
into a list of prime numbers. The calculation is compensating for the fact that sieve
doesn't contain any even numbers by multiplying each True
value's index by 2.
Upvotes: 4
Reputation: 3608
Assume n=7:
sieve = [True] * (n/2) # What does the '[True]' mean?
Make a list of boolean True values of length half of n. Eg, sieve = [True,True,True] (as 3.5 was a fraction length it would rounded down in python2)
So xrange(3,int(n**0.5)+1,2)
will be a generator that gives us this sequence: []
for i in
if sieve[i/2]: # The same complaint as in line 3, I don't understand the variable 'sieve'
sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1) # how is sieve used here - it seems to be as a list but i'm unsure
return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]] # 'sieve' is confusing me here yet again.
When we see [i::2] or somesuch that just meeans we slice the list at recurring intervals. So if mylist contains (0..19):
>>> mylist = range(20)
>>> mylist[0::1]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> mylist[0::2]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>> mylist[0::3]
[0, 3, 6, 9, 12, 15, 18]
Try playing with this yourself so that you are familiar with it.
So in this case sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1)
will be setting every ith value in a list to False.
Upvotes: 1