Sieve of Eratosthenes - Finding Primes Python












59















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)









share|improve this question




















  • 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 to range is brilliant. factors is a misnomer and should be multiples.

    – Tom Russell
    Feb 28 '18 at 23:50
















59















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)









share|improve this question




















  • 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 to range is brilliant. factors is a misnomer and should be multiples.

    – Tom Russell
    Feb 28 '18 at 23:50














59












59








59


37






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)









share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 the step parameter to range is brilliant. factors is a misnomer and should be multiples.

    – Tom Russell
    Feb 28 '18 at 23:50














  • 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 to range is brilliant. factors is a misnomer and should be multiples.

    – 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












12 Answers
12






active

oldest

votes


















94














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






share|improve this answer



















  • 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






  • 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 made 2*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 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





    +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



















11














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)





share|improve this answer



















  • 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



















6














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





share|improve this answer





















  • 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











  • Hey, would you mind explaining your code to me?

    – cyril
    Sep 27 '15 at 19:40



















1














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.






share|improve this answer





















  • 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













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



















1














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






share|improve this answer


























  • 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











  • 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



















1














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))





share|improve this answer

































    0














    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.






    share|improve this answer































      0














      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





      share|improve this answer
























      • I just testet your code and I see dict solution is 2 times slower than list solution.

        – MrHIDEn
        Nov 28 '16 at 8:54



















      0














      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!






      share|improve this answer


























      • 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



















      0














      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)





      share|improve this answer































        0














        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





        share|improve this answer































          0














          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]





          share|improve this answer























            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
            });


            }
            });














            draft saved

            draft discarded


















            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









            94














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






            share|improve this answer



















            • 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






            • 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 made 2*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 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





              +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
















            94














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






            share|improve this answer



















            • 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






            • 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 made 2*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 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





              +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














            94












            94








            94







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






            share|improve this answer













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







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Oct 15 '10 at 11:54









            Pi DelportPi Delport

            7,81123247




            7,81123247








            • 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






            • 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 made 2*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 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





              +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





              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





              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 made 2*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 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





              +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













            11














            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)





            share|improve this answer



















            • 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
















            11














            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)





            share|improve this answer



















            • 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














            11












            11








            11







            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)





            share|improve this answer













            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)






            share|improve this answer












            share|improve this answer



            share|improve this answer










            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














            • 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











            6














            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





            share|improve this answer





















            • 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











            • Hey, would you mind explaining your code to me?

              – cyril
              Sep 27 '15 at 19:40
















            6














            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





            share|improve this answer





















            • 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











            • Hey, would you mind explaining your code to me?

              – cyril
              Sep 27 '15 at 19:40














            6












            6








            6







            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





            share|improve this answer















            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






            share|improve this answer














            share|improve this answer



            share|improve this answer








            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: 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














            • 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











            • 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











            1














            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.






            share|improve this answer





















            • 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













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
















            1














            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.






            share|improve this answer





















            • 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













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














            1












            1








            1







            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.






            share|improve this answer















            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.







            share|improve this answer














            share|improve this answer



            share|improve this answer








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













            • 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













            • @marisbest2 it is not. it counts from n to infinity, rather than from 0 to n-1

              – TemporalWolf
              Nov 18 '16 at 23:46














            • 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













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








            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











            1














            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






            share|improve this answer


























            • 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











            • 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
















            1














            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






            share|improve this answer


























            • 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











            • 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














            1












            1








            1







            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






            share|improve this answer















            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







            share|improve this answer














            share|improve this answer



            share|improve this answer








            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











            • 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



















            • 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











            • 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

















            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











            1














            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))





            share|improve this answer






























              1














              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))





              share|improve this answer




























                1












                1








                1







                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))





                share|improve this answer















                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))






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jun 25 '18 at 11:32

























                answered Aug 14 '15 at 14:07









                MrHIDEnMrHIDEn

                6081019




                6081019























                    0














                    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.






                    share|improve this answer




























                      0














                      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.






                      share|improve this answer


























                        0












                        0








                        0







                        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.






                        share|improve this answer













                        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.







                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        answered Feb 1 '15 at 21:07







                        user3917838






























                            0














                            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





                            share|improve this answer
























                            • I just testet your code and I see dict solution is 2 times slower than list solution.

                              – MrHIDEn
                              Nov 28 '16 at 8:54
















                            0














                            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





                            share|improve this answer
























                            • I just testet your code and I see dict solution is 2 times slower than list solution.

                              – MrHIDEn
                              Nov 28 '16 at 8:54














                            0












                            0








                            0







                            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





                            share|improve this answer













                            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






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered May 4 '16 at 4:51









                            SilentDirgeSilentDirge

                            584716




                            584716













                            • 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

















                            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











                            0














                            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!






                            share|improve this answer


























                            • 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
















                            0














                            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!






                            share|improve this answer


























                            • 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














                            0












                            0








                            0







                            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!






                            share|improve this answer















                            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!







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            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



















                            • 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











                            0














                            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)





                            share|improve this answer




























                              0














                              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)





                              share|improve this answer


























                                0












                                0








                                0







                                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)





                                share|improve this answer













                                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)






                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                answered Sep 14 '17 at 10:18









                                foo barfoo bar

                                854618




                                854618























                                    0














                                    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





                                    share|improve this answer




























                                      0














                                      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





                                      share|improve this answer


























                                        0












                                        0








                                        0







                                        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





                                        share|improve this answer













                                        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






                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered Mar 2 '18 at 7:24









                                        Tom RussellTom Russell

                                        431216




                                        431216























                                            0














                                            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]





                                            share|improve this answer




























                                              0














                                              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]





                                              share|improve this answer


























                                                0












                                                0








                                                0







                                                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]





                                                share|improve this answer













                                                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]






                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered Sep 26 '18 at 4:26









                                                NestorghhNestorghh

                                                1,51341729




                                                1,51341729






























                                                    draft saved

                                                    draft discarded




















































                                                    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.




                                                    draft saved


                                                    draft discarded














                                                    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





















































                                                    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







                                                    Popular posts from this blog

                                                    Monofisismo

                                                    Angular Downloading a file using contenturl with Basic Authentication

                                                    Olmecas