N से नीचे के सभी प्राइम को सूचीबद्ध करने का सबसे तेज़ तरीका


357

यह सबसे अच्छा एल्गोरिथ्म है जो मैं आ सकता था।

def get_primes(n):
    numbers = set(range(n, 1, -1))
    primes = []
    while numbers:
        p = numbers.pop()
        primes.append(p)
        numbers.difference_update(set(range(p*2, n+1, p)))
    return primes

>>> timeit.Timer(stmt='get_primes.get_primes(1000000)', setup='import   get_primes').timeit(1)
1.1499958793645562

क्या इसे और भी तेज बनाया जा सकता है?

इस कोड में एक दोष है: चूंकि numbersएक अनियंत्रित सेट है, इसलिए कोई गारंटी नहीं है कि numbers.pop()सेट से सबसे कम संख्या को हटा दिया जाएगा। फिर भी, यह कुछ इनपुट नंबरों के लिए (कम से कम मेरे लिए) काम करता है:

>>> sum(get_primes(2000000))
142913828922L
#That's the correct sum of all numbers below 2 million
>>> 529 in get_primes(1000)
False
>>> 529 in get_primes(530)
True

यदि नंबर = सेट (रेंज (n, 2, -2)) जैसे नंबर घोषित किए गए हैं तो प्रश्न में कोड स्निपलेट बहुत तेज है। लेकिन sundaram3 को हरा नहीं सकते। सवाल के लिए धन्यवाद।
शेखर

3
यदि उत्तर में कार्यों के पायथन 3 संस्करण हो सकते हैं तो अच्छा होगा।
माइकल फौकैकिस

निश्चित रूप से ऐसा करने के लिए एक पुस्तकालय है, इसलिए हमें अपना स्वयं का रोल नहीं करना होगा> xkcd ने वादा किया कि पायथन उतना ही सरल है import antigravity। क्या ऐसा कुछ नहीं है require 'prime'; Prime.take(10)(रूबी)?
कर्नल पैनिक

2
@ColonelPanic जैसा कि ऐसा होता है मैंने Py3 के लिए github.com/jaredks/pyprimesieve को अपडेट किया और PyPi में जोड़ा। यह निश्चित रूप से इनसे तेज है, लेकिन परिमाण के आदेश नहीं हैं - सबसे अच्छा खसखस ​​संस्करणों की तुलना में ~ 5x तेज।
जारेड

3
@ColonelPanic: मुझे लगता है कि पुराने उत्तर संपादित करने पर ध्यान दें कि उनकी आयु उचित है, क्योंकि यह इसे अधिक उपयोगी संसाधन बनाता है। यदि "स्वीकार किया गया" उत्तर अब सबसे अच्छा नहीं है, तो वर्तमान सर्वोत्तम विधि पर लोगों को इंगित करने के लिए 2015 के अपडेट के साथ प्रश्न में एक नोट संपादित करें।
पीटर कॉर्डेस

जवाबों:


365

चेतावनी: timeit परिणाम अजगर या संस्करण के अंतर के कारण भिन्न हो सकते हैं।

नीचे एक स्क्रिप्ट है जो कई कार्यान्वयनों की तुलना करती है:

बहुत धन्यवाद करने के लिए स्टीफ़न मेरा ध्यान करने के लिए sieve_wheel_30 लाने के लिए। Primesfrom2to, primesfrom3to, rwh_primes, rwh_primes1, और rwh_primes2 के लिए श्रेय रॉबर्ट विलियम हैंक्स को जाता है ।

मानस के साथ परीक्षण किए गए सादे पायथन तरीकों में से, n = 1000000 के लिए, rwh_primes1 सबसे तेज परीक्षण किया गया था।

+---------------------+-------+
| Method              | ms    |
+---------------------+-------+
| rwh_primes1         | 43.0  |
| sieveOfAtkin        | 46.4  |
| rwh_primes          | 57.4  |
| sieve_wheel_30      | 63.0  |
| rwh_primes2         | 67.8  |    
| sieveOfEratosthenes | 147.0 |
| ambi_sieve_plain    | 152.0 |
| sundaram3           | 194.0 |
+---------------------+-------+

मानस के बिना , परीक्षण किए गए सादे पायथन तरीकों में से, n = 1000000 के लिए, rwh_primes2 सबसे तेज था।

+---------------------+-------+
| Method              | ms    |
+---------------------+-------+
| rwh_primes2         | 68.1  |
| rwh_primes1         | 93.7  |
| rwh_primes          | 94.6  |
| sieve_wheel_30      | 97.4  |
| sieveOfEratosthenes | 178.0 |
| ambi_sieve_plain    | 286.0 |
| sieveOfAtkin        | 314.0 |
| sundaram3           | 416.0 |
+---------------------+-------+

परीक्षण किए गए सभी तरीकों में से, n = 1000000 के लिए सुन्न की अनुमति , primesfrom2to सबसे तेज परीक्षण किया गया था।

+---------------------+-------+
| Method              | ms    |
+---------------------+-------+
| primesfrom2to       | 15.9  |
| primesfrom3to       | 18.4  |
| ambi_sieve          | 29.3  |
+---------------------+-------+

आदेश का उपयोग करके समय मापा गया:

python -mtimeit -s"import primes" "primes.{method}(1000000)"

साथ {method}विधि के नाम से प्रत्येक द्वारा बदल दिया।

primes.py:

#!/usr/bin/env python
import psyco; psyco.full()
from math import sqrt, ceil
import numpy as np

def rwh_primes(n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Returns  a list of primes < n """
    sieve = [True] * n
    for i in xrange(3,int(n**0.5)+1,2):
        if sieve[i]:
            sieve[i*i::2*i]=[False]*((n-i*i-1)/(2*i)+1)
    return [2] + [i for i in xrange(3,n,2) if sieve[i]]

def rwh_primes1(n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Returns  a list of primes < n """
    sieve = [True] * (n/2)
    for i in xrange(3,int(n**0.5)+1,2):
        if sieve[i/2]:
            sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1)
    return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]]

def rwh_primes2(n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Input n>=6, Returns a list of primes, 2 <= p < n """
    correction = (n%6>1)
    n = {0:n,1:n-1,2:n+4,3:n+3,4:n+2,5:n+1}[n%6]
    sieve = [True] * (n/3)
    sieve[0] = False
    for i in xrange(int(n**0.5)/3+1):
      if sieve[i]:
        k=3*i+1|1
        sieve[      ((k*k)/3)      ::2*k]=[False]*((n/6-(k*k)/6-1)/k+1)
        sieve[(k*k+4*k-2*k*(i&1))/3::2*k]=[False]*((n/6-(k*k+4*k-2*k*(i&1))/6-1)/k+1)
    return [2,3] + [3*i+1|1 for i in xrange(1,n/3-correction) if sieve[i]]

def sieve_wheel_30(N):
    # http://zerovolt.com/?p=88
    ''' Returns a list of primes <= N using wheel criterion 2*3*5 = 30

Copyright 2009 by zerovolt.com
This code is free for non-commercial purposes, in which case you can just leave this comment as a credit for my work.
If you need this code for commercial purposes, please contact me by sending an email to: info [at] zerovolt [dot] com.'''
    __smallp = ( 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, 101, 103, 107, 109, 113, 127, 131, 137, 139,
    149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
    229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311,
    313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401,
    409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491,
    499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599,
    601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683,
    691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797,
    809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887,
    907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997)

    wheel = (2, 3, 5)
    const = 30
    if N < 2:
        return []
    if N <= const:
        pos = 0
        while __smallp[pos] <= N:
            pos += 1
        return list(__smallp[:pos])
    # make the offsets list
    offsets = (7, 11, 13, 17, 19, 23, 29, 1)
    # prepare the list
    p = [2, 3, 5]
    dim = 2 + N // const
    tk1  = [True] * dim
    tk7  = [True] * dim
    tk11 = [True] * dim
    tk13 = [True] * dim
    tk17 = [True] * dim
    tk19 = [True] * dim
    tk23 = [True] * dim
    tk29 = [True] * dim
    tk1[0] = False
    # help dictionary d
    # d[a , b] = c  ==> if I want to find the smallest useful multiple of (30*pos)+a
    # on tkc, then I need the index given by the product of [(30*pos)+a][(30*pos)+b]
    # in general. If b < a, I need [(30*pos)+a][(30*(pos+1))+b]
    d = {}
    for x in offsets:
        for y in offsets:
            res = (x*y) % const
            if res in offsets:
                d[(x, res)] = y
    # another help dictionary: gives tkx calling tmptk[x]
    tmptk = {1:tk1, 7:tk7, 11:tk11, 13:tk13, 17:tk17, 19:tk19, 23:tk23, 29:tk29}
    pos, prime, lastadded, stop = 0, 0, 0, int(ceil(sqrt(N)))
    # inner functions definition
    def del_mult(tk, start, step):
        for k in xrange(start, len(tk), step):
            tk[k] = False
    # end of inner functions definition
    cpos = const * pos
    while prime < stop:
        # 30k + 7
        if tk7[pos]:
            prime = cpos + 7
            p.append(prime)
            lastadded = 7
            for off in offsets:
                tmp = d[(7, off)]
                start = (pos + prime) if off == 7 else (prime * (const * (pos + 1 if tmp < 7 else 0) + tmp) )//const
                del_mult(tmptk[off], start, prime)
        # 30k + 11
        if tk11[pos]:
            prime = cpos + 11
            p.append(prime)
            lastadded = 11
            for off in offsets:
                tmp = d[(11, off)]
                start = (pos + prime) if off == 11 else (prime * (const * (pos + 1 if tmp < 11 else 0) + tmp) )//const
                del_mult(tmptk[off], start, prime)
        # 30k + 13
        if tk13[pos]:
            prime = cpos + 13
            p.append(prime)
            lastadded = 13
            for off in offsets:
                tmp = d[(13, off)]
                start = (pos + prime) if off == 13 else (prime * (const * (pos + 1 if tmp < 13 else 0) + tmp) )//const
                del_mult(tmptk[off], start, prime)
        # 30k + 17
        if tk17[pos]:
            prime = cpos + 17
            p.append(prime)
            lastadded = 17
            for off in offsets:
                tmp = d[(17, off)]
                start = (pos + prime) if off == 17 else (prime * (const * (pos + 1 if tmp < 17 else 0) + tmp) )//const
                del_mult(tmptk[off], start, prime)
        # 30k + 19
        if tk19[pos]:
            prime = cpos + 19
            p.append(prime)
            lastadded = 19
            for off in offsets:
                tmp = d[(19, off)]
                start = (pos + prime) if off == 19 else (prime * (const * (pos + 1 if tmp < 19 else 0) + tmp) )//const
                del_mult(tmptk[off], start, prime)
        # 30k + 23
        if tk23[pos]:
            prime = cpos + 23
            p.append(prime)
            lastadded = 23
            for off in offsets:
                tmp = d[(23, off)]
                start = (pos + prime) if off == 23 else (prime * (const * (pos + 1 if tmp < 23 else 0) + tmp) )//const
                del_mult(tmptk[off], start, prime)
        # 30k + 29
        if tk29[pos]:
            prime = cpos + 29
            p.append(prime)
            lastadded = 29
            for off in offsets:
                tmp = d[(29, off)]
                start = (pos + prime) if off == 29 else (prime * (const * (pos + 1 if tmp < 29 else 0) + tmp) )//const
                del_mult(tmptk[off], start, prime)
        # now we go back to top tk1, so we need to increase pos by 1
        pos += 1
        cpos = const * pos
        # 30k + 1
        if tk1[pos]:
            prime = cpos + 1
            p.append(prime)
            lastadded = 1
            for off in offsets:
                tmp = d[(1, off)]
                start = (pos + prime) if off == 1 else (prime * (const * pos + tmp) )//const
                del_mult(tmptk[off], start, prime)
    # time to add remaining primes
    # if lastadded == 1, remove last element and start adding them from tk1
    # this way we don't need an "if" within the last while
    if lastadded == 1:
        p.pop()
    # now complete for every other possible prime
    while pos < len(tk1):
        cpos = const * pos
        if tk1[pos]: p.append(cpos + 1)
        if tk7[pos]: p.append(cpos + 7)
        if tk11[pos]: p.append(cpos + 11)
        if tk13[pos]: p.append(cpos + 13)
        if tk17[pos]: p.append(cpos + 17)
        if tk19[pos]: p.append(cpos + 19)
        if tk23[pos]: p.append(cpos + 23)
        if tk29[pos]: p.append(cpos + 29)
        pos += 1
    # remove exceeding if present
    pos = len(p) - 1
    while p[pos] > N:
        pos -= 1
    if pos < len(p) - 1:
        del p[pos+1:]
    # return p list
    return p

def sieveOfEratosthenes(n):
    """sieveOfEratosthenes(n): return the list of the primes < n."""
    # Code from: <dickinsm@gmail.com>, Nov 30 2006
    # http://groups.google.com/group/comp.lang.python/msg/f1f10ced88c68c2d
    if n <= 2:
        return []
    sieve = range(3, n, 2)
    top = len(sieve)
    for si in sieve:
        if si:
            bottom = (si*si - 3) // 2
            if bottom >= top:
                break
            sieve[bottom::si] = [0] * -((bottom - top) // si)
    return [2] + [el for el in sieve if el]

def sieveOfAtkin(end):
    """sieveOfAtkin(end): return a list of all the prime numbers <end
    using the Sieve of Atkin."""
    # Code by Steve Krenzel, <Sgk284@gmail.com>, improved
    # Code: https://web.archive.org/web/20080324064651/http://krenzel.info/?p=83
    # Info: http://en.wikipedia.org/wiki/Sieve_of_Atkin
    assert end > 0
    lng = ((end-1) // 2)
    sieve = [False] * (lng + 1)

    x_max, x2, xd = int(sqrt((end-1)/4.0)), 0, 4
    for xd in xrange(4, 8*x_max + 2, 8):
        x2 += xd
        y_max = int(sqrt(end-x2))
        n, n_diff = x2 + y_max*y_max, (y_max << 1) - 1
        if not (n & 1):
            n -= n_diff
            n_diff -= 2
        for d in xrange((n_diff - 1) << 1, -1, -8):
            m = n % 12
            if m == 1 or m == 5:
                m = n >> 1
                sieve[m] = not sieve[m]
            n -= d

    x_max, x2, xd = int(sqrt((end-1) / 3.0)), 0, 3
    for xd in xrange(3, 6 * x_max + 2, 6):
        x2 += xd
        y_max = int(sqrt(end-x2))
        n, n_diff = x2 + y_max*y_max, (y_max << 1) - 1
        if not(n & 1):
            n -= n_diff
            n_diff -= 2
        for d in xrange((n_diff - 1) << 1, -1, -8):
            if n % 12 == 7:
                m = n >> 1
                sieve[m] = not sieve[m]
            n -= d

    x_max, y_min, x2, xd = int((2 + sqrt(4-8*(1-end)))/4), -1, 0, 3
    for x in xrange(1, x_max + 1):
        x2 += xd
        xd += 6
        if x2 >= end: y_min = (((int(ceil(sqrt(x2 - end))) - 1) << 1) - 2) << 1
        n, n_diff = ((x*x + x) << 1) - 1, (((x-1) << 1) - 2) << 1
        for d in xrange(n_diff, y_min, -8):
            if n % 12 == 11:
                m = n >> 1
                sieve[m] = not sieve[m]
            n += d

    primes = [2, 3]
    if end <= 3:
        return primes[:max(0,end-2)]

    for n in xrange(5 >> 1, (int(sqrt(end))+1) >> 1):
        if sieve[n]:
            primes.append((n << 1) + 1)
            aux = (n << 1) + 1
            aux *= aux
            for k in xrange(aux, end, 2 * aux):
                sieve[k >> 1] = False

    s  = int(sqrt(end)) + 1
    if s  % 2 == 0:
        s += 1
    primes.extend([i for i in xrange(s, end, 2) if sieve[i >> 1]])

    return primes

def ambi_sieve_plain(n):
    s = range(3, n, 2)
    for m in xrange(3, int(n**0.5)+1, 2): 
        if s[(m-3)/2]: 
            for t in xrange((m*m-3)/2,(n>>1)-1,m):
                s[t]=0
    return [2]+[t for t in s if t>0]

def sundaram3(max_n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/2073279#2073279
    numbers = range(3, max_n+1, 2)
    half = (max_n)//2
    initial = 4

    for step in xrange(3, max_n+1, 2):
        for i in xrange(initial, half, step):
            numbers[i-1] = 0
        initial += 2*(step+1)

        if initial > half:
            return [2] + filter(None, numbers)

################################################################################
# Using Numpy:
def ambi_sieve(n):
    # http://tommih.blogspot.com/2009/04/fast-prime-number-generator.html
    s = np.arange(3, n, 2)
    for m in xrange(3, int(n ** 0.5)+1, 2): 
        if s[(m-3)/2]: 
            s[(m*m-3)/2::m]=0
    return np.r_[2, s[s>0]]

def primesfrom3to(n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Returns a array of primes, p < n """
    assert n>=2
    sieve = np.ones(n/2, dtype=np.bool)
    for i in xrange(3,int(n**0.5)+1,2):
        if sieve[i/2]:
            sieve[i*i/2::i] = False
    return np.r_[2, 2*np.nonzero(sieve)[0][1::]+1]    

def primesfrom2to(n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Input n>=6, Returns a array of primes, 2 <= p < n """
    sieve = np.ones(n/3 + (n%6==2), dtype=np.bool)
    sieve[0] = False
    for i in xrange(int(n**0.5)/3+1):
        if sieve[i]:
            k=3*i+1|1
            sieve[      ((k*k)/3)      ::2*k] = False
            sieve[(k*k+4*k-2*k*(i&1))/3::2*k] = False
    return np.r_[2,3,((3*np.nonzero(sieve)[0]+1)|1)]

if __name__=='__main__':
    import itertools
    import sys

    def test(f1,f2,num):
        print('Testing {f1} and {f2} return same results'.format(
            f1=f1.func_name,
            f2=f2.func_name))
        if not all([a==b for a,b in itertools.izip_longest(f1(num),f2(num))]):
            sys.exit("Error: %s(%s) != %s(%s)"%(f1.func_name,num,f2.func_name,num))

    n=1000000
    test(sieveOfAtkin,sieveOfEratosthenes,n)
    test(sieveOfAtkin,ambi_sieve,n)
    test(sieveOfAtkin,ambi_sieve_plain,n) 
    test(sieveOfAtkin,sundaram3,n)
    test(sieveOfAtkin,sieve_wheel_30,n)
    test(sieveOfAtkin,primesfrom3to,n)
    test(sieveOfAtkin,primesfrom2to,n)
    test(sieveOfAtkin,rwh_primes,n)
    test(sieveOfAtkin,rwh_primes1,n)         
    test(sieveOfAtkin,rwh_primes2,n)

स्क्रिप्ट परीक्षण चलाने से सभी कार्यान्वयन समान परिणाम देते हैं।


4
यदि आप गैर-शुद्ध-पायथन कोड में रुचि रखते हैं, तो आपको बाहर की जाँच करनी चाहिए gmpy- next_primeइसके mpzप्रकारों की विधि के माध्यम से, अपराधों के लिए बहुत अच्छा समर्थन है ।
एलेक्स मार्टेली

1
यदि आप pypy का उपयोग कर रहे हैं, तो ये मानदंड (मानस वाले) काफी बंद लग रहे हैं। आश्चर्यजनक रूप से पर्याप्त है, मुझे छलनी के साथ सबसे तेज होने के लिए sieveOfEratosthenes और ambi_sieve_plain मिला। यह वही है जो मैंने गैर-खस्ता लोगों के लिए पाया। gith.github.com/5bf466bb1ee9e5726a52
एहसान किआ

1
यदि कोई आश्चर्य करता है कि यहाँ मानस के बिना शुद्ध अजगर के लिए विकीबूक के पीजी Wik. PG के विरुद्ध किराया कैसे दिया जाता है और न ही पेपी: एन = १०००००० के लिए: पीजी :.:: ४.९ ३ प्रति लूप; rwh_primes1: 69 एमएस प्रति लूप; rwh_primes2: 57.1 एमएस प्रति लूप
विशाल जूल

8
क्या आप इसे PyPy के साथ अपडेट कर सकते हैं, अब मानस मर चुका है और PyPy ने इसे छोड़ दिया है?
no --zɐɹƆ

2
बहुत अच्छा होगा यदि ये कार्य और समय python3 के लिए अद्यतन किए जा सकते हैं।
सीएस 95 एन

134

तेज़ और अधिक मेमोरी-वार शुद्ध पायथन कोड:

def primes(n):
    """ Returns  a list of primes < n """
    sieve = [True] * n
    for i in range(3,int(n**0.5)+1,2):
        if sieve[i]:
            sieve[i*i::2*i]=[False]*((n-i*i-1)//(2*i)+1)
    return [2] + [i for i in range(3,n,2) if sieve[i]]

या आधी छलनी से शुरू करें

def primes1(n):
    """ Returns  a list of primes < n """
    sieve = [True] * (n//2)
    for i in range(3,int(n**0.5)+1,2):
        if sieve[i//2]:
            sieve[i*i//2::i] = [False] * ((n-i*i-1)//(2*i)+1)
    return [2] + [2*i+1 for i in range(1,n//2) if sieve[i]]

तेज़ और अधिक मेमोरी-वार संख्यात्मक कोड:

import numpy
def primesfrom3to(n):
    """ Returns a array of primes, 3 <= p < n """
    sieve = numpy.ones(n//2, dtype=numpy.bool)
    for i in range(3,int(n**0.5)+1,2):
        if sieve[i//2]:
            sieve[i*i//2::i] = False
    return 2*numpy.nonzero(sieve)[0][1::]+1

एक छलनी के तीसरे के साथ शुरू होने वाला तेज़ बदलाव:

import numpy
def primesfrom2to(n):
    """ Input n>=6, Returns a array of primes, 2 <= p < n """
    sieve = numpy.ones(n//3 + (n%6==2), dtype=numpy.bool)
    for i in range(1,int(n**0.5)//3+1):
        if sieve[i]:
            k=3*i+1|1
            sieve[       k*k//3     ::2*k] = False
            sieve[k*(k-2*(i&1)+4)//3::2*k] = False
    return numpy.r_[2,3,((3*numpy.nonzero(sieve)[0][1:]+1)|1)]

उपरोक्त कोड का ए (हार्ड-टू-कोड) शुद्ध-पायथन संस्करण होगा:

def primes2(n):
    """ Input n>=6, Returns a list of primes, 2 <= p < n """
    n, correction = n-n%6+6, 2-(n%6>1)
    sieve = [True] * (n//3)
    for i in range(1,int(n**0.5)//3+1):
      if sieve[i]:
        k=3*i+1|1
        sieve[      k*k//3      ::2*k] = [False] * ((n//6-k*k//6-1)//k+1)
        sieve[k*(k-2*(i&1)+4)//3::2*k] = [False] * ((n//6-k*(k-2*(i&1)+4)//6-1)//k+1)
    return [2,3] + [3*i+1|1 for i in range(1,n//3-correction) if sieve[i]]

दुर्भाग्य से शुद्ध-पायथन असाइनमेंट करने के सरल और तेज सुगम तरीके को नहीं अपनाता है, और len()लूप के अंदर कॉल [False]*len(sieve[((k*k)//3)::2*k])करना बहुत धीमा है। इसलिए मुझे इनपुट को सही करने के लिए सुधार करना पड़ा (और अधिक गणित से बचना) और कुछ चरम (और दर्दनाक) गणित-जादू करना।

व्यक्तिगत रूप से मुझे लगता है कि यह शर्म की बात है कि सुन्न (जो कि व्यापक रूप से उपयोग किया जाता है) पायथन मानक पुस्तकालय का हिस्सा नहीं है, और यह कि वाक्य रचना और गति में सुधार पायथन डेवलपर्स द्वारा पूरी तरह से अनदेखा किया गया लगता है।


2
नम्पी अब पायथन 3 के साथ संगत है। तथ्य यह है कि यह मानक पुस्तकालय में नहीं है अच्छा है, इस तरह से उनका अपना रिलीज चक्र हो सकता है।
एडम

सिर्फ एक सरणी में बाइनरी मान संग्रहीत करने के लिए मैं सुझाव है bitarray- के रूप में यहां इस्तेमाल किया (सरल प्रधानमंत्री चलनी के लिए; दौड़ में एक प्रतियोगी नहीं यहाँ!) stackoverflow.com/questions/31120986/...
हीरो नायक

primesfrom2to()विधि में कास्टिंग करते समय , विभाजन कोष्ठक के अंदर होना चाहिए?
225 पर 355durch113

3
अजगर 3 के साथ संगत एक शुद्ध अजगर संस्करण के लिए, इस लिंक का अनुसरण करें: stackoverflow.com/a/33356284/2482582
Moebius

FWIW, आपके 1 कोड ब्लॉक में संस्करण इस प्रश्न का विषय है । मुझे यह भी उल्लेख करना चाहिए कि मैंने यहां आपके कोड के पायथन 3 संस्करण का उपयोग किया है
PM 2Ring

42

यहां पाइथन कुकबुक से एक बहुत साफ नमूना है - उस URL पर प्रस्तावित सबसे तेज़ संस्करण है:

import itertools
def erat2( ):
    D = {  }
    yield 2
    for q in itertools.islice(itertools.count(3), 0, None, 2):
        p = D.pop(q, None)
        if p is None:
            D[q*q] = q
            yield q
        else:
            x = p + q
            while x in D or not (x&1):
                x += p
            D[x] = p

इतना देना होगा

def get_primes_erat(n):
  return list(itertools.takewhile(lambda p: p<n, erat2()))

इस कोड के साथ pri.py में शेल प्रॉम्प्ट (जैसा मैं करना चाहता हूं) को मापता हूं, मैं देखता हूं:

$ python2.5 -mtimeit -s'import pri' 'pri.get_primes(1000000)'
10 loops, best of 3: 1.69 sec per loop
$ python2.5 -mtimeit -s'import pri' 'pri.get_primes_erat(1000000)'
10 loops, best of 3: 673 msec per loop

तो ऐसा लगता है कि कुकबुक समाधान दो बार के रूप में तेजी से खत्म हो गया है।


1
@jbochi, आपका स्वागत है - लेकिन उस URL को देखें, जिसमें क्रेडिट भी शामिल है: इसने इस बिंदु पर कोड को सामूहिक रूप से परिष्कृत करने के लिए हमें दस ले लिया , जिसमें टिम पीटर और रेमंड हेटिंगर जैसे पायथन-प्रदर्शन लुमिनेरीज़ शामिल हैं (मैंने लिखा था) रेसिपी के अंतिम पाठ के बाद से मैंने मुद्रित कुकबुक को संपादित किया, लेकिन मेरे योगदान को कोड करने के मामले में दूसरों के साथ बराबरी पर था) - अंत में, यह वास्तव में सूक्ष्म और बारीक ट्यून्ड कोड है, और यह आश्चर्यजनक नहीं है! -)
एलेक्स मार्टेली

@ एलेक्स: यह जानते हुए कि आपका कोड "केवल" दो बार जितना तेजी से मेरा है, मुझे तब बहुत गर्व होता है। :) URL पढ़ने में भी बहुत दिलचस्प था। एक बार फिर धन्यवाद।
जौची

और इसे एक छोटे से बदलाव के साथ और भी तेज किया जा सकता है: देखें stackoverflow.com/questions/2211990/…
tzot 3

1
... और इसे अतिरिक्त ~ 1.2x-1.3x स्पीडअप के साथ तेजी से बनाया जा सकता है , O (n) से O (sqrt (n)) तक मेमोरी फ़ुटप्रिंट में भारी कमी और इसके अलावा जोड़ द्वारा समसामयिक समय जटिलता में सुधार जब तक उनका वर्ग इनपुट में नहीं दिखता तब तक तानाशाही के शिकार । इसका परीक्षण यहां करें
विल नेस

28

सुंदरम की छलनी का उपयोग , मुझे लगता है कि मैंने शुद्ध-पायथन के रिकॉर्ड को तोड़ दिया:

def sundaram3(max_n):
    numbers = range(3, max_n+1, 2)
    half = (max_n)//2
    initial = 4

    for step in xrange(3, max_n+1, 2):
        for i in xrange(initial, half, step):
            numbers[i-1] = 0
        initial += 2*(step+1)

        if initial > half:
            return [2] + filter(None, numbers)

Comparasion:

C:\USERS>python -m timeit -n10 -s "import get_primes" "get_primes.get_primes_erat(1000000)"
10 loops, best of 3: 710 msec per loop

C:\USERS>python -m timeit -n10 -s "import get_primes" "get_primes.daniel_sieve_2(1000000)"
10 loops, best of 3: 435 msec per loop

C:\USERS>python -m timeit -n10 -s "import get_primes" "get_primes.sundaram3(1000000)"
10 loops, best of 3: 327 msec per loop

1
मैंने फ़ंक्शन के शीर्ष पर "शून्य = 0" जोड़कर आपके फ़ंक्शन को 20% तक गति देने में कामयाब रहा और फिर अपने फ़िल्टर में लैंबडा को "शून्य .__ उप__" के साथ बदल दिया। नहीं दुनिया में सबसे सुंदर कोड, लेकिन थोड़ा तेज :)
truppo

1
@truppo: आपकी टिप्पणी के लिए धन्यवाद! मुझे बस एहसास हुआ कि Noneमूल कार्य के बजाय गुजर रहा है और यह उससे भी तेज हैzero.__sub__
जोबची

7
क्या आप जानते हैं कि यदि आप sundaram3(9)इसे पारित करते हैं तो यह वापस आ जाएगा [2, 3, 5, 7, 9]? यह कई लोगों के साथ ऐसा करने लगता है - शायद सभी - विषम संख्या (भले ही वे अभाज्य न हों)
wrhall

1
यह एक मुद्दा है: sundaram3 (7071) में 7071 शामिल हैं जबकि यह प्रमुख नहीं है
bigOther

18

एल्गोरिथ्म तेज है, लेकिन इसमें एक गंभीर दोष है:

>>> sorted(get_primes(530))
[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, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251,
257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 527, 529]
>>> 17*31
527
>>> 23*23
529

आप मानते हैं कि numbers.pop()सेट में सबसे छोटी संख्या वापस आ जाएगी, लेकिन इसकी गारंटी बिल्कुल नहीं है। सेट अनियंत्रित होते हैं और pop()एक मनमाना तत्व निकालते और लौटाते हैं , इसलिए इसका उपयोग शेष संख्याओं में से अगले प्राइम को चुनने के लिए नहीं किया जा सकता है।


17

के लिए सही मायने में पर्याप्त रूप से बड़े एन के साथ सबसे तेजी से समाधान एक डाउनलोड करने के लिए किया जाएगा अभाज्य संख्या की पूर्व गणना की सूची , एक टपल के रूप में संग्रहीत और की तरह कुछ कार्य करें:

for pos,i in enumerate(primes):
    if i > N:
        print primes[:pos]

यदि N > primes[-1] केवल तभी अधिक अपराधों की गणना करें और अपने कोड में नई सूची को बचाएं, तो अगली बार यह भी उतना ही तेज़ है।

हमेशा बॉक्स के बाहर सोचें।


9
निष्पक्ष होने के लिए, हालाँकि, आपको डाउनलोड करने, अनज़िप करने, और फ़ॉर्मेट करने के समय को गिनना होगा और तुलना करना होगा कि एल्गोरिथ्म का उपयोग करके प्राइम उत्पन्न करने के समय के साथ - इनमें से कोई भी एल्गोरिथम बाद में फ़ाइल के लिए परिणाम आसानी से लिख सकता है। उपयोग। मुझे लगता है कि उस मामले में, पर्याप्त स्मृति को वास्तव में 982,451,653 से कम सभी अपराधों की गणना करने के लिए दिया गया था, खस्ता समाधान अभी भी तेज होगा।
डेनियल जी

3
@ डैनियल सही। हालाँकि आपके पास जो भी है उसे स्टोर करें और जब भी जरूरत पड़े तब भी खड़े
रहें

@ डैनियल जीआई को लगता है कि डाउनलोड समय अप्रासंगिक है। क्या यह वास्तव में संख्या पैदा करने के बारे में नहीं है, इसलिए आप उस सूची को बनाने के लिए उपयोग किए गए एल्गोरिदम को ध्यान में रखना चाहेंगे जो आप डाउनलोड कर रहे हैं। और किसी भी समय जटिलता O (n) दिए गए फ़ाइल स्थानांतरण के एक बार की अनदेखी करेगी।
रॉस

पूछे जाने वाले प्रश्न UTM प्रधानमंत्री पेज के लिए पता चलता है छोटे अभाज्य संख्या की गणना के लिए तेजी से उन्हें एक डिस्क बंद पढ़ने से (सवाल क्या छोटे साधन है) है।
बैटमैन

12

यदि आप पहिए को फिर से नहीं लगाना चाहते हैं, तो आप प्रतीकात्मक गणित पुस्तकालय सहानुभूति स्थापित कर सकते हैं (हाँ यह पायथन 3 संगत है)

pip install sympy

और प्राइमरेंज फ़ंक्शन का उपयोग करें

from sympy import sieve
primes = list(sieve.primerange(1, 10**6))

8

यदि आप itertools को स्वीकार करते हैं लेकिन सुन्न नहीं है, तो यहां Python 3 के लिए rwh_primes2 का एक अनुकूलन है जो मेरी मशीन पर लगभग दो बार तेज चलता है। केवल पर्याप्त परिवर्तन बूलियन के लिए एक सूची के बजाय बायट्रे का उपयोग कर रहा है, और अंतिम सूची बनाने के लिए एक सूची समझ के बजाय सेक का उपयोग कर रहा है। (अगर मैं सक्षम होता तो मैं इसे मॉर्निंगिंग्स की तरह एक टिप्पणी के रूप में जोड़ता।)

import itertools
izip = itertools.zip_longest
chain = itertools.chain.from_iterable
compress = itertools.compress
def rwh_primes2_python3(n):
    """ Input n>=6, Returns a list of primes, 2 <= p < n """
    zero = bytearray([False])
    size = n//3 + (n % 6 == 2)
    sieve = bytearray([True]) * size
    sieve[0] = False
    for i in range(int(n**0.5)//3+1):
      if sieve[i]:
        k=3*i+1|1
        start = (k*k+4*k-2*k*(i&1))//3
        sieve[(k*k)//3::2*k]=zero*((size - (k*k)//3 - 1) // (2 * k) + 1)
        sieve[  start ::2*k]=zero*((size -   start  - 1) // (2 * k) + 1)
    ans = [2,3]
    poss = chain(izip(*[range(i, n, 6) for i in (1,5)]))
    ans.extend(compress(poss, sieve))
    return ans

तुलना:

>>> timeit.timeit('primes.rwh_primes2(10**6)', setup='import primes', number=1)
0.0652179726976101
>>> timeit.timeit('primes.rwh_primes2_python3(10**6)', setup='import primes', number=1)
0.03267321276325674

तथा

>>> timeit.timeit('primes.rwh_primes2(10**8)', setup='import primes', number=1)
6.394284538007014
>>> timeit.timeit('primes.rwh_primes2_python3(10**8)', setup='import primes', number=1)
3.833829450302801

बहुत अच्छा कार्यान्वयन। :)
कृष

7

यह अपने स्वयं के प्राइम फाइंडिंग कोड को लिखने के लिए शिक्षाप्रद है, लेकिन हाथ में तेज़ विश्वसनीय लाइब्रेरी होना भी उपयोगी है। मैंने C ++ लाइब्रेरी प्राइमिसेव के चारों ओर एक आवरण लिखा , नाम दिया primesieve-python

कोशिश करो pip install primesieve

import primesieve
primes = primesieve.generate_primes(10**8)

मैं तुलना की गति को देखने के लिए उत्सुक हूँ।


यह बिल्कुल ऐसा नहीं है जो ओपी ने आदेश दिया था लेकिन मैं यह देखने में असफल रहा कि नीचे की ओर क्यों। यह कुछ अन्य बाहरी मॉड्यूल के विपरीत 2.8 सेकेंड का समाधान है। मैंने उस स्रोत पर ध्यान दिया है जिसे यह पिरोया गया है, इस पर कोई भी परीक्षण मिला है कि यह कितना अच्छा है?
ljetibo

@ljetibo चियर्स। अड़चन को लगता है कि पायथन लिस्ट में C ++ वेक्टर की नकल की जा रही है, इस प्रकार यह count_primesफंक्शन उससे कहीं ज्यादा तेज हैgenerate_primes
कर्नल पैनिक

मेरे कंप्यूटर पर यह 1e8 तक आराम से प्राइम उत्पन्न कर सकता है (यह 1e9 के लिए MemoryError देता है), और 1e10 तक के प्राइम गिनता है। ऊपर @HappyLeapSecond 1e6 के लिए एल्गोरिदम की तुलना करता है
कर्नल पैनिक

7

यहाँ दो अद्यतन (शुद्ध पायथन 3.6) सबसे तेज़ कार्यों में से एक के संस्करण हैं,

from itertools import compress

def rwh_primes1v1(n):
    """ Returns  a list of primes < n for n > 2 """
    sieve = bytearray([True]) * (n//2)
    for i in range(3,int(n**0.5)+1,2):
        if sieve[i//2]:
            sieve[i*i//2::i] = bytearray((n-i*i-1)//(2*i)+1)
    return [2,*compress(range(3,n,2), sieve[1:])]

def rwh_primes1v2(n):
    """ Returns a list of primes < n for n > 2 """
    sieve = bytearray([True]) * (n//2+1)
    for i in range(1,int(n**0.5)//2+1):
        if sieve[i]:
            sieve[2*i*(i+1)::2*i+1] = bytearray((n//2-2*i*(i+1))//(2*i+1)+1)
    return [2,*compress(range(3,n,2), sieve[1:])]

1
पायथन 3 में मैंने इस फंक्शन stackoverflow.com/a/3035188/7799269 का इस्तेमाल किया, लेकिन / / को // और xrange को रेंज के साथ बदल दिया और वे इससे बहुत तेज लग रहे थे।
samerivertwice

4

इस धारणा पर मिलर-राबिन के प्राइमलिटी परीक्षण का एक निर्धारक कार्यान्वयन जो कि एन <9,080,191 है

import sys
import random

def miller_rabin_pass(a, n):
    d = n - 1
    s = 0
    while d % 2 == 0:
        d >>= 1
        s += 1

    a_to_power = pow(a, d, n)
    if a_to_power == 1:
        return True
    for i in xrange(s-1):
        if a_to_power == n - 1:
            return True
        a_to_power = (a_to_power * a_to_power) % n
    return a_to_power == n - 1


def miller_rabin(n):
    for a in [2, 3, 37, 73]:
      if not miller_rabin_pass(a, n):
        return False
    return True


n = int(sys.argv[1])
primes = [2]
for p in range(3,n,2):
  if miller_rabin(p):
    primes.append(p)
print len(primes)

विकिपीडिया पर लेख के अनुसार ( http://en.wikipedia.org/wiki/Miller-Rabin_primality_test ) N <9,080,191 का परीक्षण a = 2,3,37 के लिए, और 73 यह निर्णय करने के लिए पर्याप्त है कि N समग्र है या नहीं।

और मैंने यहां मिले मूल मिलर-राबिन के परीक्षण के संभाव्य कार्यान्वयन से स्रोत कोड को अनुकूलित किया: http://en.literateprograms.org/Miller-Rabin_primality_test_(Python)


1
मिलर-राबिन प्राइमलिटी टेस्ट के लिए धन्यवाद, लेकिन यह कोड वास्तव में धीमा है और सही परिणाम प्रदान नहीं कर रहा है। 37 प्राइम है और टेस्ट पास नहीं करता है।
जौची

मुझे लगता है कि 37 विशेष मामलों में से एक है, मेरा बुरा है। मैं निर्धारक संस्करण के बारे में आशान्वित था, हालांकि :)
रुगियरियो स्पीयरमैन

राबिन मिलर के लिए कोई विशेष मामला नहीं है।
गलत

2
आपने लेख को गलत बताया। यह 31 है, 37 नहीं। यही कारण है कि आपका कार्यान्वयन विफल हो जाता है।
लोगन

4

यदि आपका एन पर नियंत्रण है, तो सभी अपराधों को सूचीबद्ध करने का सबसे तेज़ तरीका उन्हें रोकना है। गंभीरता से। Precomputing एक तरह से अनुकूलन की अनदेखी है।


3
या उन्हें यहां से डाउनलोड करें primes.utm.edu/lists/small/millions , लेकिन विचार अजगर की सीमा का परीक्षण करना है और देखें कि क्या अनुकूलन से सुंदर कोड निकलता है।
जोबची

4

यहाँ वह कोड है जो मैं आमतौर पर पायथन में प्राइम उत्पन्न करने के लिए उपयोग करता हूँ:

$ python -mtimeit -s'import sieve' 'sieve.sieve(1000000)' 
10 loops, best of 3: 445 msec per loop
$ cat sieve.py
from math import sqrt

def sieve(size):
 prime=[True]*size
 rng=xrange
 limit=int(sqrt(size))

 for i in rng(3,limit+1,+2):
  if prime[i]:
   prime[i*i::+i]=[False]*len(prime[i*i::+i])

 return [2]+[i for i in rng(3,size,+2) if prime[i]]

if __name__=='__main__':
 print sieve(100)

यह यहाँ पोस्ट किए गए तेज़ समाधानों का मुकाबला नहीं कर सकता है, लेकिन कम से कम यह शुद्ध अजगर है।

इस प्रश्न को पोस्ट करने के लिए धन्यवाद। मैंने आज वास्तव में बहुत कुछ सीखा है।


3

सबसे तेज कोड के लिए, खस्ता समाधान सबसे अच्छा है। विशुद्ध रूप से अकादमिक कारणों से, हालांकि, मैं अपना शुद्ध पायथन संस्करण पोस्ट कर रहा हूं, जो कि ऊपर पोस्ट की गई रसोई की किताब के संस्करण की तुलना में थोड़ा कम 50% तेज है। चूंकि मैं पूरी सूची को मेमोरी में बनाता हूं, इसलिए आपको सब कुछ रखने के लिए पर्याप्त जगह की आवश्यकता होती है, लेकिन यह काफी अच्छा है।

def daniel_sieve_2(maxNumber):
    """
    Given a number, returns all numbers less than or equal to
    that number which are prime.
    """
    allNumbers = range(3, maxNumber+1, 2)
    for mIndex, number in enumerate(xrange(3, maxNumber+1, 2)):
        if allNumbers[mIndex] == 0:
            continue
        # now set all multiples to 0
        for index in xrange(mIndex+number, (maxNumber-3)/2+1, number):
            allNumbers[index] = 0
    return [2] + filter(lambda n: n!=0, allNumbers)

और परिणाम:

>>>mine = timeit.Timer("daniel_sieve_2(1000000)",
...                    "from sieves import daniel_sieve_2")
>>>prev = timeit.Timer("get_primes_erat(1000000)",
...                    "from sieves import get_primes_erat")
>>>print "Mine: {0:0.4f} ms".format(min(mine.repeat(3, 1))*1000)
Mine: 428.9446 ms
>>>print "Previous Best {0:0.4f} ms".format(min(prev.repeat(3, 1))*1000)
Previous Best 621.3581 ms

3

Numpy का उपयोग करके एक आधा छलनी का थोड़ा अलग कार्यान्वयन:

http://rebrained.com/?p=458

आयात गणित
आयात सुन्न
प्राइम 6 (अप) तक:
    अभाज्य संख्या = numpy.arange (3, तक + 1,2)
    isprime = numpy.ones ((तक -1) / 2, dtype = bool)
    अपराधों में कारक के लिए [: int (math.sqrt (तक))]:
        अगर isprime [(कारक -2) / 2]: isprime [(कारक * 3-2) / 2: (ऊपर -1) / 2: कारक] = 0
    वापसी numpy.insert (primes [isprime], 0,2)

क्या कोई इसकी तुलना अन्य समय के साथ कर सकता है? मेरी मशीन पर यह दूसरे Numpy आधा छलनी के साथ काफी तुलनीय लगता है।


upto=10**6: primesfrom2to()- 7 एमएस; prime6()- 12 एमएस ideone.com/oDg2Y
1

3

यह सब लिखित और परीक्षित है। तो पहिया को सुदृढ़ करने की कोई आवश्यकता नहीं है।

python -m timeit -r10 -s"from sympy import sieve" "primes = list(sieve.primerange(1, 10**6))"

हमें 12.2 मिसे को तोड़ने का एक रिकॉर्ड देता है !

10 loops, best of 10: 12.2 msec per loop

यदि यह पर्याप्त तेज़ नहीं है, तो आप PyPy आज़मा सकते हैं:

pypy -m timeit -r10 -s"from sympy import sieve" "primes = list(sieve.primerange(1, 10**6))"

जिसके परिणामस्वरूप:

10 loops, best of 10: 2.03 msec per loop

सबसे अच्छे समाधान के लिए 247 अप-वोटों के साथ उत्तर 15.9 एमएस सूचीबद्ध करता है। इसकी तुलना करें !!!


3

मैंने कुछ अनटुबों के कार्यों का परीक्षण किया , मैंने इसे लाखों संख्याओं के साथ गणना की

विजेता ऐसे कार्य हैं जो सुपीरियर लाइब्रेरी का उपयोग करते हैं,

नोट : यह भी एक मेमोरी उपयोग परीक्षण दिलचस्प होगा :)

अभिकलन समय परिणाम

नमूना कोड

मेरे गिथुब भंडार पर पूरा कोड

#!/usr/bin/env python

import lib
import timeit
import sys
import math
import datetime

import prettyplotlib as ppl
import numpy as np

import matplotlib.pyplot as plt
from prettyplotlib import brewer2mpl

primenumbers_gen = [
    'sieveOfEratosthenes',
    'ambi_sieve',
    'ambi_sieve_plain',
    'sundaram3',
    'sieve_wheel_30',
    'primesfrom3to',
    'primesfrom2to',
    'rwh_primes',
    'rwh_primes1',
    'rwh_primes2',
]

def human_format(num):
    # /programming/579310/formatting-long-numbers-as-strings-in-python?answertab=active#tab-top
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num /= 1000.0
    # add more suffixes if you need them
    return '%.2f%s' % (num, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])


if __name__=='__main__':

    # Vars
    n = 10000000 # number itereration generator
    nbcol = 5 # For decompose prime number generator
    nb_benchloop = 3 # Eliminate false positive value during the test (bench average time)
    datetimeformat = '%Y-%m-%d %H:%M:%S.%f'
    config = 'from __main__ import n; import lib'
    primenumbers_gen = {
        'sieveOfEratosthenes': {'color': 'b'},
        'ambi_sieve': {'color': 'b'},
        'ambi_sieve_plain': {'color': 'b'},
         'sundaram3': {'color': 'b'},
        'sieve_wheel_30': {'color': 'b'},
# # #        'primesfrom2to': {'color': 'b'},
        'primesfrom3to': {'color': 'b'},
        # 'rwh_primes': {'color': 'b'},
        # 'rwh_primes1': {'color': 'b'},
        'rwh_primes2': {'color': 'b'},
    }


    # Get n in command line
    if len(sys.argv)>1:
        n = int(sys.argv[1])

    step = int(math.ceil(n / float(nbcol)))
    nbs = np.array([i * step for i in range(1, int(nbcol) + 1)])
    set2 = brewer2mpl.get_map('Paired', 'qualitative', 12).mpl_colors

    print datetime.datetime.now().strftime(datetimeformat)
    print("Compute prime number to %(n)s" % locals())
    print("")

    results = dict()
    for pgen in primenumbers_gen:
        results[pgen] = dict()
        benchtimes = list()
        for n in nbs:
            t = timeit.Timer("lib.%(pgen)s(n)" % locals(), setup=config)
            execute_times = t.repeat(repeat=nb_benchloop,number=1)
            benchtime = np.mean(execute_times)
            benchtimes.append(benchtime)
        results[pgen] = {'benchtimes':np.array(benchtimes)}

fig, ax = plt.subplots(1)
plt.ylabel('Computation time (in second)')
plt.xlabel('Numbers computed')
i = 0
for pgen in primenumbers_gen:

    bench = results[pgen]['benchtimes']
    avgs = np.divide(bench,nbs)
    avg = np.average(bench, weights=nbs)

    # Compute linear regression
    A = np.vstack([nbs, np.ones(len(nbs))]).T
    a, b = np.linalg.lstsq(A, nbs*avgs)[0]

    # Plot
    i += 1
    #label="%(pgen)s" % locals()
    #ppl.plot(nbs, nbs*avgs, label=label, lw=1, linestyle='--', color=set2[i % 12])
    label="%(pgen)s avg" % locals()
    ppl.plot(nbs, a * nbs + b, label=label, lw=2, color=set2[i % 12])
print datetime.datetime.now().strftime(datetimeformat)

ppl.legend(ax, loc='upper left', ncol=4)

# Change x axis label
ax.get_xaxis().get_major_formatter().set_scientific(False)
fig.canvas.draw()
labels = [human_format(int(item.get_text())) for item in ax.get_xticklabels()]

ax.set_xticklabels(labels)
ax = plt.gca()

plt.show()

2
एल्गोरिथम प्रदर्शन की तुलना करने के लिए , लॉग-लॉग पैमाने पर साजिश करना बेहतर है ।
विल नेस 10

3

पायथन 3 के लिए

def rwh_primes2(n):
    correction = (n%6>1)
    n = {0:n,1:n-1,2:n+4,3:n+3,4:n+2,5:n+1}[n%6]
    sieve = [True] * (n//3)
    sieve[0] = False
    for i in range(int(n**0.5)//3+1):
      if sieve[i]:
        k=3*i+1|1
        sieve[      ((k*k)//3)      ::2*k]=[False]*((n//6-(k*k)//6-1)//k+1)
        sieve[(k*k+4*k-2*k*(i&1))//3::2*k]=[False]*((n//6-(k*k+4*k-2*k*(i&1))//6-1)//k+1)
    return [2,3] + [3*i+1|1 for i in range(1,n//3-correction) if sieve[i]]

3

शुद्ध पायथन में सबसे तेज चलनी :

from itertools import compress

def half_sieve(n):
    """
    Returns a list of prime numbers less than `n`.
    """
    if n <= 2:
        return []
    sieve = bytearray([True]) * (n // 2)
    for i in range(3, int(n ** 0.5) + 1, 2):
        if sieve[i // 2]:
            sieve[i * i // 2::i] = bytearray((n - i * i - 1) // (2 * i) + 1)
    primes = list(compress(range(1, n, 2), sieve))
    primes[0] = 2
    return primes

मैंने स्पीड और मेमोरी के लिए एसाव ऑफ एराटोस्थनीज को अनुकूलित किया ।

बेंचमार्क

from time import clock
import platform

def benchmark(iterations, limit):
    start = clock()
    for x in range(iterations):
        half_sieve(limit)
    end = clock() - start
    print(f'{end/iterations:.4f} seconds for primes < {limit}')

if __name__ == '__main__':
    print(platform.python_version())
    print(platform.platform())
    print(platform.processor())
    it = 10
    for pw in range(4, 9):
        benchmark(it, 10**pw)

उत्पादन

>>> 3.6.7
>>> Windows-10-10.0.17763-SP0
>>> Intel64 Family 6 Model 78 Stepping 3, GenuineIntel
>>> 0.0003 seconds for primes < 10000
>>> 0.0021 seconds for primes < 100000
>>> 0.0204 seconds for primes < 1000000
>>> 0.2389 seconds for primes < 10000000
>>> 2.6702 seconds for primes < 100000000

2

पहली बार अजगर का उपयोग करते हुए, इसलिए मेरे द्वारा उपयोग किए जाने वाले कुछ तरीके थोड़ा बोझिल लग सकते हैं। मैंने सीधे अपने सी ++ कोड को अजगर में बदल दिया और यही मेरे पास है (हालांकि अजगर में एक बालक थोड़ा धीमा होता है)

#!/usr/bin/env python
import time

def GetPrimes(n):

    Sieve = [1 for x in xrange(n)]

    Done = False
    w = 3

    while not Done:

        for q in xrange (3, n, 2):
            Prod = w*q
            if Prod < n:
                Sieve[Prod] = 0
            else:
                break

        if w > (n/2):
            Done = True
        w += 2

    return Sieve



start = time.clock()

d = 10000000
Primes = GetPrimes(d)

count = 1 #This is for 2

for x in xrange (3, d, 2):
    if Primes[x]:
        count+=1

elapsed = (time.clock() - start)
print "\nFound", count, "primes in", elapsed, "seconds!\n"

pythonw Primes.py

12.799119 सेकंड में 664579 अपराध पाए गए!

#!/usr/bin/env python
import time

def GetPrimes2(n):

    Sieve = [1 for x in xrange(n)]

    for q in xrange (3, n, 2):
        k = q
        for y in xrange(k*3, n, k*2):
            Sieve[y] = 0

    return Sieve



start = time.clock()

d = 10000000
Primes = GetPrimes2(d)

count = 1 #This is for 2

for x in xrange (3, d, 2):
    if Primes[x]:
        count+=1

elapsed = (time.clock() - start)
print "\nFound", count, "primes in", elapsed, "seconds!\n"

pythonw Primes2.py

10.230172 सेकंड में 664579 अपराध पाए गए!

#!/usr/bin/env python
import time

def GetPrimes3(n):

    Sieve = [1 for x in xrange(n)]

    for q in xrange (3, n, 2):
        k = q
        for y in xrange(k*k, n, k << 1):
            Sieve[y] = 0

    return Sieve



start = time.clock()

d = 10000000
Primes = GetPrimes3(d)

count = 1 #This is for 2

for x in xrange (3, d, 2):
    if Primes[x]:
        count+=1

elapsed = (time.clock() - start)
print "\nFound", count, "primes in", elapsed, "seconds!\n"

python Primes2.py

7.113776 सेकंड में 664579 प्राइम मिले!


2

मुझे पता है कि प्रतियोगिता कुछ वर्षों से बंद है। ...

फिर भी, यह एक शुद्ध अजगर प्राइम छलनी के लिए मेरा सुझाव है, 2 से 3 और 5 के गुणक को छोड़ने के आधार पर, आगे की प्रक्रिया को संसाधित करते समय उपयुक्त चरणों का उपयोग करके। बहरहाल, यह वास्तव में N <10 ^ 9 के लिए @Robert विलियम हैंक्स से बेहतर समाधान rwh_primes2 और rwh_primes1 की तुलना में धीमी है। 1.5 * 10 ^ 8 से ऊपर ctypes.c_ushort चलनी सरणी का उपयोग करके यह किसी तरह मेमोरी लिमिट के अनुकूल है।

10 ^ 6

$ python -mtimeit -s "आयात PrimeSieveSpeedComp" "PrimeSieveSpeedComp.primeSieveSeq (1000000)" 10 लूप, 3 का सर्वश्रेष्ठ: 46.7 मिसे प्रति लूप

तुलना करने के लिए: $ python -mtimeit -s "import PrimeSieveSpeedComp" "PrimeSieveSpeedComp.rwh_primes1 (1000000)" 10 लूप्स, सबसे अच्छा 3: 43.2 msec लूप की तुलना करने के लिए: $ python -m timeit -s "import PrimeSieveSpeedCompp" प्राइम टाइम " (1000000) "10 छोरों, 3 का सर्वश्रेष्ठ: 34.5 मिसे प्रति लूप

10 ^ 7

$ python -mtimeit -s "आयात PrimeSieveSpeedComp" "PrimeSieveSpeedComp.primeSieveSeq (10000000)" 10 लूप, सबसे अच्छा 3: 530 मिसे प्रति लूप

तुलना करने के लिए: $ python -mtimeit -s "import PrimeSieveSpeedComp" "PrimeSieveSpeedComp.rwh_primes1 (10000000)" 10 लूप्स, सबसे अच्छा 3: 494 मिसेक लूप की तुलना करने के लिए: $ python -m timeit -s "import PrimeSieveSpeedCompp" प्राइम टाइम "।" (१०००००००) "१० लूप, सर्वश्रेष्ठ ३: ३ec५ मिसेक प्रति लूप

10 ^ 8

$ python -mtimeit -s "आयात PrimeSieveSpeedComp" "PrimeSieveSpeedComp.primeSieveSeq (100000000)" 10 छोरों, 3 का सर्वश्रेष्ठ: 5.55 प्रति लूप सेकंड

तुलना करने के लिए: $ python -mtimeit -s "import PrimeSieveSpeedComp" "PrimeSieveSpeedComp.rwh_primes1 (100000000)" 10 लूप्स, सबसे अच्छा 3: 5.33 सेकंड लूप की तुलना करने के लिए: $ python -m timeit -s "import PrimeSieveSpeedCompp" प्राइम टाइम " (100000000) "10 लूप्स, सर्वश्रेष्ठ 3: 3.95 सेकंड प्रति लूप

10 ^ 9

$ python -mtimeit -s "आयात PrimeSieveSpeedComp" "PrimeSieveSpeedComp.primeSieveSeq (1000000000)" 10 लूप, 3 का सर्वश्रेष्ठ: 61.2 प्रति लूप सेकंड

तुलना करने के लिए: $ python -mtimeit -n 3 -s "import PrimeSieveSpeedComp" "PrimeSieveSpeedComp.rwh_primes1 (1000000000)" 3 लूप, सबसे अच्छा 3: 97.8 सेकंड प्रति लूप

तुलना करने के लिए: $ python -m timeit -s "import PrimeSieveSpeedComp" "PrimeSieveSpeedComp.rwh_primes2 (1000000000)" 10 छोरों, 3 का सर्वश्रेष्ठ: 41.9 प्रति सेकेंड

इस परीक्षण की समीक्षा करने के लिए आप ubuntus PrimeSieveSpeedComp में नीचे दिए गए कोड को कॉपी कर सकते हैं।

def primeSieveSeq(MAX_Int):
    if MAX_Int > 5*10**8:
        import ctypes
        int16Array = ctypes.c_ushort * (MAX_Int >> 1)
        sieve = int16Array()
        #print 'uses ctypes "unsigned short int Array"'
    else:
        sieve = (MAX_Int >> 1) * [False]
        #print 'uses python list() of long long int'
    if MAX_Int < 10**8:
        sieve[4::3] = [True]*((MAX_Int - 8)/6+1)
        sieve[12::5] = [True]*((MAX_Int - 24)/10+1)
    r = [2, 3, 5]
    n = 0
    for i in xrange(int(MAX_Int**0.5)/30+1):
        n += 3
        if not sieve[n]:
            n2 = (n << 1) + 1
            r.append(n2)
            n2q = (n2**2) >> 1
            sieve[n2q::n2] = [True]*(((MAX_Int >> 1) - n2q - 1) / n2 + 1)
        n += 2
        if not sieve[n]:
            n2 = (n << 1) + 1
            r.append(n2)
            n2q = (n2**2) >> 1
            sieve[n2q::n2] = [True]*(((MAX_Int >> 1) - n2q - 1) / n2 + 1)
        n += 1
        if not sieve[n]:
            n2 = (n << 1) + 1
            r.append(n2)
            n2q = (n2**2) >> 1
            sieve[n2q::n2] = [True]*(((MAX_Int >> 1) - n2q - 1) / n2 + 1)
        n += 2
        if not sieve[n]:
            n2 = (n << 1) + 1
            r.append(n2)
            n2q = (n2**2) >> 1
            sieve[n2q::n2] = [True]*(((MAX_Int >> 1) - n2q - 1) / n2 + 1)
        n += 1
        if not sieve[n]:
            n2 = (n << 1) + 1
            r.append(n2)
            n2q = (n2**2) >> 1
            sieve[n2q::n2] = [True]*(((MAX_Int >> 1) - n2q - 1) / n2 + 1)
        n += 2
        if not sieve[n]:
            n2 = (n << 1) + 1
            r.append(n2)
            n2q = (n2**2) >> 1
            sieve[n2q::n2] = [True]*(((MAX_Int >> 1) - n2q - 1) / n2 + 1)
        n += 3
        if not sieve[n]:
            n2 = (n << 1) + 1
            r.append(n2)
            n2q = (n2**2) >> 1
            sieve[n2q::n2] = [True]*(((MAX_Int >> 1) - n2q - 1) / n2 + 1)
        n += 1
        if not sieve[n]:
            n2 = (n << 1) + 1
            r.append(n2)
            n2q = (n2**2) >> 1
            sieve[n2q::n2] = [True]*(((MAX_Int >> 1) - n2q - 1) / n2 + 1)
    if MAX_Int < 10**8:
        return [2, 3, 5]+[(p << 1) + 1 for p in [n for n in xrange(3, MAX_Int >> 1) if not sieve[n]]]
    n = n >> 1
    try:
        for i in xrange((MAX_Int-2*n)/30 + 1):
            n += 3
            if not sieve[n]:
                r.append((n << 1) + 1)
            n += 2
            if not sieve[n]:
                r.append((n << 1) + 1)
            n += 1
            if not sieve[n]:
                r.append((n << 1) + 1)
            n += 2
            if not sieve[n]:
                r.append((n << 1) + 1)
            n += 1
            if not sieve[n]:
                r.append((n << 1) + 1)
            n += 2
            if not sieve[n]:
                r.append((n << 1) + 1)
            n += 3
            if not sieve[n]:
                r.append((n << 1) + 1)
            n += 1
            if not sieve[n]:
                r.append((n << 1) + 1)
    except:
        pass
    return r

अपने परीक्षा परिणामों की कल्पना करने के लिए, उन्हें लॉग-लॉग स्केल पर प्लॉट करें, विकास के अनुभवजन्य आदेशों को देखने और तुलना करने के लिए ।
विल नेस

@ इनपुट के लिए धन्यवाद, अगली बार जब मुझे इस तरह की तुलना की आवश्यकता होगी, तो मैं इसे ध्यान में
रखूंगा

1

यहाँ दोनों अच्छी जटिलता (लंबाई n की एक सरणी को छांटने से कम) और वैश्वीकरण दोनों के साथ चलनी Eratosthenes का एक खस्ता संस्करण है। एक लाख से नीचे सभी अपराधों को खोजने के लिए 46 माइक्रोसॉन के साथ पैकेज के रूप में बस के रूप में उपवास के रूप में @unutbu बार की तुलना में।

import numpy as np 
def generate_primes(n):
    is_prime = np.ones(n+1,dtype=bool)
    is_prime[0:2] = False
    for i in range(int(n**0.5)+1):
        if is_prime[i]:
            is_prime[i**2::i]=False
    return np.where(is_prime)[0]

समय:

import time    
for i in range(2,10):
    timer =time.time()
    generate_primes(10**i)
    print('n = 10^',i,' time =', round(time.time()-timer,6))

>> n = 10^ 2  time = 5.6e-05
>> n = 10^ 3  time = 6.4e-05
>> n = 10^ 4  time = 0.000114
>> n = 10^ 5  time = 0.000593
>> n = 10^ 6  time = 0.00467
>> n = 10^ 7  time = 0.177758
>> n = 10^ 8  time = 1.701312
>> n = 10^ 9  time = 19.322478

1

मैंने पायथन 3 के लिए बहुत से कोड अपडेट किए हैं और इसे परफ्लोट (मेरा एक प्रोजेक्ट) पर फेंक दिया है, यह देखने के लिए कि वास्तव में सबसे तेज क्या है। पता चला कि, बड़े के लिए n, primesfrom{2,3}toकेक ले लो:

यहां छवि विवरण दर्ज करें


प्लॉट को फिर से तैयार करने के लिए कोड:

import perfplot
from math import sqrt, ceil
import numpy as np
import sympy


def rwh_primes(n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Returns  a list of primes < n """
    sieve = [True] * n
    for i in range(3, int(n ** 0.5) + 1, 2):
        if sieve[i]:
            sieve[i * i::2 * i] = [False] * ((n - i * i - 1) // (2 * i) + 1)
    return [2] + [i for i in range(3, n, 2) if sieve[i]]


def rwh_primes1(n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Returns  a list of primes < n """
    sieve = [True] * (n // 2)
    for i in range(3, int(n ** 0.5) + 1, 2):
        if sieve[i // 2]:
            sieve[i * i // 2::i] = [False] * ((n - i * i - 1) // (2 * i) + 1)
    return [2] + [2 * i + 1 for i in range(1, n // 2) if sieve[i]]


def rwh_primes2(n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """Input n>=6, Returns a list of primes, 2 <= p < n"""
    assert n >= 6
    correction = n % 6 > 1
    n = {0: n, 1: n - 1, 2: n + 4, 3: n + 3, 4: n + 2, 5: n + 1}[n % 6]
    sieve = [True] * (n // 3)
    sieve[0] = False
    for i in range(int(n ** 0.5) // 3 + 1):
        if sieve[i]:
            k = 3 * i + 1 | 1
            sieve[((k * k) // 3)::2 * k] = [False] * (
                (n // 6 - (k * k) // 6 - 1) // k + 1
            )
            sieve[(k * k + 4 * k - 2 * k * (i & 1)) // 3::2 * k] = [False] * (
                (n // 6 - (k * k + 4 * k - 2 * k * (i & 1)) // 6 - 1) // k + 1
            )
    return [2, 3] + [3 * i + 1 | 1 for i in range(1, n // 3 - correction) if sieve[i]]


def sieve_wheel_30(N):
    # http://zerovolt.com/?p=88
    """ Returns a list of primes <= N using wheel criterion 2*3*5 = 30

Copyright 2009 by zerovolt.com
This code is free for non-commercial purposes, in which case you can just leave this comment as a credit for my work.
If you need this code for commercial purposes, please contact me by sending an email to: info [at] zerovolt [dot] com."""
    __smallp = (
        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,
        101,
        103,
        107,
        109,
        113,
        127,
        131,
        137,
        139,
        149,
        151,
        157,
        163,
        167,
        173,
        179,
        181,
        191,
        193,
        197,
        199,
        211,
        223,
        227,
        229,
        233,
        239,
        241,
        251,
        257,
        263,
        269,
        271,
        277,
        281,
        283,
        293,
        307,
        311,
        313,
        317,
        331,
        337,
        347,
        349,
        353,
        359,
        367,
        373,
        379,
        383,
        389,
        397,
        401,
        409,
        419,
        421,
        431,
        433,
        439,
        443,
        449,
        457,
        461,
        463,
        467,
        479,
        487,
        491,
        499,
        503,
        509,
        521,
        523,
        541,
        547,
        557,
        563,
        569,
        571,
        577,
        587,
        593,
        599,
        601,
        607,
        613,
        617,
        619,
        631,
        641,
        643,
        647,
        653,
        659,
        661,
        673,
        677,
        683,
        691,
        701,
        709,
        719,
        727,
        733,
        739,
        743,
        751,
        757,
        761,
        769,
        773,
        787,
        797,
        809,
        811,
        821,
        823,
        827,
        829,
        839,
        853,
        857,
        859,
        863,
        877,
        881,
        883,
        887,
        907,
        911,
        919,
        929,
        937,
        941,
        947,
        953,
        967,
        971,
        977,
        983,
        991,
        997,
    )
    # wheel = (2, 3, 5)
    const = 30
    if N < 2:
        return []
    if N <= const:
        pos = 0
        while __smallp[pos] <= N:
            pos += 1
        return list(__smallp[:pos])
    # make the offsets list
    offsets = (7, 11, 13, 17, 19, 23, 29, 1)
    # prepare the list
    p = [2, 3, 5]
    dim = 2 + N // const
    tk1 = [True] * dim
    tk7 = [True] * dim
    tk11 = [True] * dim
    tk13 = [True] * dim
    tk17 = [True] * dim
    tk19 = [True] * dim
    tk23 = [True] * dim
    tk29 = [True] * dim
    tk1[0] = False
    # help dictionary d
    # d[a , b] = c  ==> if I want to find the smallest useful multiple of (30*pos)+a
    # on tkc, then I need the index given by the product of [(30*pos)+a][(30*pos)+b]
    # in general. If b < a, I need [(30*pos)+a][(30*(pos+1))+b]
    d = {}
    for x in offsets:
        for y in offsets:
            res = (x * y) % const
            if res in offsets:
                d[(x, res)] = y
    # another help dictionary: gives tkx calling tmptk[x]
    tmptk = {1: tk1, 7: tk7, 11: tk11, 13: tk13, 17: tk17, 19: tk19, 23: tk23, 29: tk29}
    pos, prime, lastadded, stop = 0, 0, 0, int(ceil(sqrt(N)))

    # inner functions definition
    def del_mult(tk, start, step):
        for k in range(start, len(tk), step):
            tk[k] = False

    # end of inner functions definition
    cpos = const * pos
    while prime < stop:
        # 30k + 7
        if tk7[pos]:
            prime = cpos + 7
            p.append(prime)
            lastadded = 7
            for off in offsets:
                tmp = d[(7, off)]
                start = (
                    (pos + prime)
                    if off == 7
                    else (prime * (const * (pos + 1 if tmp < 7 else 0) + tmp)) // const
                )
                del_mult(tmptk[off], start, prime)
        # 30k + 11
        if tk11[pos]:
            prime = cpos + 11
            p.append(prime)
            lastadded = 11
            for off in offsets:
                tmp = d[(11, off)]
                start = (
                    (pos + prime)
                    if off == 11
                    else (prime * (const * (pos + 1 if tmp < 11 else 0) + tmp)) // const
                )
                del_mult(tmptk[off], start, prime)
        # 30k + 13
        if tk13[pos]:
            prime = cpos + 13
            p.append(prime)
            lastadded = 13
            for off in offsets:
                tmp = d[(13, off)]
                start = (
                    (pos + prime)
                    if off == 13
                    else (prime * (const * (pos + 1 if tmp < 13 else 0) + tmp)) // const
                )
                del_mult(tmptk[off], start, prime)
        # 30k + 17
        if tk17[pos]:
            prime = cpos + 17
            p.append(prime)
            lastadded = 17
            for off in offsets:
                tmp = d[(17, off)]
                start = (
                    (pos + prime)
                    if off == 17
                    else (prime * (const * (pos + 1 if tmp < 17 else 0) + tmp)) // const
                )
                del_mult(tmptk[off], start, prime)
        # 30k + 19
        if tk19[pos]:
            prime = cpos + 19
            p.append(prime)
            lastadded = 19
            for off in offsets:
                tmp = d[(19, off)]
                start = (
                    (pos + prime)
                    if off == 19
                    else (prime * (const * (pos + 1 if tmp < 19 else 0) + tmp)) // const
                )
                del_mult(tmptk[off], start, prime)
        # 30k + 23
        if tk23[pos]:
            prime = cpos + 23
            p.append(prime)
            lastadded = 23
            for off in offsets:
                tmp = d[(23, off)]
                start = (
                    (pos + prime)
                    if off == 23
                    else (prime * (const * (pos + 1 if tmp < 23 else 0) + tmp)) // const
                )
                del_mult(tmptk[off], start, prime)
        # 30k + 29
        if tk29[pos]:
            prime = cpos + 29
            p.append(prime)
            lastadded = 29
            for off in offsets:
                tmp = d[(29, off)]
                start = (
                    (pos + prime)
                    if off == 29
                    else (prime * (const * (pos + 1 if tmp < 29 else 0) + tmp)) // const
                )
                del_mult(tmptk[off], start, prime)
        # now we go back to top tk1, so we need to increase pos by 1
        pos += 1
        cpos = const * pos
        # 30k + 1
        if tk1[pos]:
            prime = cpos + 1
            p.append(prime)
            lastadded = 1
            for off in offsets:
                tmp = d[(1, off)]
                start = (
                    (pos + prime)
                    if off == 1
                    else (prime * (const * pos + tmp)) // const
                )
                del_mult(tmptk[off], start, prime)
    # time to add remaining primes
    # if lastadded == 1, remove last element and start adding them from tk1
    # this way we don't need an "if" within the last while
    if lastadded == 1:
        p.pop()
    # now complete for every other possible prime
    while pos < len(tk1):
        cpos = const * pos
        if tk1[pos]:
            p.append(cpos + 1)
        if tk7[pos]:
            p.append(cpos + 7)
        if tk11[pos]:
            p.append(cpos + 11)
        if tk13[pos]:
            p.append(cpos + 13)
        if tk17[pos]:
            p.append(cpos + 17)
        if tk19[pos]:
            p.append(cpos + 19)
        if tk23[pos]:
            p.append(cpos + 23)
        if tk29[pos]:
            p.append(cpos + 29)
        pos += 1
    # remove exceeding if present
    pos = len(p) - 1
    while p[pos] > N:
        pos -= 1
    if pos < len(p) - 1:
        del p[pos + 1 :]
    # return p list
    return p


def sieve_of_eratosthenes(n):
    """sieveOfEratosthenes(n): return the list of the primes < n."""
    # Code from: <dickinsm@gmail.com>, Nov 30 2006
    # http://groups.google.com/group/comp.lang.python/msg/f1f10ced88c68c2d
    if n <= 2:
        return []
    sieve = list(range(3, n, 2))
    top = len(sieve)
    for si in sieve:
        if si:
            bottom = (si * si - 3) // 2
            if bottom >= top:
                break
            sieve[bottom::si] = [0] * -((bottom - top) // si)
    return [2] + [el for el in sieve if el]


def sieve_of_atkin(end):
    """return a list of all the prime numbers <end using the Sieve of Atkin."""
    # Code by Steve Krenzel, <Sgk284@gmail.com>, improved
    # Code: https://web.archive.org/web/20080324064651/http://krenzel.info/?p=83
    # Info: http://en.wikipedia.org/wiki/Sieve_of_Atkin
    assert end > 0
    lng = (end - 1) // 2
    sieve = [False] * (lng + 1)

    x_max, x2, xd = int(sqrt((end - 1) / 4.0)), 0, 4
    for xd in range(4, 8 * x_max + 2, 8):
        x2 += xd
        y_max = int(sqrt(end - x2))
        n, n_diff = x2 + y_max * y_max, (y_max << 1) - 1
        if not (n & 1):
            n -= n_diff
            n_diff -= 2
        for d in range((n_diff - 1) << 1, -1, -8):
            m = n % 12
            if m == 1 or m == 5:
                m = n >> 1
                sieve[m] = not sieve[m]
            n -= d

    x_max, x2, xd = int(sqrt((end - 1) / 3.0)), 0, 3
    for xd in range(3, 6 * x_max + 2, 6):
        x2 += xd
        y_max = int(sqrt(end - x2))
        n, n_diff = x2 + y_max * y_max, (y_max << 1) - 1
        if not (n & 1):
            n -= n_diff
            n_diff -= 2
        for d in range((n_diff - 1) << 1, -1, -8):
            if n % 12 == 7:
                m = n >> 1
                sieve[m] = not sieve[m]
            n -= d

    x_max, y_min, x2, xd = int((2 + sqrt(4 - 8 * (1 - end))) / 4), -1, 0, 3
    for x in range(1, x_max + 1):
        x2 += xd
        xd += 6
        if x2 >= end:
            y_min = (((int(ceil(sqrt(x2 - end))) - 1) << 1) - 2) << 1
        n, n_diff = ((x * x + x) << 1) - 1, (((x - 1) << 1) - 2) << 1
        for d in range(n_diff, y_min, -8):
            if n % 12 == 11:
                m = n >> 1
                sieve[m] = not sieve[m]
            n += d

    primes = [2, 3]
    if end <= 3:
        return primes[: max(0, end - 2)]

    for n in range(5 >> 1, (int(sqrt(end)) + 1) >> 1):
        if sieve[n]:
            primes.append((n << 1) + 1)
            aux = (n << 1) + 1
            aux *= aux
            for k in range(aux, end, 2 * aux):
                sieve[k >> 1] = False

    s = int(sqrt(end)) + 1
    if s % 2 == 0:
        s += 1
    primes.extend([i for i in range(s, end, 2) if sieve[i >> 1]])

    return primes


def ambi_sieve_plain(n):
    s = list(range(3, n, 2))
    for m in range(3, int(n ** 0.5) + 1, 2):
        if s[(m - 3) // 2]:
            for t in range((m * m - 3) // 2, (n >> 1) - 1, m):
                s[t] = 0
    return [2] + [t for t in s if t > 0]


def sundaram3(max_n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/2073279#2073279
    numbers = range(3, max_n + 1, 2)
    half = (max_n) // 2
    initial = 4

    for step in range(3, max_n + 1, 2):
        for i in range(initial, half, step):
            numbers[i - 1] = 0
        initial += 2 * (step + 1)

        if initial > half:
            return [2] + filter(None, numbers)


# Using Numpy:
def ambi_sieve(n):
    # http://tommih.blogspot.com/2009/04/fast-prime-number-generator.html
    s = np.arange(3, n, 2)
    for m in range(3, int(n ** 0.5) + 1, 2):
        if s[(m - 3) // 2]:
            s[(m * m - 3) // 2::m] = 0
    return np.r_[2, s[s > 0]]


def primesfrom3to(n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Returns an array of primes, p < n """
    assert n >= 2
    sieve = np.ones(n // 2, dtype=np.bool)
    for i in range(3, int(n ** 0.5) + 1, 2):
        if sieve[i // 2]:
            sieve[i * i // 2::i] = False
    return np.r_[2, 2 * np.nonzero(sieve)[0][1::] + 1]


def primesfrom2to(n):
    # /programming/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Input n>=6, Returns an array of primes, 2 <= p < n """
    assert n >= 6
    sieve = np.ones(n // 3 + (n % 6 == 2), dtype=np.bool)
    sieve[0] = False
    for i in range(int(n ** 0.5) // 3 + 1):
        if sieve[i]:
            k = 3 * i + 1 | 1
            sieve[((k * k) // 3)::2 * k] = False
            sieve[(k * k + 4 * k - 2 * k * (i & 1)) // 3::2 * k] = False
    return np.r_[2, 3, ((3 * np.nonzero(sieve)[0] + 1) | 1)]


def sympy_sieve(n):
    return list(sympy.sieve.primerange(1, n))


perfplot.save(
    "prime.png",
    setup=lambda n: n,
    kernels=[
        rwh_primes,
        rwh_primes1,
        rwh_primes2,
        sieve_wheel_30,
        sieve_of_eratosthenes,
        sieve_of_atkin,
        # ambi_sieve_plain,
        # sundaram3,
        ambi_sieve,
        primesfrom3to,
        primesfrom2to,
        sympy_sieve,
    ],
    n_range=[2 ** k for k in range(3, 25)],
    logx=True,
    logy=True,
    xlabel="n",
)

0

मेरा अनुमान है कि सभी तरह से सबसे तेज़ आपके कोड में primes को हार्ड कोड करना है।

तो क्यों न केवल एक धीमी स्क्रिप्ट लिखी जाए जो एक अन्य स्रोत फ़ाइल उत्पन्न करती है जिसमें सभी संख्याएँ इसमें हार्डवेर की गई हैं, और फिर जब आप अपना वास्तविक प्रोग्राम चलाते हैं तो उस स्रोत फ़ाइल को आयात करते हैं।

बेशक, यह केवल तभी काम करता है जब आप संकलन समय पर एन के ऊपरी हिस्से को जानते हैं, लेकिन इस प्रकार सभी परियोजना शासक समस्याओं के लिए मामला है।

 

पुनश्च: मैं गलत हो सकता हूं, लेकिन अगर हार्ड-वायर्ड प्राइम के साथ स्रोत को पार्स करने से पहले उन्हें कंप्यूटिंग करने की तुलना में धीमी है, लेकिन जहां तक ​​मैं जानता हूं कि संकलित .pycफाइलों से पायथन चलती है, इसलिए एन तक के सभी अपराधों के साथ एक द्विआधारी सरणी पढ़ना खूनी होना चाहिए। उस मामले में उपवास।


0

परेशान करने के लिए क्षमा करें, लेकिन erat2 () के एल्गोरिथ्म में एक गंभीर दोष है।

अगले कंपोजिट की खोज करते समय, हमें केवल विषम संख्याओं का परीक्षण करना होगा। q, p दोनों विषम हैं; तब q + p सम है और परीक्षण करने की आवश्यकता नहीं है, लेकिन q + 2 * p हमेशा विषम होता है। यह लूप स्थिति में "यदि भी" परीक्षण को समाप्त करता है और लगभग 30% रनटाइम बचाता है।

हालांकि हम इस पर हैं: सुरुचिपूर्ण के बजाय 'डी। पॉप (क्यू, कोई नहीं)' पाने और हटाने की विधि का उपयोग करें 'अगर क्यू में डी: पी = डी [क्यू], डेल डी [क्यू]' जो दोगुना तेज़ है। ! कम से कम मेरी मशीन (P3-1Ghz) पर। तो मैं इस चतुर एल्गोरिथ्म के कार्यान्वयन का सुझाव देता हूं:

def erat3( ):
    from itertools import islice, count

    # q is the running integer that's checked for primeness.
    # yield 2 and no other even number thereafter
    yield 2
    D = {}
    # no need to mark D[4] as we will test odd numbers only
    for q in islice(count(3),0,None,2):
        if q in D:                  #  is composite
            p = D[q]
            del D[q]
            # q is composite. p=D[q] is the first prime that
            # divides it. Since we've reached q, we no longer
            # need it in the map, but we'll mark the next
            # multiple of its witnesses to prepare for larger
            # numbers.
            x = q + p+p        # next odd(!) multiple
            while x in D:      # skip composites
                x += p+p
            D[x] = p
        else:                  # is prime
            # q is a new prime.
            # Yield it and mark its first multiple that isn't
            # already marked in previous iterations.
            D[q*q] = q
            yield q

प्राइम में अपराधों को स्थगित करने के लिए तानाशाही में (जब तक कि प्राइम का वर्ग इनपुट में नहीं देखा जाता है) स्टैकओवरफ्लो को देखें / a/ 10733621/849891
विल नेस

0

मैंने अब तक की सबसे तेज़ विधि पायथन कुकबुकerat2 फ़ंक्शन पर आधारित है:

import itertools as it
def erat2a( ):
    D = {  }
    yield 2
    for q in it.islice(it.count(3), 0, None, 2):
        p = D.pop(q, None)
        if p is None:
            D[q*q] = q
            yield q
        else:
            x = q + 2*p
            while x in D:
                x += 2*p
            D[x] = p

इस उत्तर को तेज गति के स्पष्टीकरण के लिए देखें ।


0

मुझे पार्टी में देर हो सकती है लेकिन इसके लिए मुझे अपना कोड जोड़ना होगा। यह अंतरिक्ष में लगभग n / 2 का उपयोग करता है क्योंकि हमें संख्याओं को संग्रहीत करने की आवश्यकता नहीं है और मैं बिटार्रे पायथन मॉड्यूल का भी उपयोग करता हूं, आगे मेमोरी की खपत में कटौती कर रहा है और 1,000,000 तक सभी प्राइम की गणना करने में सक्षम है

from bitarray import bitarray
def primes_to(n):
    size = n//2
    sieve = bitarray(size)
    sieve.setall(1)
    limit = int(n**0.5)
    for i in range(1,limit):
        if sieve[i]:
            val = 2*i+1
            sieve[(i+i*val)::val] = 0
    return [2] + [2*i+1 for i, v in enumerate(sieve) if v and i > 0]

python -m timeit -n10 -s "import euler" "euler.primes_to(1000000000)"
10 loops, best of 3: 46.5 sec per loop

यह 64 बिट 2.4GHZ MAC OSX 10.8.3 पर चलाया गया था


1
एक अज्ञात मशीन के लिए एक समय पोस्टिंग कुछ भी नहीं कहती है। यहाँ स्वीकृत उत्तर कहता है कि "मानस के बिना, n = 1000000 के लिए, rwh_primes2 सबसे तेज़ था"। इसलिए यदि आप उस कोड के लिए अपनी टाइमिंग के साथ-साथ आपके लिए, उसी मशीन पर, और 2, 4, 10 mln पर भी प्रदान करेंगे, तो यह बहुत अधिक जानकारीपूर्ण होगा।
विल नेस

-1, यह कोड C में लागू बिटार्रे की विशेष विशेषताओं पर निर्भर करता है, यही कारण है कि कोड तेज है क्योंकि अधिकांश कार्य स्लाइस असाइनमेंट में देशी कोड में किया जा रहा है। Bitarray पैकेज टूट परिवर्तनशील दृश्यों के लिए उचित स्लाइस के लिए मानक परिभाषा (एक सीमा से अधिक अनुक्रमित) में है कि यह एक एकल बूलियन 0/1 या सही / टुकड़ा के सभी तत्वों को झूठी, जबकि शुद्ध अजगर के लिए मानक व्यवहार करने लगता है बताए की अनुमति देता है इसे अनुमति न दें और केवल 0 के असाइनमेंट मान की अनुमति दें जिस स्थिति में इसे अनुक्रम / सरणी से सभी स्लाइस तत्वों के डेल के रूप में माना जाता है।
गॉर्डनबूड

cont'd: यदि गैर-मानक देशी कोड की तुलना की जाए, तो हम C कोड के आधार पर "फास्टप्रिम्स" सीक्वेंस जनरेटर पैकेज लिख सकते हैं, जैसे कि किम वाल्स्कि की primesieve और सभी बिल को चार बिलियन प्लस 32 में जेनरेट करते हैं। अनुक्रम जनरेटर के लिए एक कॉल के साथ बस कुछ ही सेकंड में -बिट संख्या सीमा। यह भी लगभग किसी भी मेमोरी का उपयोग नहीं करेगा क्योंकि लिंक किए गए कोड इरेटोस्थनीज की एक खंडित छलनी पर आधारित है और इस प्रकार केवल कुछ दस किलोबाइट्स रैम का उपयोग करता है, और यदि एक अनुक्रम उत्पन्न होता है तो कोई सूची भंडारण की आवश्यकता नहीं होगी।
गॉर्डनबूड

0

मैंने समय के साथ कई अभाज्य संख्याएँ एकत्रित कीं। मेरे कंप्यूटर पर सबसे तेज़ यह है:

from time import time
# 175 ms for all the primes up to the value 10**6
def primes_sieve(limit):
    a = [True] * limit
    a[0] = a[1] = False
    #a[2] = True
    for n in xrange(4, limit, 2):
        a[n] = False
    root_limit = int(limit**.5)+1
    for i in xrange(3,root_limit):
        if a[i]:
            for n in xrange(i*i, limit, 2*i):
                a[n] = False
    return a

LIMIT = 10**6
s=time()
primes = primes_sieve(LIMIT)
print time()-s

0

मैं इस सवाल का जवाब धीमी गति से दे रहा हूं लेकिन यह एक मजेदार अभ्यास था। मैं सुन्न का उपयोग कर रहा हूं जो धोखा दे सकता है और मुझे संदेह है कि यह विधि सबसे तेज़ है लेकिन यह स्पष्ट होना चाहिए। यह एक बूलियन सरणी को संदर्भित करता है जो केवल इसके सूचकांकों का उल्लेख करता है और सभी सच्चे मूल्यों के सूचकांकों से अभाज्य संख्याओं को हटाता है। कोई मोडुलो की जरूरत नहीं।

import numpy as np
def ajs_primes3a(upto):
    mat = np.ones((upto), dtype=bool)
    mat[0] = False
    mat[1] = False
    mat[4::2] = False
    for idx in range(3, int(upto ** 0.5)+1, 2):
        mat[idx*2::idx] = False
    return np.where(mat == True)[0]

यह गलत है जैसे, ajs_primes3a(10)-> array([2, 3, 5, 7, 9])9एक प्रधान नहीं है
jfs

आपने एक किनारे का मामला देखा, जो मैंने नहीं किया था - अच्छी तरह से! समस्या 'रेंज में आईडीएक्स (3, int (** 0.5), 2), 2) के लिए थी:' रेंज में आईडीएक्स के लिए 'होना चाहिए (3, इंट (** 0.5 तक) + 1, 2):'। धन्यवाद लेकिन अब यह काम करता है।
एलन जेम्स सल्मोनी

कारण यह था कि आइडेंट लूप '** ०५ ’तक चला गया जो कि १५ तक और १५ तक के मामलों के लिए था। १६ से यह ठीक काम करता है। यह मेरे लिए परीक्षण नहीं किए गए किनारे के मामलों का एक सेट था। 1 जोड़ने का मतलब है कि यह सभी नंबरों के लिए काम करना चाहिए।
एलन जेम्स सल्मोनी

यह अब काम करने लगता है। यह numpyएक सरणी वापस लौटने वाले सबसे धीमे समाधान के बीच है । नोट: कोई भी सच्ची छलनी इरेटोस्थनीज कार्यान्वयन मोडुलो का उपयोग नहीं करता है - इसका उल्लेख करने की आवश्यकता नहीं है। आप mat[idx*idx::idx]इसके बजाय उपयोग कर सकते हैं mat[idx*2::idx]। और के np.nonzero(mat)[0]बजाय np.where(mat == True)[0]
JFS

धन्यवाद JF मैंने प्राइम 6 () के खिलाफ परीक्षण किया और प्राइम 6 () को संभालने के दौरान (आईआईआरसी) के बारे में 250k तक तेजी से परिणाम मिला। primesfrom2to () तेज था। 20m तक, ajs_primes3a () ने 0.034744977951ms लिया, प्राइम 6 () ने 0.0222899913788ms और primesfrom2to () ने 0.0104751586990ms (एक ही मशीन, एक ही लोड, 10 टाइमिंग में सर्वश्रेष्ठ) लिया। यह ईमानदारी से बेहतर है जितना मैंने सोचा था कि यह होगा!
एलन जेम्स सलोनी

0

अजगर की सूची की समझ का उपयोग करते हुए अभाज्य संख्या (अभी तक सबसे कुशल नहीं) उत्पन्न करने के लिए एक दिलचस्प तकनीक है:

noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)]
primes = [x for x in range(2, 50) if x not in noprimes]

आप उदाहरण और कुछ स्पष्टीकरण यहाँ पा सकते हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.