python prime numbers Sieve of Eratosthenes

前端 未结 6 981
旧时难觅i
旧时难觅i 2020-12-28 11:15

Hi can anyone tell me how to implement Sieve of Eratosthenes within this code to make it fast? Help will be really appreciated if you can complete it with sieve. I am really

相关标签:
6条回答
  • 2020-12-28 11:43

    Here is a simple generator using only addition that does not pre-allocate memory. The sieve is only as large as the dictionary of primes and memory use grows only as needed.

    def pgen(maxnum): # Sieve of Eratosthenes generator
        pnext, ps = 2, {}
        while pnext <= maxnum:
            for p in ps:
                while ps[p] < pnext:
                    ps[p] += p
                if ps[p] == pnext:
                    break
            else:
                ps[pnext] = pnext
                yield pnext
            pnext += 1
    
    def is_prime(n):
        return n in pgen(n)
    
    >>> is_prime(117)
    >>> is_prime(117)
    False
    >>> 83 in pgen(83)
    True
    >>> list(pgen(100)) # List prime numbers less than or equal to 100
    [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]
    
    0 讨论(0)
  • 2020-12-28 11:49

    This is a simple solution with sets. Which is very fast in comparison with many of the list-algorithms. Computation with sets is much faster because of the hash tables. (What makes sets faster than lists in python?)

    Greetings

    ----------------------------------
    from math import *
    
    def sievePrimes(n):
    
        numbers = set()
        numbers2 = set()
        bound = round(sqrt(n))
    
        for a in range(2, n+1):
            numbers.add(a)
    
        for i in range(2, n):
            for b in range(1, bound):
                if (i*(b+1)) in numbers2:
                    continue
                numbers2.add(i*(b+1))
        numbers = numbers - numbers2
    
        print(sorted(numbers))
    

    Simple Solution

    0 讨论(0)
  • 2020-12-28 11:50

    Both the original poster and the other solution posted here make the same mistake; if you use the modulo operator, or division in any form, your algorithm is trial division, not the Sieve of Eratosthenes, and will be far slower, O(n^2) instead of O(n log log n). Here is a simple Sieve of Eratosthenes in Python:

    def primes(n): # sieve of eratosthenes
        ps, sieve = [], [True] * (n + 1)
        for p in range(2, n + 1):
            if sieve[p]:
               ps.append(p)
               for i in range(p * p, n + 1, p):
                   sieve[i] = False
        return ps
    

    That should find all the primes less than a million in less than a second. If you're interested in programming with prime numbers, I modestly recommend this essay at my blog.

    0 讨论(0)
  • 2020-12-28 11:52

    Here is a very fast generator with reduced memory usage.

    def pgen(maxnum): # Sieve of Eratosthenes generator
        yield 2
        np_f = {}
        for q in xrange(3, maxnum + 1, 2):
            f = np_f.pop(q, None)
            if f:
                while f != np_f.setdefault(q+f, f):
                    q += f
            else:
                yield q
                np = q*q
                if np < maxnum:  # does not add to dict beyond maxnum
                    np_f[np] = q+q
    
    def is_prime(n):
        return n in pgen(n)
    
    >>> is_prime(541)
    True
    >>> is_prime(539)
    False
    >>> 83 in pgen(100)
    True
    >>> list(pgen(100)) # List prime numbers less than or equal to 100
    [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]
    
    0 讨论(0)
  • 2020-12-28 12:03

    Fastest implementation I could think of

    def sieve(maxNum):
        yield 2
        D, q = {}, 3
        while q <= maxNum:
            p = D.pop(q, 0)
            if p:
                x = q + p
                while x in D: x += p
                D[x] = p
            else:
                yield q
                D[q*q] = 2*q
            q += 2
        raise StopIteration
    

    Source: http://code.activestate.com/recipes/117119-sieve-of-eratosthenes/#c4

    Replace this part

    import math
    def is_prime(n):
        if n == 2:
            return True
        if n%2 == 0 or n <= 1:
            return False
        sqr = int(math.sqrt(n)) + 1
        for divisor in range(3, sqr, 2):
            if n%divisor == 0:
                return False
        return True
    

    with

    primes = [prime for prime in sieve(10000000)]
    def is_prime(n):
        return n in primes
    

    Instead of 10000000 you can put whatever the maximum number till which you need prime numbers.

    0 讨论(0)
  • 2020-12-28 12:06

    An old trick for speeding sieves in Python is to use fancy ;-) list slice notation, like below. This uses Python 3. Changes needed for Python 2 are noted in comments:

    def sieve(n):
        "Return all primes <= n."
        np1 = n + 1
        s = list(range(np1)) # leave off `list()` in Python 2
        s[1] = 0
        sqrtn = int(round(n**0.5))
        for i in range(2, sqrtn + 1): # use `xrange()` in Python 2
            if s[i]:
                # next line:  use `xrange()` in Python 2
                s[i*i: np1: i] = [0] * len(range(i*i, np1, i))
        return filter(None, s)
    

    In Python 2 this returns a list; in Python 3 an iterator. Here under Python 3:

    >>> list(sieve(20))
    [2, 3, 5, 7, 11, 13, 17, 19]
    >>> len(list(sieve(1000000)))
    78498
    

    Those both run in an eyeblink. Given that, here's how to build an is_prime function:

    primes = set(sieve(the_max_integer_you_care_about))
    def is_prime(n):
        return n in primes
    

    It's the set() part that makes it fast. Of course the function is so simple you'd probably want to write:

    if n in primes:
    

    directly instead of messing with:

    if is_prime(n):
    
    0 讨论(0)
提交回复
热议问题