I have this code I do not quite understand because I just started learning Python a week ago.
import numpy as np
import time
start_time=time.clock()
def Sieb(n): #Sieve
Eins = np.ones(n, dtype=bool) #Eins is just german for One
Eins[0] = Eins[1] = False #->I don't quite understand what
for i in range(2, n): #this one does.
if Eins[i]:
Eins[i*i::i] = False #Does this make the ones = zero?
return np.flatnonzero(Eins)
print Sieb(1000000)
print start_time
So, I understand the concept of the sieve (I guess) but I'm not sure how it is achieved here.
Where are the multiples of itself get to 0
and how does the np.flatnonzero
puts out the prime numbers because before that, they are just 1
and 0
?
I hope you can understand and help me. :)
Let's go through it step-by-step.
This creates a new array of size n, with type
bool
, and all ones. Because of the type, "one" meansTrue
. The array represents all our numbers that we want to test for primality, withTrue
meaning the number is prime,False
meaning it is not. So we start with all numbers marked as (potential) primes.Now we set the
0
th and1
st element toFalse
: Neither 0 nor 1 are primes.Next, we'll iterate over all remaining numbers (from 2 onwards). We could get away with only going up to the square root of n, but for simplicity, we go over all numbers.
If the
i
th value of the array isTrue
, that meansi
is a prime. The first time this condition will be entered is withi=2
. Next, we want to remove all multiples of our number from the prime candidates:We can read this line as if it was
Eins[2*i::i] = False
, starting fromi*i
is just an optimization¹. If 2 is a prime number, that means that 2*2, 3*2, 4*2, ... aren't, so we set the multiples toFalse
. The indexing notation stands for "fromi*i
until the end" (represented by the empty space between the colons) ", in steps ofi
". This statement produces the numbersi*i
,i*(i+1)
,i*(i+2)
, ..., so all multiples ofi
that haven't been marked as "not a prime" yet.And this simply returns all indices where the value is
True
, i.e. all prime numbers that were found.1: A word regarding the
i*i
: We can start from the square ofi
, because any numbersj*i
(forj < i
) have already been marked as nonprime when we were atj
.Here's a demonstration that this works, for
n=15
:We start with the array filled with
.ones
:Then we empty
Eins[0]
andEins[1]
:And now we start iterating over the range, starting with
i=2
, and we remove every multiple of 2 starting with2*2=4
:i=3
, removing every multiple of 3 starting with3*3=9
:Note that we didn't have to remove
6
, because it was already removed byi=2
.When
i=4
, we skip the removal becauseEins[i]
isFalse
. Fromi=5
onwards, nothing happens, because the squares (25, 36, ...) are larger than the array. Finally, we useflatnonzero
and get all indices where the value isTrue
: