Sieve of Eratosthenes - Finding Primes Python
Just to clarify, this is not a homework problem :)
I wanted to find primes for a math application I am building & came across Sieve of Eratosthenes approach.
I have written an implementation of it in Python. But it's terribly slow. For say, if I want to find all primes less than 2 million. It takes > 20 mins. (I stopped it at this point). How can I speed this up?
def primes_sieve(limit):
limitn = limit+1
primes = range(2, limitn)
for i in primes:
factors = range(i, limitn, i)
for f in factors[1:]:
if f in primes:
primes.remove(f)
return primes
print primes_sieve(2000)
UPDATE:
I ended up doing profiling on this code & found that quite a lot of time was spent on removing an element from the list. Quite understandable considering it has to traverse the entire list (worst-case) to find the element & then remove it and then readjust the list (maybe some copy goes on?). Anyway, I chucked out list for dictionary. My new implementation -
def primes_sieve1(limit):
limitn = limit+1
primes = dict()
for i in range(2, limitn): primes[i] = True
for i in primes:
factors = range(i,limitn, i)
for f in factors[1:]:
primes[f] = False
return [i for i in primes if primes[i]==True]
print primes_sieve1(2000000)
python math primes sieve-of-eratosthenes
add a comment |
Just to clarify, this is not a homework problem :)
I wanted to find primes for a math application I am building & came across Sieve of Eratosthenes approach.
I have written an implementation of it in Python. But it's terribly slow. For say, if I want to find all primes less than 2 million. It takes > 20 mins. (I stopped it at this point). How can I speed this up?
def primes_sieve(limit):
limitn = limit+1
primes = range(2, limitn)
for i in primes:
factors = range(i, limitn, i)
for f in factors[1:]:
if f in primes:
primes.remove(f)
return primes
print primes_sieve(2000)
UPDATE:
I ended up doing profiling on this code & found that quite a lot of time was spent on removing an element from the list. Quite understandable considering it has to traverse the entire list (worst-case) to find the element & then remove it and then readjust the list (maybe some copy goes on?). Anyway, I chucked out list for dictionary. My new implementation -
def primes_sieve1(limit):
limitn = limit+1
primes = dict()
for i in range(2, limitn): primes[i] = True
for i in primes:
factors = range(i,limitn, i)
for f in factors[1:]:
primes[f] = False
return [i for i in primes if primes[i]==True]
print primes_sieve1(2000000)
python math primes sieve-of-eratosthenes
1
There's a similar question here stackoverflow.com/questions/2897297 that you might find useful.
– Scott Griffiths
Oct 15 '10 at 8:18
Check that answer.
– tzot
Oct 15 '10 at 19:57
stackoverflow.com/questions/2068372/…
– Robert William Hanks
Oct 18 '10 at 22:57
@Srikar: Rather than iterating upto limit, you can just iterate upto the square root of limit, since any composite number in your dictionary will have one factor less than the square root of limit.
– sayantankhan
Aug 17 '13 at 1:36
Using thestep
parameter torange
is brilliant.factors
is a misnomer and should bemultiples
.
– Tom Russell
Feb 28 '18 at 23:50
add a comment |
Just to clarify, this is not a homework problem :)
I wanted to find primes for a math application I am building & came across Sieve of Eratosthenes approach.
I have written an implementation of it in Python. But it's terribly slow. For say, if I want to find all primes less than 2 million. It takes > 20 mins. (I stopped it at this point). How can I speed this up?
def primes_sieve(limit):
limitn = limit+1
primes = range(2, limitn)
for i in primes:
factors = range(i, limitn, i)
for f in factors[1:]:
if f in primes:
primes.remove(f)
return primes
print primes_sieve(2000)
UPDATE:
I ended up doing profiling on this code & found that quite a lot of time was spent on removing an element from the list. Quite understandable considering it has to traverse the entire list (worst-case) to find the element & then remove it and then readjust the list (maybe some copy goes on?). Anyway, I chucked out list for dictionary. My new implementation -
def primes_sieve1(limit):
limitn = limit+1
primes = dict()
for i in range(2, limitn): primes[i] = True
for i in primes:
factors = range(i,limitn, i)
for f in factors[1:]:
primes[f] = False
return [i for i in primes if primes[i]==True]
print primes_sieve1(2000000)
python math primes sieve-of-eratosthenes
Just to clarify, this is not a homework problem :)
I wanted to find primes for a math application I am building & came across Sieve of Eratosthenes approach.
I have written an implementation of it in Python. But it's terribly slow. For say, if I want to find all primes less than 2 million. It takes > 20 mins. (I stopped it at this point). How can I speed this up?
def primes_sieve(limit):
limitn = limit+1
primes = range(2, limitn)
for i in primes:
factors = range(i, limitn, i)
for f in factors[1:]:
if f in primes:
primes.remove(f)
return primes
print primes_sieve(2000)
UPDATE:
I ended up doing profiling on this code & found that quite a lot of time was spent on removing an element from the list. Quite understandable considering it has to traverse the entire list (worst-case) to find the element & then remove it and then readjust the list (maybe some copy goes on?). Anyway, I chucked out list for dictionary. My new implementation -
def primes_sieve1(limit):
limitn = limit+1
primes = dict()
for i in range(2, limitn): primes[i] = True
for i in primes:
factors = range(i,limitn, i)
for f in factors[1:]:
primes[f] = False
return [i for i in primes if primes[i]==True]
print primes_sieve1(2000000)
python math primes sieve-of-eratosthenes
python math primes sieve-of-eratosthenes
edited Oct 19 '10 at 13:27
starblue
44.8k1176135
44.8k1176135
asked Oct 15 '10 at 5:16
Srikar AppalarajuSrikar Appalaraju
48.9k45183246
48.9k45183246
1
There's a similar question here stackoverflow.com/questions/2897297 that you might find useful.
– Scott Griffiths
Oct 15 '10 at 8:18
Check that answer.
– tzot
Oct 15 '10 at 19:57
stackoverflow.com/questions/2068372/…
– Robert William Hanks
Oct 18 '10 at 22:57
@Srikar: Rather than iterating upto limit, you can just iterate upto the square root of limit, since any composite number in your dictionary will have one factor less than the square root of limit.
– sayantankhan
Aug 17 '13 at 1:36
Using thestep
parameter torange
is brilliant.factors
is a misnomer and should bemultiples
.
– Tom Russell
Feb 28 '18 at 23:50
add a comment |
1
There's a similar question here stackoverflow.com/questions/2897297 that you might find useful.
– Scott Griffiths
Oct 15 '10 at 8:18
Check that answer.
– tzot
Oct 15 '10 at 19:57
stackoverflow.com/questions/2068372/…
– Robert William Hanks
Oct 18 '10 at 22:57
@Srikar: Rather than iterating upto limit, you can just iterate upto the square root of limit, since any composite number in your dictionary will have one factor less than the square root of limit.
– sayantankhan
Aug 17 '13 at 1:36
Using thestep
parameter torange
is brilliant.factors
is a misnomer and should bemultiples
.
– Tom Russell
Feb 28 '18 at 23:50
1
1
There's a similar question here stackoverflow.com/questions/2897297 that you might find useful.
– Scott Griffiths
Oct 15 '10 at 8:18
There's a similar question here stackoverflow.com/questions/2897297 that you might find useful.
– Scott Griffiths
Oct 15 '10 at 8:18
Check that answer.
– tzot
Oct 15 '10 at 19:57
Check that answer.
– tzot
Oct 15 '10 at 19:57
stackoverflow.com/questions/2068372/…
– Robert William Hanks
Oct 18 '10 at 22:57
stackoverflow.com/questions/2068372/…
– Robert William Hanks
Oct 18 '10 at 22:57
@Srikar: Rather than iterating upto limit, you can just iterate upto the square root of limit, since any composite number in your dictionary will have one factor less than the square root of limit.
– sayantankhan
Aug 17 '13 at 1:36
@Srikar: Rather than iterating upto limit, you can just iterate upto the square root of limit, since any composite number in your dictionary will have one factor less than the square root of limit.
– sayantankhan
Aug 17 '13 at 1:36
Using the
step
parameter to range
is brilliant. factors
is a misnomer and should be multiples
.– Tom Russell
Feb 28 '18 at 23:50
Using the
step
parameter to range
is brilliant. factors
is a misnomer and should be multiples
.– Tom Russell
Feb 28 '18 at 23:50
add a comment |
12 Answers
12
active
oldest
votes
You're not quite implementing the correct algorithm:
In your first example, primes_sieve
doesn't maintain a list of primality flags to strike/unset (as in the algorithm), but instead resizes a list of integers continuously, which is very expensive: removing an item from a list requires shifting all subsequent items down by one.
In the second example, primes_sieve1
maintains a dictionary of primality flags, which is a step in the right direction, but it iterates over the dictionary in undefined order, and redundantly strikes out factors of factors (instead of only factors of primes, as in the algorithm). You could fix this by sorting the keys, and skipping non-primes (which already makes it an order of magnitude faster), but it's still much more efficient to just use a list directly.
The correct algorithm (with a list instead of a dictionary) looks something like:
def primes_sieve2(limit):
a = [True] * limit # Initialize the primality list
a[0] = a[1] = False
for (i, isprime) in enumerate(a):
if isprime:
yield i
for n in xrange(i*i, limit, i): # Mark factors non-prime
a[n] = False
(Note that this also includes the algorithmic optimization of starting the non-prime marking at the prime's square (i*i
) instead of its double.)
7
another optimization, the step size of yourxrange(i*i,limit,i)
can be made2*i
– st0le
Oct 21 '10 at 12:20
3
I like your succinct implementation of the Sieve of Eratosthenes. : ) However, I'm having a OverflowError: Python int too large to convert to C long. I changed xrange(i*i, limit, i) to xrange(i, limit, i). Thanks for sharing this code snippet!
– Annie Lagang
Apr 2 '12 at 13:26
10
@st0le: No, the step-size cannot be made2*i
. Just tried it. It yields 14 as a prime.
– mpen
Jul 13 '12 at 1:33
2
@Mark, I'm sorry I didn't really explain it in full. Eliminate all even numbers by doing an iteration withi=2
with steps ofi
but for the rest you can use2*i
. In fact, in my implementation I use half the booleans since I don't store even numbers and instead use a simplemod 2
. You can find my Java implementation here which uses even less (1/8th) the memory. HERE
– st0le
Jul 13 '12 at 3:44
4
+1, just a small detail, if you use[False] * 2 + [True] * (limit-2)
in the initialisation, you can avoid IndexError on passing number < 2 as an argument
– Jan Vorcak
Nov 10 '13 at 17:57
|
show 13 more comments
def eratosthenes(n):
multiples =
for i in range(2, n+1):
if i not in multiples:
print (i)
for j in range(i*i, n+1, i):
multiples.append(j)
eratosthenes(100)
3
instead of a list, I would use a set in order to speed up the membership test
– Copperfield
Sep 4 '16 at 13:36
The last output showing 'None' , how I can remove it?
– tarit goswami
Sep 17 '18 at 12:12
add a comment |
Removing from the beginning of an array (list) requires moving all of the items after it down. That means that removing every element from a list in this way starting from the front is an O(n^2) operation.
You can do this much more efficiently with sets:
def primes_sieve(limit):
limitn = limit+1
not_prime = set()
primes =
for i in range(2, limitn):
if i in not_prime:
continue
for f in range(i*2, limitn, i):
not_prime.add(f)
primes.append(i)
return primes
print primes_sieve(1000000)
... or alternatively, avoid having to rearrange the list:
def primes_sieve(limit):
limitn = limit+1
not_prime = [False] * limitn
primes =
for i in range(2, limitn):
if not_prime[i]:
continue
for f in xrange(i*2, limitn, i):
not_prime[f] = True
primes.append(i)
return primes
2
See @Piet Delport answer below for an optimization: replacei*2
above withi*i
.
– James K Polk
Oct 17 '10 at 14:44
Hey, would you mind explaining your code to me?
– cyril
Sep 27 '15 at 19:40
add a comment |
I realise this isn't really answering the question of how to generate primes quickly, but perhaps some will find this alternative interesting: because python provides lazy evaluation via generators, eratosthenes' sieve can be implemented exactly as stated:
def intsfrom(n):
while True:
yield n
n += 1
def sieve(ilist):
p = next(ilist)
yield p
for q in sieve(n for n in ilist if n%p != 0):
yield q
try:
for p in sieve(intsfrom(2)):
print p,
print ''
except RuntimeError as e:
print e
The try block is there because the algorithm runs until it blows the stack and without the
try block the backtrace is displayed pushing the actual output you want to see off screen.
3
no, it's not the sieve of Eratosthenes, but rather a sieve of trial division. Even that is very suboptimal, because it's not postponed: any candidate number need only be tested by primes not above its square root. Implementing this along the lines of the pseudocode at the bottom of the linked above answer (the latter one) will give your code immense speedup (even before you switch to the proper sieve) and/because it'll greatly minimize the stack usage - so you mightn't need yourtry
block after all.
– Will Ness
Jul 21 '14 at 14:11
... see also: more discussion about the "sqrt" issue and its effects, an actual Python code for a postponed trial division, and some related Scala. --- And kudos to you, if you came up with that code on your own! :)
– Will Ness
Jul 21 '14 at 14:15
Interesting, although I'm not yet understanding why what I put is different from the sieve of Eratosthenes. I thought it was described as placing all the intergers from 2 in a line, then repeadly take the first in the line as a prime and strike out all multiples. the "n for n in ilist if n%p != 0" bit was supposed to represent striking out the multiples. Admittedly highly suboptimal though, definitely
– Paul Gardiner
Feb 18 '15 at 14:05
n for n in ilist if n%p != 0
tests each numbern
in a range for divisibility byp
; butrange(p*p, N, p)
generates the multiples directly, all by itself, without testing all these numbers.
– Will Ness
Feb 25 '15 at 4:06
@marisbest2 it is not. it counts fromn
toinfinity
, rather than from0
ton-1
– TemporalWolf
Nov 18 '16 at 23:46
|
show 1 more comment
By combining contributions from many enthusiasts (including Glenn Maynard and MrHIDEn from above comments), I came up with following piece of code in python 2:
def simpleSieve(sieveSize):
#creating Sieve.
sieve = [True] * (sieveSize+1)
# 0 and 1 are not considered prime.
sieve[0] = False
sieve[1] = False
for i in xrange(2,int(math.sqrt(sieveSize))+1):
if sieve[i] == False:
continue
for pointer in xrange(i**2, sieveSize+1, i):
sieve[pointer] = False
# Sieve is left with prime numbers == True
primes =
for i in xrange(sieveSize+1):
if sieve[i] == True:
primes.append(i)
return primes
sieveSize = input()
primes = simpleSieve(sieveSize)
Time taken for computation on my machine for different inputs in power of 10 is:
- 3 : 0.3 ms
- 4 : 2.4 ms
- 5 : 23 ms
- 6 : 0.26 s
- 7 : 3.1 s
- 8 : 33 s
the comparison with True or False are unneeded more so as they are already Boolean,
– Copperfield
Sep 4 '16 at 13:32
@Copperfield Thanks! It helped in increasing speed by 10-20%.
– Ajay
Sep 4 '16 at 20:04
Thissieve = [True] * (sieveSize+1)
is faster than my solution, butsieve[0]/[1]
andxrange(sieveSize+1)
at primes does not improve anything.xrange(2, sieveSize+1)
is good enouth. :). Also instead offor i in xrange(2,int(math.sqrt(sieveSize))+1):
we can just usefor i in xrange(2, int((sieveSize+1)**0.5):
Good code. :)
– MrHIDEn
Nov 28 '16 at 8:49
add a comment |
Much faster:
import time
def get_primes(n):
m = n+1
#numbers = [True for i in range(m)]
numbers = [True] * m #EDIT: faster
for i in range(2, int(n**0.5 + 1)):
if numbers[i]:
for j in range(i*i, m, i):
numbers[j] = False
primes =
for i in range(2, m):
if numbers[i]:
primes.append(i)
return primes
start = time.time()
primes = get_primes(10000)
print(time.time() - start)
print(get_primes(100))
add a comment |
A simple speed hack: when you define the variable "primes," set the step to 2 to skip all even numbers automatically, and set the starting point to 1.
Then you can further optimize by instead of for i in primes, use for i in primes[:round(len(primes) ** 0.5)]. That will dramatically increase performance. In addition, you can eliminate numbers ending with 5 to further increase speed.
add a comment |
My implementation:
import math
n = 100
marked = {}
for i in range(2, int(math.sqrt(n))):
if not marked.get(i):
for x in range(i * i, n, i):
marked[x] = True
for i in range(2, n):
if not marked.get(i):
print i
I just testet your code and I seedict
solution is 2 times slower thanlist
solution.
– MrHIDEn
Nov 28 '16 at 8:54
add a comment |
Here's a version that's a bit more memory-efficient (and: a proper sieve, not trial divisions). Basically, instead of keeping an array of all the numbers, and crossing out those that aren't prime, this keeps an array of counters - one for each prime it's discovered - and leap-frogging them ahead of the putative prime. That way, it uses storage proportional to the number of primes, not up to to the highest prime.
import itertools
def primes():
class counter:
def __init__ (this, n): this.n, this.current, this.isVirgin = n, n*n, True
# isVirgin means it's never been incremented
def advancePast (this, n): # return true if the counter advanced
if this.current > n:
if this.isVirgin: raise StopIteration # if this is virgin, then so will be all the subsequent counters. Don't need to iterate further.
return False
this.current += this.n # pre: this.current == n; post: this.current > n.
this.isVirgin = False # when it's gone, it's gone
return True
yield 1
multiples =
for n in itertools.count(2):
isPrime = True
for p in (m.advancePast(n) for m in multiples):
if p: isPrime = False
if isPrime:
yield n
multiples.append (counter (n))
You'll note that primes()
is a generator, so you can keep the results in a list or you can use them directly. Here's the first n
primes:
import itertools
for k in itertools.islice (primes(), n):
print (k)
And, for completeness, here's a timer to measure the performance:
import time
def timer ():
t, k = time.process_time(), 10
for p in primes():
if p>k:
print (time.process_time()-t, " to ", p, "n")
k *= 10
if k>100000: return
Just in case you're wondering, I also wrote primes()
as a simple iterator (using __iter__
and __next__
), and it ran at almost the same speed. Surprised me too!
interesting idea - it would improve performance if you store the prime counters in a min-heap though (inner loop would be O(log num_primes) instead of O(num_primes))
– anthonybell
Jul 25 '17 at 17:34
Why? Even if they were in a heap, we still have to account for every one.
– Jules May
Jul 26 '17 at 10:26
If you store each prime in the heap keyed by it's next value you would only have to look at primes whose next value is the current value n. the largest primes will sink to the bottom of the heap and would need to be evaluated much more rarely than the smaller primes.
– anthonybell
Jul 26 '17 at 19:30
add a comment |
I prefer NumPy because of speed.
import numpy as np
# Find all prime numbers using Sieve of Eratosthenes
def get_primes1(n):
m = int(np.sqrt(n))
is_prime = np.ones(n, dtype=bool)
is_prime[:2] = False # 0 and 1 are not primes
for i in range(2, m):
if is_prime[i] == False:
continue
is_prime[i*i::i] = False
return np.nonzero(is_prime)[0]
# Find all prime numbers using brute-force.
def isprime(n):
''' Check if integer n is a prime '''
n = abs(int(n)) # n is a positive integer
if n < 2: # 0 and 1 are not primes
return False
if n == 2: # 2 is the only even prime number
return True
if not n & 1: # all other even numbers are not primes
return False
# Range starts with 3 and only needs to go up the square root
# of n for all odd numbers
for x in range(3, int(n**0.5)+1, 2):
if n % x == 0:
return False
return True
# To apply a function to a numpy array, one have to vectorize the function
def get_primes2(n):
vectorized_isprime = np.vectorize(isprime)
a = np.arange(n)
return a[vectorized_isprime(a)]
Check the output:
n = 100
print(get_primes1(n))
print(get_primes2(n))
[ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
[ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
Compare the speed of Sieve of Eratosthenes and brute-force on Jupyter Notebook. Sieve of Eratosthenes in 539 times faster than brute-force for million elements.
%timeit get_primes1(1000000)
%timeit get_primes2(1000000)
4.79 ms ± 90.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.58 s ± 31.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
add a comment |
I figured it must be possible to simply use the empty list as the terminating condition for the loop and came up with this:
limit = 100
ints = list(range(2, limit)) # Will end up empty
while len(ints) > 0:
prime = ints[0]
print prime
ints.remove(prime)
i = 2
multiple = prime * i
while multiple <= limit:
if multiple in ints:
ints.remove(multiple)
i += 1
multiple = prime * i
add a comment |
import math
def sieve(n):
primes = [True]*n
primes[0] = False
primes[1] = False
for i in range(2,int(math.sqrt(n))+1):
j = i*i
while j < n:
primes[j] = False
j = j+i
return [x for x in range(n) if primes[x] == True]
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f3939660%2fsieve-of-eratosthenes-finding-primes-python%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
12 Answers
12
active
oldest
votes
12 Answers
12
active
oldest
votes
active
oldest
votes
active
oldest
votes
You're not quite implementing the correct algorithm:
In your first example, primes_sieve
doesn't maintain a list of primality flags to strike/unset (as in the algorithm), but instead resizes a list of integers continuously, which is very expensive: removing an item from a list requires shifting all subsequent items down by one.
In the second example, primes_sieve1
maintains a dictionary of primality flags, which is a step in the right direction, but it iterates over the dictionary in undefined order, and redundantly strikes out factors of factors (instead of only factors of primes, as in the algorithm). You could fix this by sorting the keys, and skipping non-primes (which already makes it an order of magnitude faster), but it's still much more efficient to just use a list directly.
The correct algorithm (with a list instead of a dictionary) looks something like:
def primes_sieve2(limit):
a = [True] * limit # Initialize the primality list
a[0] = a[1] = False
for (i, isprime) in enumerate(a):
if isprime:
yield i
for n in xrange(i*i, limit, i): # Mark factors non-prime
a[n] = False
(Note that this also includes the algorithmic optimization of starting the non-prime marking at the prime's square (i*i
) instead of its double.)
7
another optimization, the step size of yourxrange(i*i,limit,i)
can be made2*i
– st0le
Oct 21 '10 at 12:20
3
I like your succinct implementation of the Sieve of Eratosthenes. : ) However, I'm having a OverflowError: Python int too large to convert to C long. I changed xrange(i*i, limit, i) to xrange(i, limit, i). Thanks for sharing this code snippet!
– Annie Lagang
Apr 2 '12 at 13:26
10
@st0le: No, the step-size cannot be made2*i
. Just tried it. It yields 14 as a prime.
– mpen
Jul 13 '12 at 1:33
2
@Mark, I'm sorry I didn't really explain it in full. Eliminate all even numbers by doing an iteration withi=2
with steps ofi
but for the rest you can use2*i
. In fact, in my implementation I use half the booleans since I don't store even numbers and instead use a simplemod 2
. You can find my Java implementation here which uses even less (1/8th) the memory. HERE
– st0le
Jul 13 '12 at 3:44
4
+1, just a small detail, if you use[False] * 2 + [True] * (limit-2)
in the initialisation, you can avoid IndexError on passing number < 2 as an argument
– Jan Vorcak
Nov 10 '13 at 17:57
|
show 13 more comments
You're not quite implementing the correct algorithm:
In your first example, primes_sieve
doesn't maintain a list of primality flags to strike/unset (as in the algorithm), but instead resizes a list of integers continuously, which is very expensive: removing an item from a list requires shifting all subsequent items down by one.
In the second example, primes_sieve1
maintains a dictionary of primality flags, which is a step in the right direction, but it iterates over the dictionary in undefined order, and redundantly strikes out factors of factors (instead of only factors of primes, as in the algorithm). You could fix this by sorting the keys, and skipping non-primes (which already makes it an order of magnitude faster), but it's still much more efficient to just use a list directly.
The correct algorithm (with a list instead of a dictionary) looks something like:
def primes_sieve2(limit):
a = [True] * limit # Initialize the primality list
a[0] = a[1] = False
for (i, isprime) in enumerate(a):
if isprime:
yield i
for n in xrange(i*i, limit, i): # Mark factors non-prime
a[n] = False
(Note that this also includes the algorithmic optimization of starting the non-prime marking at the prime's square (i*i
) instead of its double.)
7
another optimization, the step size of yourxrange(i*i,limit,i)
can be made2*i
– st0le
Oct 21 '10 at 12:20
3
I like your succinct implementation of the Sieve of Eratosthenes. : ) However, I'm having a OverflowError: Python int too large to convert to C long. I changed xrange(i*i, limit, i) to xrange(i, limit, i). Thanks for sharing this code snippet!
– Annie Lagang
Apr 2 '12 at 13:26
10
@st0le: No, the step-size cannot be made2*i
. Just tried it. It yields 14 as a prime.
– mpen
Jul 13 '12 at 1:33
2
@Mark, I'm sorry I didn't really explain it in full. Eliminate all even numbers by doing an iteration withi=2
with steps ofi
but for the rest you can use2*i
. In fact, in my implementation I use half the booleans since I don't store even numbers and instead use a simplemod 2
. You can find my Java implementation here which uses even less (1/8th) the memory. HERE
– st0le
Jul 13 '12 at 3:44
4
+1, just a small detail, if you use[False] * 2 + [True] * (limit-2)
in the initialisation, you can avoid IndexError on passing number < 2 as an argument
– Jan Vorcak
Nov 10 '13 at 17:57
|
show 13 more comments
You're not quite implementing the correct algorithm:
In your first example, primes_sieve
doesn't maintain a list of primality flags to strike/unset (as in the algorithm), but instead resizes a list of integers continuously, which is very expensive: removing an item from a list requires shifting all subsequent items down by one.
In the second example, primes_sieve1
maintains a dictionary of primality flags, which is a step in the right direction, but it iterates over the dictionary in undefined order, and redundantly strikes out factors of factors (instead of only factors of primes, as in the algorithm). You could fix this by sorting the keys, and skipping non-primes (which already makes it an order of magnitude faster), but it's still much more efficient to just use a list directly.
The correct algorithm (with a list instead of a dictionary) looks something like:
def primes_sieve2(limit):
a = [True] * limit # Initialize the primality list
a[0] = a[1] = False
for (i, isprime) in enumerate(a):
if isprime:
yield i
for n in xrange(i*i, limit, i): # Mark factors non-prime
a[n] = False
(Note that this also includes the algorithmic optimization of starting the non-prime marking at the prime's square (i*i
) instead of its double.)
You're not quite implementing the correct algorithm:
In your first example, primes_sieve
doesn't maintain a list of primality flags to strike/unset (as in the algorithm), but instead resizes a list of integers continuously, which is very expensive: removing an item from a list requires shifting all subsequent items down by one.
In the second example, primes_sieve1
maintains a dictionary of primality flags, which is a step in the right direction, but it iterates over the dictionary in undefined order, and redundantly strikes out factors of factors (instead of only factors of primes, as in the algorithm). You could fix this by sorting the keys, and skipping non-primes (which already makes it an order of magnitude faster), but it's still much more efficient to just use a list directly.
The correct algorithm (with a list instead of a dictionary) looks something like:
def primes_sieve2(limit):
a = [True] * limit # Initialize the primality list
a[0] = a[1] = False
for (i, isprime) in enumerate(a):
if isprime:
yield i
for n in xrange(i*i, limit, i): # Mark factors non-prime
a[n] = False
(Note that this also includes the algorithmic optimization of starting the non-prime marking at the prime's square (i*i
) instead of its double.)
answered Oct 15 '10 at 11:54
Pi DelportPi Delport
7,81123247
7,81123247
7
another optimization, the step size of yourxrange(i*i,limit,i)
can be made2*i
– st0le
Oct 21 '10 at 12:20
3
I like your succinct implementation of the Sieve of Eratosthenes. : ) However, I'm having a OverflowError: Python int too large to convert to C long. I changed xrange(i*i, limit, i) to xrange(i, limit, i). Thanks for sharing this code snippet!
– Annie Lagang
Apr 2 '12 at 13:26
10
@st0le: No, the step-size cannot be made2*i
. Just tried it. It yields 14 as a prime.
– mpen
Jul 13 '12 at 1:33
2
@Mark, I'm sorry I didn't really explain it in full. Eliminate all even numbers by doing an iteration withi=2
with steps ofi
but for the rest you can use2*i
. In fact, in my implementation I use half the booleans since I don't store even numbers and instead use a simplemod 2
. You can find my Java implementation here which uses even less (1/8th) the memory. HERE
– st0le
Jul 13 '12 at 3:44
4
+1, just a small detail, if you use[False] * 2 + [True] * (limit-2)
in the initialisation, you can avoid IndexError on passing number < 2 as an argument
– Jan Vorcak
Nov 10 '13 at 17:57
|
show 13 more comments
7
another optimization, the step size of yourxrange(i*i,limit,i)
can be made2*i
– st0le
Oct 21 '10 at 12:20
3
I like your succinct implementation of the Sieve of Eratosthenes. : ) However, I'm having a OverflowError: Python int too large to convert to C long. I changed xrange(i*i, limit, i) to xrange(i, limit, i). Thanks for sharing this code snippet!
– Annie Lagang
Apr 2 '12 at 13:26
10
@st0le: No, the step-size cannot be made2*i
. Just tried it. It yields 14 as a prime.
– mpen
Jul 13 '12 at 1:33
2
@Mark, I'm sorry I didn't really explain it in full. Eliminate all even numbers by doing an iteration withi=2
with steps ofi
but for the rest you can use2*i
. In fact, in my implementation I use half the booleans since I don't store even numbers and instead use a simplemod 2
. You can find my Java implementation here which uses even less (1/8th) the memory. HERE
– st0le
Jul 13 '12 at 3:44
4
+1, just a small detail, if you use[False] * 2 + [True] * (limit-2)
in the initialisation, you can avoid IndexError on passing number < 2 as an argument
– Jan Vorcak
Nov 10 '13 at 17:57
7
7
another optimization, the step size of your
xrange(i*i,limit,i)
can be made 2*i
– st0le
Oct 21 '10 at 12:20
another optimization, the step size of your
xrange(i*i,limit,i)
can be made 2*i
– st0le
Oct 21 '10 at 12:20
3
3
I like your succinct implementation of the Sieve of Eratosthenes. : ) However, I'm having a OverflowError: Python int too large to convert to C long. I changed xrange(i*i, limit, i) to xrange(i, limit, i). Thanks for sharing this code snippet!
– Annie Lagang
Apr 2 '12 at 13:26
I like your succinct implementation of the Sieve of Eratosthenes. : ) However, I'm having a OverflowError: Python int too large to convert to C long. I changed xrange(i*i, limit, i) to xrange(i, limit, i). Thanks for sharing this code snippet!
– Annie Lagang
Apr 2 '12 at 13:26
10
10
@st0le: No, the step-size cannot be made
2*i
. Just tried it. It yields 14 as a prime.– mpen
Jul 13 '12 at 1:33
@st0le: No, the step-size cannot be made
2*i
. Just tried it. It yields 14 as a prime.– mpen
Jul 13 '12 at 1:33
2
2
@Mark, I'm sorry I didn't really explain it in full. Eliminate all even numbers by doing an iteration with
i=2
with steps of i
but for the rest you can use 2*i
. In fact, in my implementation I use half the booleans since I don't store even numbers and instead use a simple mod 2
. You can find my Java implementation here which uses even less (1/8th) the memory. HERE– st0le
Jul 13 '12 at 3:44
@Mark, I'm sorry I didn't really explain it in full. Eliminate all even numbers by doing an iteration with
i=2
with steps of i
but for the rest you can use 2*i
. In fact, in my implementation I use half the booleans since I don't store even numbers and instead use a simple mod 2
. You can find my Java implementation here which uses even less (1/8th) the memory. HERE– st0le
Jul 13 '12 at 3:44
4
4
+1, just a small detail, if you use
[False] * 2 + [True] * (limit-2)
in the initialisation, you can avoid IndexError on passing number < 2 as an argument– Jan Vorcak
Nov 10 '13 at 17:57
+1, just a small detail, if you use
[False] * 2 + [True] * (limit-2)
in the initialisation, you can avoid IndexError on passing number < 2 as an argument– Jan Vorcak
Nov 10 '13 at 17:57
|
show 13 more comments
def eratosthenes(n):
multiples =
for i in range(2, n+1):
if i not in multiples:
print (i)
for j in range(i*i, n+1, i):
multiples.append(j)
eratosthenes(100)
3
instead of a list, I would use a set in order to speed up the membership test
– Copperfield
Sep 4 '16 at 13:36
The last output showing 'None' , how I can remove it?
– tarit goswami
Sep 17 '18 at 12:12
add a comment |
def eratosthenes(n):
multiples =
for i in range(2, n+1):
if i not in multiples:
print (i)
for j in range(i*i, n+1, i):
multiples.append(j)
eratosthenes(100)
3
instead of a list, I would use a set in order to speed up the membership test
– Copperfield
Sep 4 '16 at 13:36
The last output showing 'None' , how I can remove it?
– tarit goswami
Sep 17 '18 at 12:12
add a comment |
def eratosthenes(n):
multiples =
for i in range(2, n+1):
if i not in multiples:
print (i)
for j in range(i*i, n+1, i):
multiples.append(j)
eratosthenes(100)
def eratosthenes(n):
multiples =
for i in range(2, n+1):
if i not in multiples:
print (i)
for j in range(i*i, n+1, i):
multiples.append(j)
eratosthenes(100)
answered Jan 4 '14 at 18:01
Saurabh RanaSaurabh Rana
1,64611218
1,64611218
3
instead of a list, I would use a set in order to speed up the membership test
– Copperfield
Sep 4 '16 at 13:36
The last output showing 'None' , how I can remove it?
– tarit goswami
Sep 17 '18 at 12:12
add a comment |
3
instead of a list, I would use a set in order to speed up the membership test
– Copperfield
Sep 4 '16 at 13:36
The last output showing 'None' , how I can remove it?
– tarit goswami
Sep 17 '18 at 12:12
3
3
instead of a list, I would use a set in order to speed up the membership test
– Copperfield
Sep 4 '16 at 13:36
instead of a list, I would use a set in order to speed up the membership test
– Copperfield
Sep 4 '16 at 13:36
The last output showing 'None' , how I can remove it?
– tarit goswami
Sep 17 '18 at 12:12
The last output showing 'None' , how I can remove it?
– tarit goswami
Sep 17 '18 at 12:12
add a comment |
Removing from the beginning of an array (list) requires moving all of the items after it down. That means that removing every element from a list in this way starting from the front is an O(n^2) operation.
You can do this much more efficiently with sets:
def primes_sieve(limit):
limitn = limit+1
not_prime = set()
primes =
for i in range(2, limitn):
if i in not_prime:
continue
for f in range(i*2, limitn, i):
not_prime.add(f)
primes.append(i)
return primes
print primes_sieve(1000000)
... or alternatively, avoid having to rearrange the list:
def primes_sieve(limit):
limitn = limit+1
not_prime = [False] * limitn
primes =
for i in range(2, limitn):
if not_prime[i]:
continue
for f in xrange(i*2, limitn, i):
not_prime[f] = True
primes.append(i)
return primes
2
See @Piet Delport answer below for an optimization: replacei*2
above withi*i
.
– James K Polk
Oct 17 '10 at 14:44
Hey, would you mind explaining your code to me?
– cyril
Sep 27 '15 at 19:40
add a comment |
Removing from the beginning of an array (list) requires moving all of the items after it down. That means that removing every element from a list in this way starting from the front is an O(n^2) operation.
You can do this much more efficiently with sets:
def primes_sieve(limit):
limitn = limit+1
not_prime = set()
primes =
for i in range(2, limitn):
if i in not_prime:
continue
for f in range(i*2, limitn, i):
not_prime.add(f)
primes.append(i)
return primes
print primes_sieve(1000000)
... or alternatively, avoid having to rearrange the list:
def primes_sieve(limit):
limitn = limit+1
not_prime = [False] * limitn
primes =
for i in range(2, limitn):
if not_prime[i]:
continue
for f in xrange(i*2, limitn, i):
not_prime[f] = True
primes.append(i)
return primes
2
See @Piet Delport answer below for an optimization: replacei*2
above withi*i
.
– James K Polk
Oct 17 '10 at 14:44
Hey, would you mind explaining your code to me?
– cyril
Sep 27 '15 at 19:40
add a comment |
Removing from the beginning of an array (list) requires moving all of the items after it down. That means that removing every element from a list in this way starting from the front is an O(n^2) operation.
You can do this much more efficiently with sets:
def primes_sieve(limit):
limitn = limit+1
not_prime = set()
primes =
for i in range(2, limitn):
if i in not_prime:
continue
for f in range(i*2, limitn, i):
not_prime.add(f)
primes.append(i)
return primes
print primes_sieve(1000000)
... or alternatively, avoid having to rearrange the list:
def primes_sieve(limit):
limitn = limit+1
not_prime = [False] * limitn
primes =
for i in range(2, limitn):
if not_prime[i]:
continue
for f in xrange(i*2, limitn, i):
not_prime[f] = True
primes.append(i)
return primes
Removing from the beginning of an array (list) requires moving all of the items after it down. That means that removing every element from a list in this way starting from the front is an O(n^2) operation.
You can do this much more efficiently with sets:
def primes_sieve(limit):
limitn = limit+1
not_prime = set()
primes =
for i in range(2, limitn):
if i in not_prime:
continue
for f in range(i*2, limitn, i):
not_prime.add(f)
primes.append(i)
return primes
print primes_sieve(1000000)
... or alternatively, avoid having to rearrange the list:
def primes_sieve(limit):
limitn = limit+1
not_prime = [False] * limitn
primes =
for i in range(2, limitn):
if not_prime[i]:
continue
for f in xrange(i*2, limitn, i):
not_prime[f] = True
primes.append(i)
return primes
edited Oct 15 '10 at 6:03
answered Oct 15 '10 at 5:27
Glenn MaynardGlenn Maynard
42.8k692121
42.8k692121
2
See @Piet Delport answer below for an optimization: replacei*2
above withi*i
.
– James K Polk
Oct 17 '10 at 14:44
Hey, would you mind explaining your code to me?
– cyril
Sep 27 '15 at 19:40
add a comment |
2
See @Piet Delport answer below for an optimization: replacei*2
above withi*i
.
– James K Polk
Oct 17 '10 at 14:44
Hey, would you mind explaining your code to me?
– cyril
Sep 27 '15 at 19:40
2
2
See @Piet Delport answer below for an optimization: replace
i*2
above with i*i
.– James K Polk
Oct 17 '10 at 14:44
See @Piet Delport answer below for an optimization: replace
i*2
above with i*i
.– James K Polk
Oct 17 '10 at 14:44
Hey, would you mind explaining your code to me?
– cyril
Sep 27 '15 at 19:40
Hey, would you mind explaining your code to me?
– cyril
Sep 27 '15 at 19:40
add a comment |
I realise this isn't really answering the question of how to generate primes quickly, but perhaps some will find this alternative interesting: because python provides lazy evaluation via generators, eratosthenes' sieve can be implemented exactly as stated:
def intsfrom(n):
while True:
yield n
n += 1
def sieve(ilist):
p = next(ilist)
yield p
for q in sieve(n for n in ilist if n%p != 0):
yield q
try:
for p in sieve(intsfrom(2)):
print p,
print ''
except RuntimeError as e:
print e
The try block is there because the algorithm runs until it blows the stack and without the
try block the backtrace is displayed pushing the actual output you want to see off screen.
3
no, it's not the sieve of Eratosthenes, but rather a sieve of trial division. Even that is very suboptimal, because it's not postponed: any candidate number need only be tested by primes not above its square root. Implementing this along the lines of the pseudocode at the bottom of the linked above answer (the latter one) will give your code immense speedup (even before you switch to the proper sieve) and/because it'll greatly minimize the stack usage - so you mightn't need yourtry
block after all.
– Will Ness
Jul 21 '14 at 14:11
... see also: more discussion about the "sqrt" issue and its effects, an actual Python code for a postponed trial division, and some related Scala. --- And kudos to you, if you came up with that code on your own! :)
– Will Ness
Jul 21 '14 at 14:15
Interesting, although I'm not yet understanding why what I put is different from the sieve of Eratosthenes. I thought it was described as placing all the intergers from 2 in a line, then repeadly take the first in the line as a prime and strike out all multiples. the "n for n in ilist if n%p != 0" bit was supposed to represent striking out the multiples. Admittedly highly suboptimal though, definitely
– Paul Gardiner
Feb 18 '15 at 14:05
n for n in ilist if n%p != 0
tests each numbern
in a range for divisibility byp
; butrange(p*p, N, p)
generates the multiples directly, all by itself, without testing all these numbers.
– Will Ness
Feb 25 '15 at 4:06
@marisbest2 it is not. it counts fromn
toinfinity
, rather than from0
ton-1
– TemporalWolf
Nov 18 '16 at 23:46
|
show 1 more comment
I realise this isn't really answering the question of how to generate primes quickly, but perhaps some will find this alternative interesting: because python provides lazy evaluation via generators, eratosthenes' sieve can be implemented exactly as stated:
def intsfrom(n):
while True:
yield n
n += 1
def sieve(ilist):
p = next(ilist)
yield p
for q in sieve(n for n in ilist if n%p != 0):
yield q
try:
for p in sieve(intsfrom(2)):
print p,
print ''
except RuntimeError as e:
print e
The try block is there because the algorithm runs until it blows the stack and without the
try block the backtrace is displayed pushing the actual output you want to see off screen.
3
no, it's not the sieve of Eratosthenes, but rather a sieve of trial division. Even that is very suboptimal, because it's not postponed: any candidate number need only be tested by primes not above its square root. Implementing this along the lines of the pseudocode at the bottom of the linked above answer (the latter one) will give your code immense speedup (even before you switch to the proper sieve) and/because it'll greatly minimize the stack usage - so you mightn't need yourtry
block after all.
– Will Ness
Jul 21 '14 at 14:11
... see also: more discussion about the "sqrt" issue and its effects, an actual Python code for a postponed trial division, and some related Scala. --- And kudos to you, if you came up with that code on your own! :)
– Will Ness
Jul 21 '14 at 14:15
Interesting, although I'm not yet understanding why what I put is different from the sieve of Eratosthenes. I thought it was described as placing all the intergers from 2 in a line, then repeadly take the first in the line as a prime and strike out all multiples. the "n for n in ilist if n%p != 0" bit was supposed to represent striking out the multiples. Admittedly highly suboptimal though, definitely
– Paul Gardiner
Feb 18 '15 at 14:05
n for n in ilist if n%p != 0
tests each numbern
in a range for divisibility byp
; butrange(p*p, N, p)
generates the multiples directly, all by itself, without testing all these numbers.
– Will Ness
Feb 25 '15 at 4:06
@marisbest2 it is not. it counts fromn
toinfinity
, rather than from0
ton-1
– TemporalWolf
Nov 18 '16 at 23:46
|
show 1 more comment
I realise this isn't really answering the question of how to generate primes quickly, but perhaps some will find this alternative interesting: because python provides lazy evaluation via generators, eratosthenes' sieve can be implemented exactly as stated:
def intsfrom(n):
while True:
yield n
n += 1
def sieve(ilist):
p = next(ilist)
yield p
for q in sieve(n for n in ilist if n%p != 0):
yield q
try:
for p in sieve(intsfrom(2)):
print p,
print ''
except RuntimeError as e:
print e
The try block is there because the algorithm runs until it blows the stack and without the
try block the backtrace is displayed pushing the actual output you want to see off screen.
I realise this isn't really answering the question of how to generate primes quickly, but perhaps some will find this alternative interesting: because python provides lazy evaluation via generators, eratosthenes' sieve can be implemented exactly as stated:
def intsfrom(n):
while True:
yield n
n += 1
def sieve(ilist):
p = next(ilist)
yield p
for q in sieve(n for n in ilist if n%p != 0):
yield q
try:
for p in sieve(intsfrom(2)):
print p,
print ''
except RuntimeError as e:
print e
The try block is there because the algorithm runs until it blows the stack and without the
try block the backtrace is displayed pushing the actual output you want to see off screen.
edited Jul 20 '14 at 10:47
answered Jul 20 '14 at 10:38
Paul GardinerPaul Gardiner
33413
33413
3
no, it's not the sieve of Eratosthenes, but rather a sieve of trial division. Even that is very suboptimal, because it's not postponed: any candidate number need only be tested by primes not above its square root. Implementing this along the lines of the pseudocode at the bottom of the linked above answer (the latter one) will give your code immense speedup (even before you switch to the proper sieve) and/because it'll greatly minimize the stack usage - so you mightn't need yourtry
block after all.
– Will Ness
Jul 21 '14 at 14:11
... see also: more discussion about the "sqrt" issue and its effects, an actual Python code for a postponed trial division, and some related Scala. --- And kudos to you, if you came up with that code on your own! :)
– Will Ness
Jul 21 '14 at 14:15
Interesting, although I'm not yet understanding why what I put is different from the sieve of Eratosthenes. I thought it was described as placing all the intergers from 2 in a line, then repeadly take the first in the line as a prime and strike out all multiples. the "n for n in ilist if n%p != 0" bit was supposed to represent striking out the multiples. Admittedly highly suboptimal though, definitely
– Paul Gardiner
Feb 18 '15 at 14:05
n for n in ilist if n%p != 0
tests each numbern
in a range for divisibility byp
; butrange(p*p, N, p)
generates the multiples directly, all by itself, without testing all these numbers.
– Will Ness
Feb 25 '15 at 4:06
@marisbest2 it is not. it counts fromn
toinfinity
, rather than from0
ton-1
– TemporalWolf
Nov 18 '16 at 23:46
|
show 1 more comment
3
no, it's not the sieve of Eratosthenes, but rather a sieve of trial division. Even that is very suboptimal, because it's not postponed: any candidate number need only be tested by primes not above its square root. Implementing this along the lines of the pseudocode at the bottom of the linked above answer (the latter one) will give your code immense speedup (even before you switch to the proper sieve) and/because it'll greatly minimize the stack usage - so you mightn't need yourtry
block after all.
– Will Ness
Jul 21 '14 at 14:11
... see also: more discussion about the "sqrt" issue and its effects, an actual Python code for a postponed trial division, and some related Scala. --- And kudos to you, if you came up with that code on your own! :)
– Will Ness
Jul 21 '14 at 14:15
Interesting, although I'm not yet understanding why what I put is different from the sieve of Eratosthenes. I thought it was described as placing all the intergers from 2 in a line, then repeadly take the first in the line as a prime and strike out all multiples. the "n for n in ilist if n%p != 0" bit was supposed to represent striking out the multiples. Admittedly highly suboptimal though, definitely
– Paul Gardiner
Feb 18 '15 at 14:05
n for n in ilist if n%p != 0
tests each numbern
in a range for divisibility byp
; butrange(p*p, N, p)
generates the multiples directly, all by itself, without testing all these numbers.
– Will Ness
Feb 25 '15 at 4:06
@marisbest2 it is not. it counts fromn
toinfinity
, rather than from0
ton-1
– TemporalWolf
Nov 18 '16 at 23:46
3
3
no, it's not the sieve of Eratosthenes, but rather a sieve of trial division. Even that is very suboptimal, because it's not postponed: any candidate number need only be tested by primes not above its square root. Implementing this along the lines of the pseudocode at the bottom of the linked above answer (the latter one) will give your code immense speedup (even before you switch to the proper sieve) and/because it'll greatly minimize the stack usage - so you mightn't need your
try
block after all.– Will Ness
Jul 21 '14 at 14:11
no, it's not the sieve of Eratosthenes, but rather a sieve of trial division. Even that is very suboptimal, because it's not postponed: any candidate number need only be tested by primes not above its square root. Implementing this along the lines of the pseudocode at the bottom of the linked above answer (the latter one) will give your code immense speedup (even before you switch to the proper sieve) and/because it'll greatly minimize the stack usage - so you mightn't need your
try
block after all.– Will Ness
Jul 21 '14 at 14:11
... see also: more discussion about the "sqrt" issue and its effects, an actual Python code for a postponed trial division, and some related Scala. --- And kudos to you, if you came up with that code on your own! :)
– Will Ness
Jul 21 '14 at 14:15
... see also: more discussion about the "sqrt" issue and its effects, an actual Python code for a postponed trial division, and some related Scala. --- And kudos to you, if you came up with that code on your own! :)
– Will Ness
Jul 21 '14 at 14:15
Interesting, although I'm not yet understanding why what I put is different from the sieve of Eratosthenes. I thought it was described as placing all the intergers from 2 in a line, then repeadly take the first in the line as a prime and strike out all multiples. the "n for n in ilist if n%p != 0" bit was supposed to represent striking out the multiples. Admittedly highly suboptimal though, definitely
– Paul Gardiner
Feb 18 '15 at 14:05
Interesting, although I'm not yet understanding why what I put is different from the sieve of Eratosthenes. I thought it was described as placing all the intergers from 2 in a line, then repeadly take the first in the line as a prime and strike out all multiples. the "n for n in ilist if n%p != 0" bit was supposed to represent striking out the multiples. Admittedly highly suboptimal though, definitely
– Paul Gardiner
Feb 18 '15 at 14:05
n for n in ilist if n%p != 0
tests each number n
in a range for divisibility by p
; but range(p*p, N, p)
generates the multiples directly, all by itself, without testing all these numbers.– Will Ness
Feb 25 '15 at 4:06
n for n in ilist if n%p != 0
tests each number n
in a range for divisibility by p
; but range(p*p, N, p)
generates the multiples directly, all by itself, without testing all these numbers.– Will Ness
Feb 25 '15 at 4:06
@marisbest2 it is not. it counts from
n
to infinity
, rather than from 0
to n-1
– TemporalWolf
Nov 18 '16 at 23:46
@marisbest2 it is not. it counts from
n
to infinity
, rather than from 0
to n-1
– TemporalWolf
Nov 18 '16 at 23:46
|
show 1 more comment
By combining contributions from many enthusiasts (including Glenn Maynard and MrHIDEn from above comments), I came up with following piece of code in python 2:
def simpleSieve(sieveSize):
#creating Sieve.
sieve = [True] * (sieveSize+1)
# 0 and 1 are not considered prime.
sieve[0] = False
sieve[1] = False
for i in xrange(2,int(math.sqrt(sieveSize))+1):
if sieve[i] == False:
continue
for pointer in xrange(i**2, sieveSize+1, i):
sieve[pointer] = False
# Sieve is left with prime numbers == True
primes =
for i in xrange(sieveSize+1):
if sieve[i] == True:
primes.append(i)
return primes
sieveSize = input()
primes = simpleSieve(sieveSize)
Time taken for computation on my machine for different inputs in power of 10 is:
- 3 : 0.3 ms
- 4 : 2.4 ms
- 5 : 23 ms
- 6 : 0.26 s
- 7 : 3.1 s
- 8 : 33 s
the comparison with True or False are unneeded more so as they are already Boolean,
– Copperfield
Sep 4 '16 at 13:32
@Copperfield Thanks! It helped in increasing speed by 10-20%.
– Ajay
Sep 4 '16 at 20:04
Thissieve = [True] * (sieveSize+1)
is faster than my solution, butsieve[0]/[1]
andxrange(sieveSize+1)
at primes does not improve anything.xrange(2, sieveSize+1)
is good enouth. :). Also instead offor i in xrange(2,int(math.sqrt(sieveSize))+1):
we can just usefor i in xrange(2, int((sieveSize+1)**0.5):
Good code. :)
– MrHIDEn
Nov 28 '16 at 8:49
add a comment |
By combining contributions from many enthusiasts (including Glenn Maynard and MrHIDEn from above comments), I came up with following piece of code in python 2:
def simpleSieve(sieveSize):
#creating Sieve.
sieve = [True] * (sieveSize+1)
# 0 and 1 are not considered prime.
sieve[0] = False
sieve[1] = False
for i in xrange(2,int(math.sqrt(sieveSize))+1):
if sieve[i] == False:
continue
for pointer in xrange(i**2, sieveSize+1, i):
sieve[pointer] = False
# Sieve is left with prime numbers == True
primes =
for i in xrange(sieveSize+1):
if sieve[i] == True:
primes.append(i)
return primes
sieveSize = input()
primes = simpleSieve(sieveSize)
Time taken for computation on my machine for different inputs in power of 10 is:
- 3 : 0.3 ms
- 4 : 2.4 ms
- 5 : 23 ms
- 6 : 0.26 s
- 7 : 3.1 s
- 8 : 33 s
the comparison with True or False are unneeded more so as they are already Boolean,
– Copperfield
Sep 4 '16 at 13:32
@Copperfield Thanks! It helped in increasing speed by 10-20%.
– Ajay
Sep 4 '16 at 20:04
Thissieve = [True] * (sieveSize+1)
is faster than my solution, butsieve[0]/[1]
andxrange(sieveSize+1)
at primes does not improve anything.xrange(2, sieveSize+1)
is good enouth. :). Also instead offor i in xrange(2,int(math.sqrt(sieveSize))+1):
we can just usefor i in xrange(2, int((sieveSize+1)**0.5):
Good code. :)
– MrHIDEn
Nov 28 '16 at 8:49
add a comment |
By combining contributions from many enthusiasts (including Glenn Maynard and MrHIDEn from above comments), I came up with following piece of code in python 2:
def simpleSieve(sieveSize):
#creating Sieve.
sieve = [True] * (sieveSize+1)
# 0 and 1 are not considered prime.
sieve[0] = False
sieve[1] = False
for i in xrange(2,int(math.sqrt(sieveSize))+1):
if sieve[i] == False:
continue
for pointer in xrange(i**2, sieveSize+1, i):
sieve[pointer] = False
# Sieve is left with prime numbers == True
primes =
for i in xrange(sieveSize+1):
if sieve[i] == True:
primes.append(i)
return primes
sieveSize = input()
primes = simpleSieve(sieveSize)
Time taken for computation on my machine for different inputs in power of 10 is:
- 3 : 0.3 ms
- 4 : 2.4 ms
- 5 : 23 ms
- 6 : 0.26 s
- 7 : 3.1 s
- 8 : 33 s
By combining contributions from many enthusiasts (including Glenn Maynard and MrHIDEn from above comments), I came up with following piece of code in python 2:
def simpleSieve(sieveSize):
#creating Sieve.
sieve = [True] * (sieveSize+1)
# 0 and 1 are not considered prime.
sieve[0] = False
sieve[1] = False
for i in xrange(2,int(math.sqrt(sieveSize))+1):
if sieve[i] == False:
continue
for pointer in xrange(i**2, sieveSize+1, i):
sieve[pointer] = False
# Sieve is left with prime numbers == True
primes =
for i in xrange(sieveSize+1):
if sieve[i] == True:
primes.append(i)
return primes
sieveSize = input()
primes = simpleSieve(sieveSize)
Time taken for computation on my machine for different inputs in power of 10 is:
- 3 : 0.3 ms
- 4 : 2.4 ms
- 5 : 23 ms
- 6 : 0.26 s
- 7 : 3.1 s
- 8 : 33 s
edited Sep 4 '16 at 2:08
answered Sep 4 '16 at 2:03
AjayAjay
455
455
the comparison with True or False are unneeded more so as they are already Boolean,
– Copperfield
Sep 4 '16 at 13:32
@Copperfield Thanks! It helped in increasing speed by 10-20%.
– Ajay
Sep 4 '16 at 20:04
Thissieve = [True] * (sieveSize+1)
is faster than my solution, butsieve[0]/[1]
andxrange(sieveSize+1)
at primes does not improve anything.xrange(2, sieveSize+1)
is good enouth. :). Also instead offor i in xrange(2,int(math.sqrt(sieveSize))+1):
we can just usefor i in xrange(2, int((sieveSize+1)**0.5):
Good code. :)
– MrHIDEn
Nov 28 '16 at 8:49
add a comment |
the comparison with True or False are unneeded more so as they are already Boolean,
– Copperfield
Sep 4 '16 at 13:32
@Copperfield Thanks! It helped in increasing speed by 10-20%.
– Ajay
Sep 4 '16 at 20:04
Thissieve = [True] * (sieveSize+1)
is faster than my solution, butsieve[0]/[1]
andxrange(sieveSize+1)
at primes does not improve anything.xrange(2, sieveSize+1)
is good enouth. :). Also instead offor i in xrange(2,int(math.sqrt(sieveSize))+1):
we can just usefor i in xrange(2, int((sieveSize+1)**0.5):
Good code. :)
– MrHIDEn
Nov 28 '16 at 8:49
the comparison with True or False are unneeded more so as they are already Boolean,
– Copperfield
Sep 4 '16 at 13:32
the comparison with True or False are unneeded more so as they are already Boolean,
– Copperfield
Sep 4 '16 at 13:32
@Copperfield Thanks! It helped in increasing speed by 10-20%.
– Ajay
Sep 4 '16 at 20:04
@Copperfield Thanks! It helped in increasing speed by 10-20%.
– Ajay
Sep 4 '16 at 20:04
This
sieve = [True] * (sieveSize+1)
is faster than my solution, but sieve[0]/[1]
and xrange(sieveSize+1)
at primes does not improve anything. xrange(2, sieveSize+1)
is good enouth. :). Also instead of for i in xrange(2,int(math.sqrt(sieveSize))+1):
we can just use for i in xrange(2, int((sieveSize+1)**0.5):
Good code. :)– MrHIDEn
Nov 28 '16 at 8:49
This
sieve = [True] * (sieveSize+1)
is faster than my solution, but sieve[0]/[1]
and xrange(sieveSize+1)
at primes does not improve anything. xrange(2, sieveSize+1)
is good enouth. :). Also instead of for i in xrange(2,int(math.sqrt(sieveSize))+1):
we can just use for i in xrange(2, int((sieveSize+1)**0.5):
Good code. :)– MrHIDEn
Nov 28 '16 at 8:49
add a comment |
Much faster:
import time
def get_primes(n):
m = n+1
#numbers = [True for i in range(m)]
numbers = [True] * m #EDIT: faster
for i in range(2, int(n**0.5 + 1)):
if numbers[i]:
for j in range(i*i, m, i):
numbers[j] = False
primes =
for i in range(2, m):
if numbers[i]:
primes.append(i)
return primes
start = time.time()
primes = get_primes(10000)
print(time.time() - start)
print(get_primes(100))
add a comment |
Much faster:
import time
def get_primes(n):
m = n+1
#numbers = [True for i in range(m)]
numbers = [True] * m #EDIT: faster
for i in range(2, int(n**0.5 + 1)):
if numbers[i]:
for j in range(i*i, m, i):
numbers[j] = False
primes =
for i in range(2, m):
if numbers[i]:
primes.append(i)
return primes
start = time.time()
primes = get_primes(10000)
print(time.time() - start)
print(get_primes(100))
add a comment |
Much faster:
import time
def get_primes(n):
m = n+1
#numbers = [True for i in range(m)]
numbers = [True] * m #EDIT: faster
for i in range(2, int(n**0.5 + 1)):
if numbers[i]:
for j in range(i*i, m, i):
numbers[j] = False
primes =
for i in range(2, m):
if numbers[i]:
primes.append(i)
return primes
start = time.time()
primes = get_primes(10000)
print(time.time() - start)
print(get_primes(100))
Much faster:
import time
def get_primes(n):
m = n+1
#numbers = [True for i in range(m)]
numbers = [True] * m #EDIT: faster
for i in range(2, int(n**0.5 + 1)):
if numbers[i]:
for j in range(i*i, m, i):
numbers[j] = False
primes =
for i in range(2, m):
if numbers[i]:
primes.append(i)
return primes
start = time.time()
primes = get_primes(10000)
print(time.time() - start)
print(get_primes(100))
edited Jun 25 '18 at 11:32
answered Aug 14 '15 at 14:07
MrHIDEnMrHIDEn
6081019
6081019
add a comment |
add a comment |
A simple speed hack: when you define the variable "primes," set the step to 2 to skip all even numbers automatically, and set the starting point to 1.
Then you can further optimize by instead of for i in primes, use for i in primes[:round(len(primes) ** 0.5)]. That will dramatically increase performance. In addition, you can eliminate numbers ending with 5 to further increase speed.
add a comment |
A simple speed hack: when you define the variable "primes," set the step to 2 to skip all even numbers automatically, and set the starting point to 1.
Then you can further optimize by instead of for i in primes, use for i in primes[:round(len(primes) ** 0.5)]. That will dramatically increase performance. In addition, you can eliminate numbers ending with 5 to further increase speed.
add a comment |
A simple speed hack: when you define the variable "primes," set the step to 2 to skip all even numbers automatically, and set the starting point to 1.
Then you can further optimize by instead of for i in primes, use for i in primes[:round(len(primes) ** 0.5)]. That will dramatically increase performance. In addition, you can eliminate numbers ending with 5 to further increase speed.
A simple speed hack: when you define the variable "primes," set the step to 2 to skip all even numbers automatically, and set the starting point to 1.
Then you can further optimize by instead of for i in primes, use for i in primes[:round(len(primes) ** 0.5)]. That will dramatically increase performance. In addition, you can eliminate numbers ending with 5 to further increase speed.
answered Feb 1 '15 at 21:07
user3917838
add a comment |
add a comment |
My implementation:
import math
n = 100
marked = {}
for i in range(2, int(math.sqrt(n))):
if not marked.get(i):
for x in range(i * i, n, i):
marked[x] = True
for i in range(2, n):
if not marked.get(i):
print i
I just testet your code and I seedict
solution is 2 times slower thanlist
solution.
– MrHIDEn
Nov 28 '16 at 8:54
add a comment |
My implementation:
import math
n = 100
marked = {}
for i in range(2, int(math.sqrt(n))):
if not marked.get(i):
for x in range(i * i, n, i):
marked[x] = True
for i in range(2, n):
if not marked.get(i):
print i
I just testet your code and I seedict
solution is 2 times slower thanlist
solution.
– MrHIDEn
Nov 28 '16 at 8:54
add a comment |
My implementation:
import math
n = 100
marked = {}
for i in range(2, int(math.sqrt(n))):
if not marked.get(i):
for x in range(i * i, n, i):
marked[x] = True
for i in range(2, n):
if not marked.get(i):
print i
My implementation:
import math
n = 100
marked = {}
for i in range(2, int(math.sqrt(n))):
if not marked.get(i):
for x in range(i * i, n, i):
marked[x] = True
for i in range(2, n):
if not marked.get(i):
print i
answered May 4 '16 at 4:51
SilentDirgeSilentDirge
584716
584716
I just testet your code and I seedict
solution is 2 times slower thanlist
solution.
– MrHIDEn
Nov 28 '16 at 8:54
add a comment |
I just testet your code and I seedict
solution is 2 times slower thanlist
solution.
– MrHIDEn
Nov 28 '16 at 8:54
I just testet your code and I see
dict
solution is 2 times slower than list
solution.– MrHIDEn
Nov 28 '16 at 8:54
I just testet your code and I see
dict
solution is 2 times slower than list
solution.– MrHIDEn
Nov 28 '16 at 8:54
add a comment |
Here's a version that's a bit more memory-efficient (and: a proper sieve, not trial divisions). Basically, instead of keeping an array of all the numbers, and crossing out those that aren't prime, this keeps an array of counters - one for each prime it's discovered - and leap-frogging them ahead of the putative prime. That way, it uses storage proportional to the number of primes, not up to to the highest prime.
import itertools
def primes():
class counter:
def __init__ (this, n): this.n, this.current, this.isVirgin = n, n*n, True
# isVirgin means it's never been incremented
def advancePast (this, n): # return true if the counter advanced
if this.current > n:
if this.isVirgin: raise StopIteration # if this is virgin, then so will be all the subsequent counters. Don't need to iterate further.
return False
this.current += this.n # pre: this.current == n; post: this.current > n.
this.isVirgin = False # when it's gone, it's gone
return True
yield 1
multiples =
for n in itertools.count(2):
isPrime = True
for p in (m.advancePast(n) for m in multiples):
if p: isPrime = False
if isPrime:
yield n
multiples.append (counter (n))
You'll note that primes()
is a generator, so you can keep the results in a list or you can use them directly. Here's the first n
primes:
import itertools
for k in itertools.islice (primes(), n):
print (k)
And, for completeness, here's a timer to measure the performance:
import time
def timer ():
t, k = time.process_time(), 10
for p in primes():
if p>k:
print (time.process_time()-t, " to ", p, "n")
k *= 10
if k>100000: return
Just in case you're wondering, I also wrote primes()
as a simple iterator (using __iter__
and __next__
), and it ran at almost the same speed. Surprised me too!
interesting idea - it would improve performance if you store the prime counters in a min-heap though (inner loop would be O(log num_primes) instead of O(num_primes))
– anthonybell
Jul 25 '17 at 17:34
Why? Even if they were in a heap, we still have to account for every one.
– Jules May
Jul 26 '17 at 10:26
If you store each prime in the heap keyed by it's next value you would only have to look at primes whose next value is the current value n. the largest primes will sink to the bottom of the heap and would need to be evaluated much more rarely than the smaller primes.
– anthonybell
Jul 26 '17 at 19:30
add a comment |
Here's a version that's a bit more memory-efficient (and: a proper sieve, not trial divisions). Basically, instead of keeping an array of all the numbers, and crossing out those that aren't prime, this keeps an array of counters - one for each prime it's discovered - and leap-frogging them ahead of the putative prime. That way, it uses storage proportional to the number of primes, not up to to the highest prime.
import itertools
def primes():
class counter:
def __init__ (this, n): this.n, this.current, this.isVirgin = n, n*n, True
# isVirgin means it's never been incremented
def advancePast (this, n): # return true if the counter advanced
if this.current > n:
if this.isVirgin: raise StopIteration # if this is virgin, then so will be all the subsequent counters. Don't need to iterate further.
return False
this.current += this.n # pre: this.current == n; post: this.current > n.
this.isVirgin = False # when it's gone, it's gone
return True
yield 1
multiples =
for n in itertools.count(2):
isPrime = True
for p in (m.advancePast(n) for m in multiples):
if p: isPrime = False
if isPrime:
yield n
multiples.append (counter (n))
You'll note that primes()
is a generator, so you can keep the results in a list or you can use them directly. Here's the first n
primes:
import itertools
for k in itertools.islice (primes(), n):
print (k)
And, for completeness, here's a timer to measure the performance:
import time
def timer ():
t, k = time.process_time(), 10
for p in primes():
if p>k:
print (time.process_time()-t, " to ", p, "n")
k *= 10
if k>100000: return
Just in case you're wondering, I also wrote primes()
as a simple iterator (using __iter__
and __next__
), and it ran at almost the same speed. Surprised me too!
interesting idea - it would improve performance if you store the prime counters in a min-heap though (inner loop would be O(log num_primes) instead of O(num_primes))
– anthonybell
Jul 25 '17 at 17:34
Why? Even if they were in a heap, we still have to account for every one.
– Jules May
Jul 26 '17 at 10:26
If you store each prime in the heap keyed by it's next value you would only have to look at primes whose next value is the current value n. the largest primes will sink to the bottom of the heap and would need to be evaluated much more rarely than the smaller primes.
– anthonybell
Jul 26 '17 at 19:30
add a comment |
Here's a version that's a bit more memory-efficient (and: a proper sieve, not trial divisions). Basically, instead of keeping an array of all the numbers, and crossing out those that aren't prime, this keeps an array of counters - one for each prime it's discovered - and leap-frogging them ahead of the putative prime. That way, it uses storage proportional to the number of primes, not up to to the highest prime.
import itertools
def primes():
class counter:
def __init__ (this, n): this.n, this.current, this.isVirgin = n, n*n, True
# isVirgin means it's never been incremented
def advancePast (this, n): # return true if the counter advanced
if this.current > n:
if this.isVirgin: raise StopIteration # if this is virgin, then so will be all the subsequent counters. Don't need to iterate further.
return False
this.current += this.n # pre: this.current == n; post: this.current > n.
this.isVirgin = False # when it's gone, it's gone
return True
yield 1
multiples =
for n in itertools.count(2):
isPrime = True
for p in (m.advancePast(n) for m in multiples):
if p: isPrime = False
if isPrime:
yield n
multiples.append (counter (n))
You'll note that primes()
is a generator, so you can keep the results in a list or you can use them directly. Here's the first n
primes:
import itertools
for k in itertools.islice (primes(), n):
print (k)
And, for completeness, here's a timer to measure the performance:
import time
def timer ():
t, k = time.process_time(), 10
for p in primes():
if p>k:
print (time.process_time()-t, " to ", p, "n")
k *= 10
if k>100000: return
Just in case you're wondering, I also wrote primes()
as a simple iterator (using __iter__
and __next__
), and it ran at almost the same speed. Surprised me too!
Here's a version that's a bit more memory-efficient (and: a proper sieve, not trial divisions). Basically, instead of keeping an array of all the numbers, and crossing out those that aren't prime, this keeps an array of counters - one for each prime it's discovered - and leap-frogging them ahead of the putative prime. That way, it uses storage proportional to the number of primes, not up to to the highest prime.
import itertools
def primes():
class counter:
def __init__ (this, n): this.n, this.current, this.isVirgin = n, n*n, True
# isVirgin means it's never been incremented
def advancePast (this, n): # return true if the counter advanced
if this.current > n:
if this.isVirgin: raise StopIteration # if this is virgin, then so will be all the subsequent counters. Don't need to iterate further.
return False
this.current += this.n # pre: this.current == n; post: this.current > n.
this.isVirgin = False # when it's gone, it's gone
return True
yield 1
multiples =
for n in itertools.count(2):
isPrime = True
for p in (m.advancePast(n) for m in multiples):
if p: isPrime = False
if isPrime:
yield n
multiples.append (counter (n))
You'll note that primes()
is a generator, so you can keep the results in a list or you can use them directly. Here's the first n
primes:
import itertools
for k in itertools.islice (primes(), n):
print (k)
And, for completeness, here's a timer to measure the performance:
import time
def timer ():
t, k = time.process_time(), 10
for p in primes():
if p>k:
print (time.process_time()-t, " to ", p, "n")
k *= 10
if k>100000: return
Just in case you're wondering, I also wrote primes()
as a simple iterator (using __iter__
and __next__
), and it ran at almost the same speed. Surprised me too!
edited Aug 4 '17 at 13:14
answered Jan 5 '17 at 19:55
Jules MayJules May
4261715
4261715
interesting idea - it would improve performance if you store the prime counters in a min-heap though (inner loop would be O(log num_primes) instead of O(num_primes))
– anthonybell
Jul 25 '17 at 17:34
Why? Even if they were in a heap, we still have to account for every one.
– Jules May
Jul 26 '17 at 10:26
If you store each prime in the heap keyed by it's next value you would only have to look at primes whose next value is the current value n. the largest primes will sink to the bottom of the heap and would need to be evaluated much more rarely than the smaller primes.
– anthonybell
Jul 26 '17 at 19:30
add a comment |
interesting idea - it would improve performance if you store the prime counters in a min-heap though (inner loop would be O(log num_primes) instead of O(num_primes))
– anthonybell
Jul 25 '17 at 17:34
Why? Even if they were in a heap, we still have to account for every one.
– Jules May
Jul 26 '17 at 10:26
If you store each prime in the heap keyed by it's next value you would only have to look at primes whose next value is the current value n. the largest primes will sink to the bottom of the heap and would need to be evaluated much more rarely than the smaller primes.
– anthonybell
Jul 26 '17 at 19:30
interesting idea - it would improve performance if you store the prime counters in a min-heap though (inner loop would be O(log num_primes) instead of O(num_primes))
– anthonybell
Jul 25 '17 at 17:34
interesting idea - it would improve performance if you store the prime counters in a min-heap though (inner loop would be O(log num_primes) instead of O(num_primes))
– anthonybell
Jul 25 '17 at 17:34
Why? Even if they were in a heap, we still have to account for every one.
– Jules May
Jul 26 '17 at 10:26
Why? Even if they were in a heap, we still have to account for every one.
– Jules May
Jul 26 '17 at 10:26
If you store each prime in the heap keyed by it's next value you would only have to look at primes whose next value is the current value n. the largest primes will sink to the bottom of the heap and would need to be evaluated much more rarely than the smaller primes.
– anthonybell
Jul 26 '17 at 19:30
If you store each prime in the heap keyed by it's next value you would only have to look at primes whose next value is the current value n. the largest primes will sink to the bottom of the heap and would need to be evaluated much more rarely than the smaller primes.
– anthonybell
Jul 26 '17 at 19:30
add a comment |
I prefer NumPy because of speed.
import numpy as np
# Find all prime numbers using Sieve of Eratosthenes
def get_primes1(n):
m = int(np.sqrt(n))
is_prime = np.ones(n, dtype=bool)
is_prime[:2] = False # 0 and 1 are not primes
for i in range(2, m):
if is_prime[i] == False:
continue
is_prime[i*i::i] = False
return np.nonzero(is_prime)[0]
# Find all prime numbers using brute-force.
def isprime(n):
''' Check if integer n is a prime '''
n = abs(int(n)) # n is a positive integer
if n < 2: # 0 and 1 are not primes
return False
if n == 2: # 2 is the only even prime number
return True
if not n & 1: # all other even numbers are not primes
return False
# Range starts with 3 and only needs to go up the square root
# of n for all odd numbers
for x in range(3, int(n**0.5)+1, 2):
if n % x == 0:
return False
return True
# To apply a function to a numpy array, one have to vectorize the function
def get_primes2(n):
vectorized_isprime = np.vectorize(isprime)
a = np.arange(n)
return a[vectorized_isprime(a)]
Check the output:
n = 100
print(get_primes1(n))
print(get_primes2(n))
[ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
[ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
Compare the speed of Sieve of Eratosthenes and brute-force on Jupyter Notebook. Sieve of Eratosthenes in 539 times faster than brute-force for million elements.
%timeit get_primes1(1000000)
%timeit get_primes2(1000000)
4.79 ms ± 90.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.58 s ± 31.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
add a comment |
I prefer NumPy because of speed.
import numpy as np
# Find all prime numbers using Sieve of Eratosthenes
def get_primes1(n):
m = int(np.sqrt(n))
is_prime = np.ones(n, dtype=bool)
is_prime[:2] = False # 0 and 1 are not primes
for i in range(2, m):
if is_prime[i] == False:
continue
is_prime[i*i::i] = False
return np.nonzero(is_prime)[0]
# Find all prime numbers using brute-force.
def isprime(n):
''' Check if integer n is a prime '''
n = abs(int(n)) # n is a positive integer
if n < 2: # 0 and 1 are not primes
return False
if n == 2: # 2 is the only even prime number
return True
if not n & 1: # all other even numbers are not primes
return False
# Range starts with 3 and only needs to go up the square root
# of n for all odd numbers
for x in range(3, int(n**0.5)+1, 2):
if n % x == 0:
return False
return True
# To apply a function to a numpy array, one have to vectorize the function
def get_primes2(n):
vectorized_isprime = np.vectorize(isprime)
a = np.arange(n)
return a[vectorized_isprime(a)]
Check the output:
n = 100
print(get_primes1(n))
print(get_primes2(n))
[ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
[ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
Compare the speed of Sieve of Eratosthenes and brute-force on Jupyter Notebook. Sieve of Eratosthenes in 539 times faster than brute-force for million elements.
%timeit get_primes1(1000000)
%timeit get_primes2(1000000)
4.79 ms ± 90.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.58 s ± 31.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
add a comment |
I prefer NumPy because of speed.
import numpy as np
# Find all prime numbers using Sieve of Eratosthenes
def get_primes1(n):
m = int(np.sqrt(n))
is_prime = np.ones(n, dtype=bool)
is_prime[:2] = False # 0 and 1 are not primes
for i in range(2, m):
if is_prime[i] == False:
continue
is_prime[i*i::i] = False
return np.nonzero(is_prime)[0]
# Find all prime numbers using brute-force.
def isprime(n):
''' Check if integer n is a prime '''
n = abs(int(n)) # n is a positive integer
if n < 2: # 0 and 1 are not primes
return False
if n == 2: # 2 is the only even prime number
return True
if not n & 1: # all other even numbers are not primes
return False
# Range starts with 3 and only needs to go up the square root
# of n for all odd numbers
for x in range(3, int(n**0.5)+1, 2):
if n % x == 0:
return False
return True
# To apply a function to a numpy array, one have to vectorize the function
def get_primes2(n):
vectorized_isprime = np.vectorize(isprime)
a = np.arange(n)
return a[vectorized_isprime(a)]
Check the output:
n = 100
print(get_primes1(n))
print(get_primes2(n))
[ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
[ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
Compare the speed of Sieve of Eratosthenes and brute-force on Jupyter Notebook. Sieve of Eratosthenes in 539 times faster than brute-force for million elements.
%timeit get_primes1(1000000)
%timeit get_primes2(1000000)
4.79 ms ± 90.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.58 s ± 31.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
I prefer NumPy because of speed.
import numpy as np
# Find all prime numbers using Sieve of Eratosthenes
def get_primes1(n):
m = int(np.sqrt(n))
is_prime = np.ones(n, dtype=bool)
is_prime[:2] = False # 0 and 1 are not primes
for i in range(2, m):
if is_prime[i] == False:
continue
is_prime[i*i::i] = False
return np.nonzero(is_prime)[0]
# Find all prime numbers using brute-force.
def isprime(n):
''' Check if integer n is a prime '''
n = abs(int(n)) # n is a positive integer
if n < 2: # 0 and 1 are not primes
return False
if n == 2: # 2 is the only even prime number
return True
if not n & 1: # all other even numbers are not primes
return False
# Range starts with 3 and only needs to go up the square root
# of n for all odd numbers
for x in range(3, int(n**0.5)+1, 2):
if n % x == 0:
return False
return True
# To apply a function to a numpy array, one have to vectorize the function
def get_primes2(n):
vectorized_isprime = np.vectorize(isprime)
a = np.arange(n)
return a[vectorized_isprime(a)]
Check the output:
n = 100
print(get_primes1(n))
print(get_primes2(n))
[ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
[ 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
Compare the speed of Sieve of Eratosthenes and brute-force on Jupyter Notebook. Sieve of Eratosthenes in 539 times faster than brute-force for million elements.
%timeit get_primes1(1000000)
%timeit get_primes2(1000000)
4.79 ms ± 90.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.58 s ± 31.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
answered Sep 14 '17 at 10:18
foo barfoo bar
854618
854618
add a comment |
add a comment |
I figured it must be possible to simply use the empty list as the terminating condition for the loop and came up with this:
limit = 100
ints = list(range(2, limit)) # Will end up empty
while len(ints) > 0:
prime = ints[0]
print prime
ints.remove(prime)
i = 2
multiple = prime * i
while multiple <= limit:
if multiple in ints:
ints.remove(multiple)
i += 1
multiple = prime * i
add a comment |
I figured it must be possible to simply use the empty list as the terminating condition for the loop and came up with this:
limit = 100
ints = list(range(2, limit)) # Will end up empty
while len(ints) > 0:
prime = ints[0]
print prime
ints.remove(prime)
i = 2
multiple = prime * i
while multiple <= limit:
if multiple in ints:
ints.remove(multiple)
i += 1
multiple = prime * i
add a comment |
I figured it must be possible to simply use the empty list as the terminating condition for the loop and came up with this:
limit = 100
ints = list(range(2, limit)) # Will end up empty
while len(ints) > 0:
prime = ints[0]
print prime
ints.remove(prime)
i = 2
multiple = prime * i
while multiple <= limit:
if multiple in ints:
ints.remove(multiple)
i += 1
multiple = prime * i
I figured it must be possible to simply use the empty list as the terminating condition for the loop and came up with this:
limit = 100
ints = list(range(2, limit)) # Will end up empty
while len(ints) > 0:
prime = ints[0]
print prime
ints.remove(prime)
i = 2
multiple = prime * i
while multiple <= limit:
if multiple in ints:
ints.remove(multiple)
i += 1
multiple = prime * i
answered Mar 2 '18 at 7:24
Tom RussellTom Russell
431216
431216
add a comment |
add a comment |
import math
def sieve(n):
primes = [True]*n
primes[0] = False
primes[1] = False
for i in range(2,int(math.sqrt(n))+1):
j = i*i
while j < n:
primes[j] = False
j = j+i
return [x for x in range(n) if primes[x] == True]
add a comment |
import math
def sieve(n):
primes = [True]*n
primes[0] = False
primes[1] = False
for i in range(2,int(math.sqrt(n))+1):
j = i*i
while j < n:
primes[j] = False
j = j+i
return [x for x in range(n) if primes[x] == True]
add a comment |
import math
def sieve(n):
primes = [True]*n
primes[0] = False
primes[1] = False
for i in range(2,int(math.sqrt(n))+1):
j = i*i
while j < n:
primes[j] = False
j = j+i
return [x for x in range(n) if primes[x] == True]
import math
def sieve(n):
primes = [True]*n
primes[0] = False
primes[1] = False
for i in range(2,int(math.sqrt(n))+1):
j = i*i
while j < n:
primes[j] = False
j = j+i
return [x for x in range(n) if primes[x] == True]
answered Sep 26 '18 at 4:26
NestorghhNestorghh
1,51341729
1,51341729
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f3939660%2fsieve-of-eratosthenes-finding-primes-python%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
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
Required, but never shown
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
Required, but never shown
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
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
There's a similar question here stackoverflow.com/questions/2897297 that you might find useful.
– Scott Griffiths
Oct 15 '10 at 8:18
Check that answer.
– tzot
Oct 15 '10 at 19:57
stackoverflow.com/questions/2068372/…
– Robert William Hanks
Oct 18 '10 at 22:57
@Srikar: Rather than iterating upto limit, you can just iterate upto the square root of limit, since any composite number in your dictionary will have one factor less than the square root of limit.
– sayantankhan
Aug 17 '13 at 1:36
Using the
step
parameter torange
is brilliant.factors
is a misnomer and should bemultiples
.– Tom Russell
Feb 28 '18 at 23:50