Python 3: Why is my prime sieve so slow?

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
15
down vote
favorite
I've implemented the sieve of Eratosthenes in Python 3 as follows:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
p = 0
while True:
for i, prime in enumerate(is_prime):
if prime and i > p:
p = i
break
else:
break
multiple = p + p
while multiple <= n:
is_prime[multiple]= False
multiple = multiple + p
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
Running this to 100,000 takes ~25 seconds.
I felt that was on the slow side, so I decided to take a different approach. The Sieve works prospectivly: it works ahead to clear out all multiples. I made a retrospective function, trial-dividing everything lower than the current prime-candidate:
def retrospect(n):
primes = [2, 3]
i = 5
while i <= n:
isprime = True
lim = math.sqrt(n)+1
for p in primes:
if p > lim:
break
if i % p == 0:
isprime = False
break
if isprime:
primes.append(i)
i += 2
return primes
This is way faster!
Questions:
- Are there any obvious shortcomings to the Sieve implementation?
- Is there a point where the retrospect gets slower than the sieve?
python performance python-3.x primes
add a comment |Â
up vote
15
down vote
favorite
I've implemented the sieve of Eratosthenes in Python 3 as follows:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
p = 0
while True:
for i, prime in enumerate(is_prime):
if prime and i > p:
p = i
break
else:
break
multiple = p + p
while multiple <= n:
is_prime[multiple]= False
multiple = multiple + p
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
Running this to 100,000 takes ~25 seconds.
I felt that was on the slow side, so I decided to take a different approach. The Sieve works prospectivly: it works ahead to clear out all multiples. I made a retrospective function, trial-dividing everything lower than the current prime-candidate:
def retrospect(n):
primes = [2, 3]
i = 5
while i <= n:
isprime = True
lim = math.sqrt(n)+1
for p in primes:
if p > lim:
break
if i % p == 0:
isprime = False
break
if isprime:
primes.append(i)
i += 2
return primes
This is way faster!
Questions:
- Are there any obvious shortcomings to the Sieve implementation?
- Is there a point where the retrospect gets slower than the sieve?
python performance python-3.x primes
add a comment |Â
up vote
15
down vote
favorite
up vote
15
down vote
favorite
I've implemented the sieve of Eratosthenes in Python 3 as follows:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
p = 0
while True:
for i, prime in enumerate(is_prime):
if prime and i > p:
p = i
break
else:
break
multiple = p + p
while multiple <= n:
is_prime[multiple]= False
multiple = multiple + p
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
Running this to 100,000 takes ~25 seconds.
I felt that was on the slow side, so I decided to take a different approach. The Sieve works prospectivly: it works ahead to clear out all multiples. I made a retrospective function, trial-dividing everything lower than the current prime-candidate:
def retrospect(n):
primes = [2, 3]
i = 5
while i <= n:
isprime = True
lim = math.sqrt(n)+1
for p in primes:
if p > lim:
break
if i % p == 0:
isprime = False
break
if isprime:
primes.append(i)
i += 2
return primes
This is way faster!
Questions:
- Are there any obvious shortcomings to the Sieve implementation?
- Is there a point where the retrospect gets slower than the sieve?
python performance python-3.x primes
I've implemented the sieve of Eratosthenes in Python 3 as follows:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
p = 0
while True:
for i, prime in enumerate(is_prime):
if prime and i > p:
p = i
break
else:
break
multiple = p + p
while multiple <= n:
is_prime[multiple]= False
multiple = multiple + p
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
Running this to 100,000 takes ~25 seconds.
I felt that was on the slow side, so I decided to take a different approach. The Sieve works prospectivly: it works ahead to clear out all multiples. I made a retrospective function, trial-dividing everything lower than the current prime-candidate:
def retrospect(n):
primes = [2, 3]
i = 5
while i <= n:
isprime = True
lim = math.sqrt(n)+1
for p in primes:
if p > lim:
break
if i % p == 0:
isprime = False
break
if isprime:
primes.append(i)
i += 2
return primes
This is way faster!
Questions:
- Are there any obvious shortcomings to the Sieve implementation?
- Is there a point where the retrospect gets slower than the sieve?
python performance python-3.x primes
edited Jul 18 at 12:11
Toby Speight
17.2k13486
17.2k13486
asked Jul 18 at 9:56
steenbergh
320311
320311
add a comment |Â
add a comment |Â
5 Answers
5
active
oldest
votes
up vote
27
down vote
while True:
for i, prime in enumerate(is_prime):
if prime and i > p:
p = i
break
else:
break
This is the cause of the slowness: track the state between loops and the 25 seconds drop to 0.05 seconds.
multiple = p + p
while multiple <= n:
is_prime[multiple]= False
multiple = multiple + p
It's probably more Pythonic to use range here:
for multiple in range(p + p, n + 1, p):
is_prime[multiple] = False
When handling larger inputs, it becomes worthwhile starting at p * p instead of p + p (on the basis that every composite multiple of p smaller than p * p also has a smaller prime factor).
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
IMO it makes more sense to inline this into the main loop.
Edited code at this point:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
primes =
for p in range(2, n+1):
if is_prime[p]:
primes.append(p)
for multiple in range(p * p, n + 1, p):
is_prime[multiple] = False
return primes
Now if you want more speed at the cost of complicating things ever so slightly, you can apply a simple wheel by special-casing the only even prime:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
primes = [2]
for p in range(3, n + 1, 2):
if is_prime[p]:
primes.append(p)
for multiple in range(p * p, n + 1, p + p):
is_prime[multiple] = False
return primes
1
Basically, yourforloop only selects every number in range once and discards it if it isn't prime. The total number of iterations to find the next prime whenn=1000is 831, which when added to the number of primes < n is 999. In my original function, every number is tested again and again, leading to 77296 iterations.
â steenbergh
Jul 19 at 11:04
add a comment |Â
up vote
8
down vote
Your prime sieve is overly complicated. You only need a single loop (and can also make it a generator to potentially save some memory):
def prime_sieve(limit):
prime = [True] * limit
prime[0] = prime[1] = False
for p, is_prime in enumerate(prime):
if is_prime:
yield p
for n in range(p * p, limit, p):
prime[n] = False
This also uses the fact that p + p is already known to be composite for most numbers (since it is 2 * p and all multiples of 2 have already been marked composite once you have added 2 to the primes) and indeed all multiples of n * p for n < p have already been excluded. So it is sufficient to start at p * p, because that is the first multiple that has not been marked of as composite.
This is strictly faster than your retrospect function:

It is also linear with n, whereas retrospect is roughly $mathcalO(n^2)$, due to having to iterate over all already found primes.
In your other function I would also use a for loop. It has the nice feature that it has an else clause that gets executed if the loop was not interrupted with a break statement:
def retrospect(n):
primes = [2, 3]
lim = math.sqrt(n) + 1
for i in range(5, n + 1, 2):
for p in primes:
if p > lim:
break
if i % p == 0:
break
else:
primes.append(i)
return primes
It is also sufficient to calculate lim only once.
Couldn't you take your last 2 lines and combine them into a slice assignment?prime[p*p:limit:p] = Falseshould speed it up even more.
â Sunny Patel
Jul 19 at 21:17
@SunnyPatel That works only with advanced broadcasting rules like innumpy. Vanilla Python needs an iterable of correct length on the right side for that to work.
â Graipher
Jul 19 at 21:20
Oooh, I thought I had implemented one like this before in the same fashion.
â Sunny Patel
Jul 19 at 21:22
add a comment |Â
up vote
8
down vote
Your sieve function is rather convoluted and slow. If we think carefully about what's actually required, for each identified prime number, we cross off multiples. We can stop when we get to $sqrtn$ and each prime cross-out operation for a prime $i$ can start with $i^2$.
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
limit = int(math.sqrt(n))+1
for i in range(2, limit):
if is_prime[i]:
for j in range(i*i, n+1, i):
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
A still faster way to do it would be to note that all even numbers except for 2 are composite (that is, non-prime). We can slightly tweak the code to account for that:
def sieve_of_eratosthenes(n):
is_prime = [False, True] * int(n/2 + 1)
del is_prime[n+1:]
is_prime[1] = False
is_prime[2] = True
limit = int(math.sqrt(n))+1
for i in range(3, limit):
if is_prime[i]:
for j in range(i*i, n+1, 2*i):
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime:
r.append(i)
return r
Performance
Just for fun, I decided to repeat and expand the performance measurement that @Graipher made. Here's the code I used to do it:
import time
import matplotlib.pyplot as plt
def time_algo(algo, times):
result =
for t in times:
start = time.time()
algo(t)
result.append((time.time() - start)*1000)
return result
names = [
#'retrospect',
taylor1,
graipher,
edward1,
taylor2,
edward2,
]
numarray = [1000, 3000,
10000, 30000,
100000, 300000,
1000000, 3000000,
10000000, 30000000,]
trials =
for algo in names:
trials.append(time_algo(algo, numarray))
for t in trials:
plt.plot(numarray, t, '.-')
plt.ylabel('time (ms)')
plt.xlabel('n')
plt.title("Prime algorithm perfomance")
plt.legend([alg.__name__ for alg in names])
plt.show()
Here are the results from the test on my machine:
I've corrected the limit, as noted by @ack.
â Edward
Jul 19 at 14:54
add a comment |Â
up vote
4
down vote
@Edward: corrected limit
def sieve_of_eratosthenes(n):
is_prime = [False, True] * int(n/2 + 1)
n_plus_one = n + 1 # save n+1 for later use
del is_prime[n_plus_one:] #
is_prime[1] = False
is_prime[2] = True
#limit = int(math.sqrt(n))
limit = int(n**.5) + 1 # import math not required, limit corrected!
for i in range(3, limit):
if is_prime[i]:
for j in range(i*i, n_plus_one, 2*i): # limit corrected!
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime:
r.append(i)
return r
without corrected limit s_o_e(9) yields [2,3,5,7,9], so 9 would be prime (as would 11,13,17,...)
I don't think this constitutes an answer, it should probably be a comment on @Edward answer. Once you have enough reputation (50), you will be able to comment everywhere.
â Graipher
Jul 19 at 7:36
@Graipher I agree, though this is a valid point; in fact I believe ack deserves rep for this find. It's a shame to see the user not rewarded for their effort because of a lack of reputation-points...
â steenbergh
Jul 19 at 7:56
@steenbergh I agree that it is a good find. But if they had had more rep and commented this instead, they would not have gotten any rep from upvotes on that comment either.
â Graipher
Jul 19 at 7:58
1
@Graipher I think this is a significant improvement enough to Edward's answer that is possible to stand as its own answer. (For this time)
â Simon Forsbergâ¦
Jul 19 at 8:07
Applied to my answer. Thanks!
â Edward
Jul 19 at 15:03
 |Â
show 3 more comments
up vote
2
down vote
On the performance side, using numpy arrays makes the computations 10 times faster of course.
Using Edward's code for performance, together with the following code ("Edward1" algorithm adapted to numpy) :
def sieve_of_eratosthenes(n):
import numpy as np
is_prime = np.ones(n,dtype=bool)
is_prime[0:2] = False
limit = int(math.sqrt(n))+1
for i in range(2, limit):
if is_prime[i]:
is_prime[np.arange(i*i,n,i)] = False
r = np.where(is_prime == True)[0]
return r
I get on my machine :
Will definitely look into Numpy then!
â steenbergh
Jul 19 at 13:39
1
This reproduces the bug in Edward's code. It's also not actually reviewing the code in the question, so by the standards of this site it shouldn't be an answer.
â Peter Taylor
Jul 19 at 13:40
Sorry about that. This has just been corrected for.
â D. Le Borgne
Jul 19 at 13:41
add a comment |Â
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
27
down vote
while True:
for i, prime in enumerate(is_prime):
if prime and i > p:
p = i
break
else:
break
This is the cause of the slowness: track the state between loops and the 25 seconds drop to 0.05 seconds.
multiple = p + p
while multiple <= n:
is_prime[multiple]= False
multiple = multiple + p
It's probably more Pythonic to use range here:
for multiple in range(p + p, n + 1, p):
is_prime[multiple] = False
When handling larger inputs, it becomes worthwhile starting at p * p instead of p + p (on the basis that every composite multiple of p smaller than p * p also has a smaller prime factor).
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
IMO it makes more sense to inline this into the main loop.
Edited code at this point:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
primes =
for p in range(2, n+1):
if is_prime[p]:
primes.append(p)
for multiple in range(p * p, n + 1, p):
is_prime[multiple] = False
return primes
Now if you want more speed at the cost of complicating things ever so slightly, you can apply a simple wheel by special-casing the only even prime:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
primes = [2]
for p in range(3, n + 1, 2):
if is_prime[p]:
primes.append(p)
for multiple in range(p * p, n + 1, p + p):
is_prime[multiple] = False
return primes
1
Basically, yourforloop only selects every number in range once and discards it if it isn't prime. The total number of iterations to find the next prime whenn=1000is 831, which when added to the number of primes < n is 999. In my original function, every number is tested again and again, leading to 77296 iterations.
â steenbergh
Jul 19 at 11:04
add a comment |Â
up vote
27
down vote
while True:
for i, prime in enumerate(is_prime):
if prime and i > p:
p = i
break
else:
break
This is the cause of the slowness: track the state between loops and the 25 seconds drop to 0.05 seconds.
multiple = p + p
while multiple <= n:
is_prime[multiple]= False
multiple = multiple + p
It's probably more Pythonic to use range here:
for multiple in range(p + p, n + 1, p):
is_prime[multiple] = False
When handling larger inputs, it becomes worthwhile starting at p * p instead of p + p (on the basis that every composite multiple of p smaller than p * p also has a smaller prime factor).
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
IMO it makes more sense to inline this into the main loop.
Edited code at this point:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
primes =
for p in range(2, n+1):
if is_prime[p]:
primes.append(p)
for multiple in range(p * p, n + 1, p):
is_prime[multiple] = False
return primes
Now if you want more speed at the cost of complicating things ever so slightly, you can apply a simple wheel by special-casing the only even prime:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
primes = [2]
for p in range(3, n + 1, 2):
if is_prime[p]:
primes.append(p)
for multiple in range(p * p, n + 1, p + p):
is_prime[multiple] = False
return primes
1
Basically, yourforloop only selects every number in range once and discards it if it isn't prime. The total number of iterations to find the next prime whenn=1000is 831, which when added to the number of primes < n is 999. In my original function, every number is tested again and again, leading to 77296 iterations.
â steenbergh
Jul 19 at 11:04
add a comment |Â
up vote
27
down vote
up vote
27
down vote
while True:
for i, prime in enumerate(is_prime):
if prime and i > p:
p = i
break
else:
break
This is the cause of the slowness: track the state between loops and the 25 seconds drop to 0.05 seconds.
multiple = p + p
while multiple <= n:
is_prime[multiple]= False
multiple = multiple + p
It's probably more Pythonic to use range here:
for multiple in range(p + p, n + 1, p):
is_prime[multiple] = False
When handling larger inputs, it becomes worthwhile starting at p * p instead of p + p (on the basis that every composite multiple of p smaller than p * p also has a smaller prime factor).
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
IMO it makes more sense to inline this into the main loop.
Edited code at this point:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
primes =
for p in range(2, n+1):
if is_prime[p]:
primes.append(p)
for multiple in range(p * p, n + 1, p):
is_prime[multiple] = False
return primes
Now if you want more speed at the cost of complicating things ever so slightly, you can apply a simple wheel by special-casing the only even prime:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
primes = [2]
for p in range(3, n + 1, 2):
if is_prime[p]:
primes.append(p)
for multiple in range(p * p, n + 1, p + p):
is_prime[multiple] = False
return primes
while True:
for i, prime in enumerate(is_prime):
if prime and i > p:
p = i
break
else:
break
This is the cause of the slowness: track the state between loops and the 25 seconds drop to 0.05 seconds.
multiple = p + p
while multiple <= n:
is_prime[multiple]= False
multiple = multiple + p
It's probably more Pythonic to use range here:
for multiple in range(p + p, n + 1, p):
is_prime[multiple] = False
When handling larger inputs, it becomes worthwhile starting at p * p instead of p + p (on the basis that every composite multiple of p smaller than p * p also has a smaller prime factor).
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
IMO it makes more sense to inline this into the main loop.
Edited code at this point:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
primes =
for p in range(2, n+1):
if is_prime[p]:
primes.append(p)
for multiple in range(p * p, n + 1, p):
is_prime[multiple] = False
return primes
Now if you want more speed at the cost of complicating things ever so slightly, you can apply a simple wheel by special-casing the only even prime:
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
primes = [2]
for p in range(3, n + 1, 2):
if is_prime[p]:
primes.append(p)
for multiple in range(p * p, n + 1, p + p):
is_prime[multiple] = False
return primes
edited Jul 18 at 11:41
answered Jul 18 at 11:27
Peter Taylor
14k2454
14k2454
1
Basically, yourforloop only selects every number in range once and discards it if it isn't prime. The total number of iterations to find the next prime whenn=1000is 831, which when added to the number of primes < n is 999. In my original function, every number is tested again and again, leading to 77296 iterations.
â steenbergh
Jul 19 at 11:04
add a comment |Â
1
Basically, yourforloop only selects every number in range once and discards it if it isn't prime. The total number of iterations to find the next prime whenn=1000is 831, which when added to the number of primes < n is 999. In my original function, every number is tested again and again, leading to 77296 iterations.
â steenbergh
Jul 19 at 11:04
1
1
Basically, your
for loop only selects every number in range once and discards it if it isn't prime. The total number of iterations to find the next prime when n=1000 is 831, which when added to the number of primes < n is 999. In my original function, every number is tested again and again, leading to 77296 iterations.â steenbergh
Jul 19 at 11:04
Basically, your
for loop only selects every number in range once and discards it if it isn't prime. The total number of iterations to find the next prime when n=1000 is 831, which when added to the number of primes < n is 999. In my original function, every number is tested again and again, leading to 77296 iterations.â steenbergh
Jul 19 at 11:04
add a comment |Â
up vote
8
down vote
Your prime sieve is overly complicated. You only need a single loop (and can also make it a generator to potentially save some memory):
def prime_sieve(limit):
prime = [True] * limit
prime[0] = prime[1] = False
for p, is_prime in enumerate(prime):
if is_prime:
yield p
for n in range(p * p, limit, p):
prime[n] = False
This also uses the fact that p + p is already known to be composite for most numbers (since it is 2 * p and all multiples of 2 have already been marked composite once you have added 2 to the primes) and indeed all multiples of n * p for n < p have already been excluded. So it is sufficient to start at p * p, because that is the first multiple that has not been marked of as composite.
This is strictly faster than your retrospect function:

It is also linear with n, whereas retrospect is roughly $mathcalO(n^2)$, due to having to iterate over all already found primes.
In your other function I would also use a for loop. It has the nice feature that it has an else clause that gets executed if the loop was not interrupted with a break statement:
def retrospect(n):
primes = [2, 3]
lim = math.sqrt(n) + 1
for i in range(5, n + 1, 2):
for p in primes:
if p > lim:
break
if i % p == 0:
break
else:
primes.append(i)
return primes
It is also sufficient to calculate lim only once.
Couldn't you take your last 2 lines and combine them into a slice assignment?prime[p*p:limit:p] = Falseshould speed it up even more.
â Sunny Patel
Jul 19 at 21:17
@SunnyPatel That works only with advanced broadcasting rules like innumpy. Vanilla Python needs an iterable of correct length on the right side for that to work.
â Graipher
Jul 19 at 21:20
Oooh, I thought I had implemented one like this before in the same fashion.
â Sunny Patel
Jul 19 at 21:22
add a comment |Â
up vote
8
down vote
Your prime sieve is overly complicated. You only need a single loop (and can also make it a generator to potentially save some memory):
def prime_sieve(limit):
prime = [True] * limit
prime[0] = prime[1] = False
for p, is_prime in enumerate(prime):
if is_prime:
yield p
for n in range(p * p, limit, p):
prime[n] = False
This also uses the fact that p + p is already known to be composite for most numbers (since it is 2 * p and all multiples of 2 have already been marked composite once you have added 2 to the primes) and indeed all multiples of n * p for n < p have already been excluded. So it is sufficient to start at p * p, because that is the first multiple that has not been marked of as composite.
This is strictly faster than your retrospect function:

It is also linear with n, whereas retrospect is roughly $mathcalO(n^2)$, due to having to iterate over all already found primes.
In your other function I would also use a for loop. It has the nice feature that it has an else clause that gets executed if the loop was not interrupted with a break statement:
def retrospect(n):
primes = [2, 3]
lim = math.sqrt(n) + 1
for i in range(5, n + 1, 2):
for p in primes:
if p > lim:
break
if i % p == 0:
break
else:
primes.append(i)
return primes
It is also sufficient to calculate lim only once.
Couldn't you take your last 2 lines and combine them into a slice assignment?prime[p*p:limit:p] = Falseshould speed it up even more.
â Sunny Patel
Jul 19 at 21:17
@SunnyPatel That works only with advanced broadcasting rules like innumpy. Vanilla Python needs an iterable of correct length on the right side for that to work.
â Graipher
Jul 19 at 21:20
Oooh, I thought I had implemented one like this before in the same fashion.
â Sunny Patel
Jul 19 at 21:22
add a comment |Â
up vote
8
down vote
up vote
8
down vote
Your prime sieve is overly complicated. You only need a single loop (and can also make it a generator to potentially save some memory):
def prime_sieve(limit):
prime = [True] * limit
prime[0] = prime[1] = False
for p, is_prime in enumerate(prime):
if is_prime:
yield p
for n in range(p * p, limit, p):
prime[n] = False
This also uses the fact that p + p is already known to be composite for most numbers (since it is 2 * p and all multiples of 2 have already been marked composite once you have added 2 to the primes) and indeed all multiples of n * p for n < p have already been excluded. So it is sufficient to start at p * p, because that is the first multiple that has not been marked of as composite.
This is strictly faster than your retrospect function:

It is also linear with n, whereas retrospect is roughly $mathcalO(n^2)$, due to having to iterate over all already found primes.
In your other function I would also use a for loop. It has the nice feature that it has an else clause that gets executed if the loop was not interrupted with a break statement:
def retrospect(n):
primes = [2, 3]
lim = math.sqrt(n) + 1
for i in range(5, n + 1, 2):
for p in primes:
if p > lim:
break
if i % p == 0:
break
else:
primes.append(i)
return primes
It is also sufficient to calculate lim only once.
Your prime sieve is overly complicated. You only need a single loop (and can also make it a generator to potentially save some memory):
def prime_sieve(limit):
prime = [True] * limit
prime[0] = prime[1] = False
for p, is_prime in enumerate(prime):
if is_prime:
yield p
for n in range(p * p, limit, p):
prime[n] = False
This also uses the fact that p + p is already known to be composite for most numbers (since it is 2 * p and all multiples of 2 have already been marked composite once you have added 2 to the primes) and indeed all multiples of n * p for n < p have already been excluded. So it is sufficient to start at p * p, because that is the first multiple that has not been marked of as composite.
This is strictly faster than your retrospect function:

It is also linear with n, whereas retrospect is roughly $mathcalO(n^2)$, due to having to iterate over all already found primes.
In your other function I would also use a for loop. It has the nice feature that it has an else clause that gets executed if the loop was not interrupted with a break statement:
def retrospect(n):
primes = [2, 3]
lim = math.sqrt(n) + 1
for i in range(5, n + 1, 2):
for p in primes:
if p > lim:
break
if i % p == 0:
break
else:
primes.append(i)
return primes
It is also sufficient to calculate lim only once.
edited Jul 18 at 12:14
Toby Speight
17.2k13486
17.2k13486
answered Jul 18 at 11:41
Graipher
20.4k42981
20.4k42981
Couldn't you take your last 2 lines and combine them into a slice assignment?prime[p*p:limit:p] = Falseshould speed it up even more.
â Sunny Patel
Jul 19 at 21:17
@SunnyPatel That works only with advanced broadcasting rules like innumpy. Vanilla Python needs an iterable of correct length on the right side for that to work.
â Graipher
Jul 19 at 21:20
Oooh, I thought I had implemented one like this before in the same fashion.
â Sunny Patel
Jul 19 at 21:22
add a comment |Â
Couldn't you take your last 2 lines and combine them into a slice assignment?prime[p*p:limit:p] = Falseshould speed it up even more.
â Sunny Patel
Jul 19 at 21:17
@SunnyPatel That works only with advanced broadcasting rules like innumpy. Vanilla Python needs an iterable of correct length on the right side for that to work.
â Graipher
Jul 19 at 21:20
Oooh, I thought I had implemented one like this before in the same fashion.
â Sunny Patel
Jul 19 at 21:22
Couldn't you take your last 2 lines and combine them into a slice assignment?
prime[p*p:limit:p] = False should speed it up even more.â Sunny Patel
Jul 19 at 21:17
Couldn't you take your last 2 lines and combine them into a slice assignment?
prime[p*p:limit:p] = False should speed it up even more.â Sunny Patel
Jul 19 at 21:17
@SunnyPatel That works only with advanced broadcasting rules like in
numpy. Vanilla Python needs an iterable of correct length on the right side for that to work.â Graipher
Jul 19 at 21:20
@SunnyPatel That works only with advanced broadcasting rules like in
numpy. Vanilla Python needs an iterable of correct length on the right side for that to work.â Graipher
Jul 19 at 21:20
Oooh, I thought I had implemented one like this before in the same fashion.
â Sunny Patel
Jul 19 at 21:22
Oooh, I thought I had implemented one like this before in the same fashion.
â Sunny Patel
Jul 19 at 21:22
add a comment |Â
up vote
8
down vote
Your sieve function is rather convoluted and slow. If we think carefully about what's actually required, for each identified prime number, we cross off multiples. We can stop when we get to $sqrtn$ and each prime cross-out operation for a prime $i$ can start with $i^2$.
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
limit = int(math.sqrt(n))+1
for i in range(2, limit):
if is_prime[i]:
for j in range(i*i, n+1, i):
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
A still faster way to do it would be to note that all even numbers except for 2 are composite (that is, non-prime). We can slightly tweak the code to account for that:
def sieve_of_eratosthenes(n):
is_prime = [False, True] * int(n/2 + 1)
del is_prime[n+1:]
is_prime[1] = False
is_prime[2] = True
limit = int(math.sqrt(n))+1
for i in range(3, limit):
if is_prime[i]:
for j in range(i*i, n+1, 2*i):
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime:
r.append(i)
return r
Performance
Just for fun, I decided to repeat and expand the performance measurement that @Graipher made. Here's the code I used to do it:
import time
import matplotlib.pyplot as plt
def time_algo(algo, times):
result =
for t in times:
start = time.time()
algo(t)
result.append((time.time() - start)*1000)
return result
names = [
#'retrospect',
taylor1,
graipher,
edward1,
taylor2,
edward2,
]
numarray = [1000, 3000,
10000, 30000,
100000, 300000,
1000000, 3000000,
10000000, 30000000,]
trials =
for algo in names:
trials.append(time_algo(algo, numarray))
for t in trials:
plt.plot(numarray, t, '.-')
plt.ylabel('time (ms)')
plt.xlabel('n')
plt.title("Prime algorithm perfomance")
plt.legend([alg.__name__ for alg in names])
plt.show()
Here are the results from the test on my machine:
I've corrected the limit, as noted by @ack.
â Edward
Jul 19 at 14:54
add a comment |Â
up vote
8
down vote
Your sieve function is rather convoluted and slow. If we think carefully about what's actually required, for each identified prime number, we cross off multiples. We can stop when we get to $sqrtn$ and each prime cross-out operation for a prime $i$ can start with $i^2$.
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
limit = int(math.sqrt(n))+1
for i in range(2, limit):
if is_prime[i]:
for j in range(i*i, n+1, i):
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
A still faster way to do it would be to note that all even numbers except for 2 are composite (that is, non-prime). We can slightly tweak the code to account for that:
def sieve_of_eratosthenes(n):
is_prime = [False, True] * int(n/2 + 1)
del is_prime[n+1:]
is_prime[1] = False
is_prime[2] = True
limit = int(math.sqrt(n))+1
for i in range(3, limit):
if is_prime[i]:
for j in range(i*i, n+1, 2*i):
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime:
r.append(i)
return r
Performance
Just for fun, I decided to repeat and expand the performance measurement that @Graipher made. Here's the code I used to do it:
import time
import matplotlib.pyplot as plt
def time_algo(algo, times):
result =
for t in times:
start = time.time()
algo(t)
result.append((time.time() - start)*1000)
return result
names = [
#'retrospect',
taylor1,
graipher,
edward1,
taylor2,
edward2,
]
numarray = [1000, 3000,
10000, 30000,
100000, 300000,
1000000, 3000000,
10000000, 30000000,]
trials =
for algo in names:
trials.append(time_algo(algo, numarray))
for t in trials:
plt.plot(numarray, t, '.-')
plt.ylabel('time (ms)')
plt.xlabel('n')
plt.title("Prime algorithm perfomance")
plt.legend([alg.__name__ for alg in names])
plt.show()
Here are the results from the test on my machine:
I've corrected the limit, as noted by @ack.
â Edward
Jul 19 at 14:54
add a comment |Â
up vote
8
down vote
up vote
8
down vote
Your sieve function is rather convoluted and slow. If we think carefully about what's actually required, for each identified prime number, we cross off multiples. We can stop when we get to $sqrtn$ and each prime cross-out operation for a prime $i$ can start with $i^2$.
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
limit = int(math.sqrt(n))+1
for i in range(2, limit):
if is_prime[i]:
for j in range(i*i, n+1, i):
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
A still faster way to do it would be to note that all even numbers except for 2 are composite (that is, non-prime). We can slightly tweak the code to account for that:
def sieve_of_eratosthenes(n):
is_prime = [False, True] * int(n/2 + 1)
del is_prime[n+1:]
is_prime[1] = False
is_prime[2] = True
limit = int(math.sqrt(n))+1
for i in range(3, limit):
if is_prime[i]:
for j in range(i*i, n+1, 2*i):
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime:
r.append(i)
return r
Performance
Just for fun, I decided to repeat and expand the performance measurement that @Graipher made. Here's the code I used to do it:
import time
import matplotlib.pyplot as plt
def time_algo(algo, times):
result =
for t in times:
start = time.time()
algo(t)
result.append((time.time() - start)*1000)
return result
names = [
#'retrospect',
taylor1,
graipher,
edward1,
taylor2,
edward2,
]
numarray = [1000, 3000,
10000, 30000,
100000, 300000,
1000000, 3000000,
10000000, 30000000,]
trials =
for algo in names:
trials.append(time_algo(algo, numarray))
for t in trials:
plt.plot(numarray, t, '.-')
plt.ylabel('time (ms)')
plt.xlabel('n')
plt.title("Prime algorithm perfomance")
plt.legend([alg.__name__ for alg in names])
plt.show()
Here are the results from the test on my machine:
Your sieve function is rather convoluted and slow. If we think carefully about what's actually required, for each identified prime number, we cross off multiples. We can stop when we get to $sqrtn$ and each prime cross-out operation for a prime $i$ can start with $i^2$.
def sieve_of_eratosthenes(n):
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False
limit = int(math.sqrt(n))+1
for i in range(2, limit):
if is_prime[i]:
for j in range(i*i, n+1, i):
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime: r.append(i)
return r
A still faster way to do it would be to note that all even numbers except for 2 are composite (that is, non-prime). We can slightly tweak the code to account for that:
def sieve_of_eratosthenes(n):
is_prime = [False, True] * int(n/2 + 1)
del is_prime[n+1:]
is_prime[1] = False
is_prime[2] = True
limit = int(math.sqrt(n))+1
for i in range(3, limit):
if is_prime[i]:
for j in range(i*i, n+1, 2*i):
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime:
r.append(i)
return r
Performance
Just for fun, I decided to repeat and expand the performance measurement that @Graipher made. Here's the code I used to do it:
import time
import matplotlib.pyplot as plt
def time_algo(algo, times):
result =
for t in times:
start = time.time()
algo(t)
result.append((time.time() - start)*1000)
return result
names = [
#'retrospect',
taylor1,
graipher,
edward1,
taylor2,
edward2,
]
numarray = [1000, 3000,
10000, 30000,
100000, 300000,
1000000, 3000000,
10000000, 30000000,]
trials =
for algo in names:
trials.append(time_algo(algo, numarray))
for t in trials:
plt.plot(numarray, t, '.-')
plt.ylabel('time (ms)')
plt.xlabel('n')
plt.title("Prime algorithm perfomance")
plt.legend([alg.__name__ for alg in names])
plt.show()
Here are the results from the test on my machine:
edited Jul 19 at 15:11
answered Jul 18 at 11:41
Edward
43.9k373200
43.9k373200
I've corrected the limit, as noted by @ack.
â Edward
Jul 19 at 14:54
add a comment |Â
I've corrected the limit, as noted by @ack.
â Edward
Jul 19 at 14:54
I've corrected the limit, as noted by @ack.
â Edward
Jul 19 at 14:54
I've corrected the limit, as noted by @ack.
â Edward
Jul 19 at 14:54
add a comment |Â
up vote
4
down vote
@Edward: corrected limit
def sieve_of_eratosthenes(n):
is_prime = [False, True] * int(n/2 + 1)
n_plus_one = n + 1 # save n+1 for later use
del is_prime[n_plus_one:] #
is_prime[1] = False
is_prime[2] = True
#limit = int(math.sqrt(n))
limit = int(n**.5) + 1 # import math not required, limit corrected!
for i in range(3, limit):
if is_prime[i]:
for j in range(i*i, n_plus_one, 2*i): # limit corrected!
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime:
r.append(i)
return r
without corrected limit s_o_e(9) yields [2,3,5,7,9], so 9 would be prime (as would 11,13,17,...)
I don't think this constitutes an answer, it should probably be a comment on @Edward answer. Once you have enough reputation (50), you will be able to comment everywhere.
â Graipher
Jul 19 at 7:36
@Graipher I agree, though this is a valid point; in fact I believe ack deserves rep for this find. It's a shame to see the user not rewarded for their effort because of a lack of reputation-points...
â steenbergh
Jul 19 at 7:56
@steenbergh I agree that it is a good find. But if they had had more rep and commented this instead, they would not have gotten any rep from upvotes on that comment either.
â Graipher
Jul 19 at 7:58
1
@Graipher I think this is a significant improvement enough to Edward's answer that is possible to stand as its own answer. (For this time)
â Simon Forsbergâ¦
Jul 19 at 8:07
Applied to my answer. Thanks!
â Edward
Jul 19 at 15:03
 |Â
show 3 more comments
up vote
4
down vote
@Edward: corrected limit
def sieve_of_eratosthenes(n):
is_prime = [False, True] * int(n/2 + 1)
n_plus_one = n + 1 # save n+1 for later use
del is_prime[n_plus_one:] #
is_prime[1] = False
is_prime[2] = True
#limit = int(math.sqrt(n))
limit = int(n**.5) + 1 # import math not required, limit corrected!
for i in range(3, limit):
if is_prime[i]:
for j in range(i*i, n_plus_one, 2*i): # limit corrected!
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime:
r.append(i)
return r
without corrected limit s_o_e(9) yields [2,3,5,7,9], so 9 would be prime (as would 11,13,17,...)
I don't think this constitutes an answer, it should probably be a comment on @Edward answer. Once you have enough reputation (50), you will be able to comment everywhere.
â Graipher
Jul 19 at 7:36
@Graipher I agree, though this is a valid point; in fact I believe ack deserves rep for this find. It's a shame to see the user not rewarded for their effort because of a lack of reputation-points...
â steenbergh
Jul 19 at 7:56
@steenbergh I agree that it is a good find. But if they had had more rep and commented this instead, they would not have gotten any rep from upvotes on that comment either.
â Graipher
Jul 19 at 7:58
1
@Graipher I think this is a significant improvement enough to Edward's answer that is possible to stand as its own answer. (For this time)
â Simon Forsbergâ¦
Jul 19 at 8:07
Applied to my answer. Thanks!
â Edward
Jul 19 at 15:03
 |Â
show 3 more comments
up vote
4
down vote
up vote
4
down vote
@Edward: corrected limit
def sieve_of_eratosthenes(n):
is_prime = [False, True] * int(n/2 + 1)
n_plus_one = n + 1 # save n+1 for later use
del is_prime[n_plus_one:] #
is_prime[1] = False
is_prime[2] = True
#limit = int(math.sqrt(n))
limit = int(n**.5) + 1 # import math not required, limit corrected!
for i in range(3, limit):
if is_prime[i]:
for j in range(i*i, n_plus_one, 2*i): # limit corrected!
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime:
r.append(i)
return r
without corrected limit s_o_e(9) yields [2,3,5,7,9], so 9 would be prime (as would 11,13,17,...)
@Edward: corrected limit
def sieve_of_eratosthenes(n):
is_prime = [False, True] * int(n/2 + 1)
n_plus_one = n + 1 # save n+1 for later use
del is_prime[n_plus_one:] #
is_prime[1] = False
is_prime[2] = True
#limit = int(math.sqrt(n))
limit = int(n**.5) + 1 # import math not required, limit corrected!
for i in range(3, limit):
if is_prime[i]:
for j in range(i*i, n_plus_one, 2*i): # limit corrected!
is_prime[j] = False
r =
for i, prime in enumerate(is_prime):
if prime:
r.append(i)
return r
without corrected limit s_o_e(9) yields [2,3,5,7,9], so 9 would be prime (as would 11,13,17,...)
answered Jul 19 at 7:23
ack
414
414
I don't think this constitutes an answer, it should probably be a comment on @Edward answer. Once you have enough reputation (50), you will be able to comment everywhere.
â Graipher
Jul 19 at 7:36
@Graipher I agree, though this is a valid point; in fact I believe ack deserves rep for this find. It's a shame to see the user not rewarded for their effort because of a lack of reputation-points...
â steenbergh
Jul 19 at 7:56
@steenbergh I agree that it is a good find. But if they had had more rep and commented this instead, they would not have gotten any rep from upvotes on that comment either.
â Graipher
Jul 19 at 7:58
1
@Graipher I think this is a significant improvement enough to Edward's answer that is possible to stand as its own answer. (For this time)
â Simon Forsbergâ¦
Jul 19 at 8:07
Applied to my answer. Thanks!
â Edward
Jul 19 at 15:03
 |Â
show 3 more comments
I don't think this constitutes an answer, it should probably be a comment on @Edward answer. Once you have enough reputation (50), you will be able to comment everywhere.
â Graipher
Jul 19 at 7:36
@Graipher I agree, though this is a valid point; in fact I believe ack deserves rep for this find. It's a shame to see the user not rewarded for their effort because of a lack of reputation-points...
â steenbergh
Jul 19 at 7:56
@steenbergh I agree that it is a good find. But if they had had more rep and commented this instead, they would not have gotten any rep from upvotes on that comment either.
â Graipher
Jul 19 at 7:58
1
@Graipher I think this is a significant improvement enough to Edward's answer that is possible to stand as its own answer. (For this time)
â Simon Forsbergâ¦
Jul 19 at 8:07
Applied to my answer. Thanks!
â Edward
Jul 19 at 15:03
I don't think this constitutes an answer, it should probably be a comment on @Edward answer. Once you have enough reputation (50), you will be able to comment everywhere.
â Graipher
Jul 19 at 7:36
I don't think this constitutes an answer, it should probably be a comment on @Edward answer. Once you have enough reputation (50), you will be able to comment everywhere.
â Graipher
Jul 19 at 7:36
@Graipher I agree, though this is a valid point; in fact I believe ack deserves rep for this find. It's a shame to see the user not rewarded for their effort because of a lack of reputation-points...
â steenbergh
Jul 19 at 7:56
@Graipher I agree, though this is a valid point; in fact I believe ack deserves rep for this find. It's a shame to see the user not rewarded for their effort because of a lack of reputation-points...
â steenbergh
Jul 19 at 7:56
@steenbergh I agree that it is a good find. But if they had had more rep and commented this instead, they would not have gotten any rep from upvotes on that comment either.
â Graipher
Jul 19 at 7:58
@steenbergh I agree that it is a good find. But if they had had more rep and commented this instead, they would not have gotten any rep from upvotes on that comment either.
â Graipher
Jul 19 at 7:58
1
1
@Graipher I think this is a significant improvement enough to Edward's answer that is possible to stand as its own answer. (For this time)
â Simon Forsbergâ¦
Jul 19 at 8:07
@Graipher I think this is a significant improvement enough to Edward's answer that is possible to stand as its own answer. (For this time)
â Simon Forsbergâ¦
Jul 19 at 8:07
Applied to my answer. Thanks!
â Edward
Jul 19 at 15:03
Applied to my answer. Thanks!
â Edward
Jul 19 at 15:03
 |Â
show 3 more comments
up vote
2
down vote
On the performance side, using numpy arrays makes the computations 10 times faster of course.
Using Edward's code for performance, together with the following code ("Edward1" algorithm adapted to numpy) :
def sieve_of_eratosthenes(n):
import numpy as np
is_prime = np.ones(n,dtype=bool)
is_prime[0:2] = False
limit = int(math.sqrt(n))+1
for i in range(2, limit):
if is_prime[i]:
is_prime[np.arange(i*i,n,i)] = False
r = np.where(is_prime == True)[0]
return r
I get on my machine :
Will definitely look into Numpy then!
â steenbergh
Jul 19 at 13:39
1
This reproduces the bug in Edward's code. It's also not actually reviewing the code in the question, so by the standards of this site it shouldn't be an answer.
â Peter Taylor
Jul 19 at 13:40
Sorry about that. This has just been corrected for.
â D. Le Borgne
Jul 19 at 13:41
add a comment |Â
up vote
2
down vote
On the performance side, using numpy arrays makes the computations 10 times faster of course.
Using Edward's code for performance, together with the following code ("Edward1" algorithm adapted to numpy) :
def sieve_of_eratosthenes(n):
import numpy as np
is_prime = np.ones(n,dtype=bool)
is_prime[0:2] = False
limit = int(math.sqrt(n))+1
for i in range(2, limit):
if is_prime[i]:
is_prime[np.arange(i*i,n,i)] = False
r = np.where(is_prime == True)[0]
return r
I get on my machine :
Will definitely look into Numpy then!
â steenbergh
Jul 19 at 13:39
1
This reproduces the bug in Edward's code. It's also not actually reviewing the code in the question, so by the standards of this site it shouldn't be an answer.
â Peter Taylor
Jul 19 at 13:40
Sorry about that. This has just been corrected for.
â D. Le Borgne
Jul 19 at 13:41
add a comment |Â
up vote
2
down vote
up vote
2
down vote
On the performance side, using numpy arrays makes the computations 10 times faster of course.
Using Edward's code for performance, together with the following code ("Edward1" algorithm adapted to numpy) :
def sieve_of_eratosthenes(n):
import numpy as np
is_prime = np.ones(n,dtype=bool)
is_prime[0:2] = False
limit = int(math.sqrt(n))+1
for i in range(2, limit):
if is_prime[i]:
is_prime[np.arange(i*i,n,i)] = False
r = np.where(is_prime == True)[0]
return r
I get on my machine :
On the performance side, using numpy arrays makes the computations 10 times faster of course.
Using Edward's code for performance, together with the following code ("Edward1" algorithm adapted to numpy) :
def sieve_of_eratosthenes(n):
import numpy as np
is_prime = np.ones(n,dtype=bool)
is_prime[0:2] = False
limit = int(math.sqrt(n))+1
for i in range(2, limit):
if is_prime[i]:
is_prime[np.arange(i*i,n,i)] = False
r = np.where(is_prime == True)[0]
return r
I get on my machine :
edited Jul 19 at 13:40
answered Jul 19 at 13:36
D. Le Borgne
294
294
Will definitely look into Numpy then!
â steenbergh
Jul 19 at 13:39
1
This reproduces the bug in Edward's code. It's also not actually reviewing the code in the question, so by the standards of this site it shouldn't be an answer.
â Peter Taylor
Jul 19 at 13:40
Sorry about that. This has just been corrected for.
â D. Le Borgne
Jul 19 at 13:41
add a comment |Â
Will definitely look into Numpy then!
â steenbergh
Jul 19 at 13:39
1
This reproduces the bug in Edward's code. It's also not actually reviewing the code in the question, so by the standards of this site it shouldn't be an answer.
â Peter Taylor
Jul 19 at 13:40
Sorry about that. This has just been corrected for.
â D. Le Borgne
Jul 19 at 13:41
Will definitely look into Numpy then!
â steenbergh
Jul 19 at 13:39
Will definitely look into Numpy then!
â steenbergh
Jul 19 at 13:39
1
1
This reproduces the bug in Edward's code. It's also not actually reviewing the code in the question, so by the standards of this site it shouldn't be an answer.
â Peter Taylor
Jul 19 at 13:40
This reproduces the bug in Edward's code. It's also not actually reviewing the code in the question, so by the standards of this site it shouldn't be an answer.
â Peter Taylor
Jul 19 at 13:40
Sorry about that. This has just been corrected for.
â D. Le Borgne
Jul 19 at 13:41
Sorry about that. This has just been corrected for.
â D. Le Borgne
Jul 19 at 13:41
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f199734%2fpython-3-why-is-my-prime-sieve-so-slow%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password