Матрис и питон [дубликат]

Убедитесь, что сценарий содержит

<?php

перед кодом, который должен быть выполнен. Между <? и php в этом не должно быть пробелов.

319
задан bjb568 2 November 2014 в 23:33
поделиться

28 ответов

Самый быстрый метод, который я пробовал до сих пор, основан на функции кулинарной книги Python 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

См. этот ответ для объяснения ускорения.

321
ответ дан Community 20 August 2018 в 15:44
поделиться
  • 1
    Это не чистый Python, но это самая быстрая версия. благодаря! – jbochi 15 January 2010 в 02:11
  • 2
    Если вас интересует нечисто-Python-код, вы должны проверить gmpy - он имеет довольно хорошую поддержку простых чисел с помощью метода next_prime своего типа mpz. – Alex Martelli 15 January 2010 в 02:41
  • 3
    Если вы используете pypy, эти тесты (psyco) кажутся довольно прочь. Удивительно, но я нашел sieveOfEratosthenes и ambi_sieve_plain самым быстрым с pypy. Это то, что я нашел для не-numpy gist.github.com/5bf466bb1ee9e5726a52 – Ehsan Kia 28 April 2014 в 02:53
  • 4
    Если кто-то задается вопросом, как здесь действуют функции против PG7.8 из Викиучебников для чистого питона без psyco и pypy: для n = 1000000: PG7.8: 4.93 с за цикл; rwh_primes1: 69 мс за цикл; rwh_primes2: 57,1 мс за цикл – gaborous 9 July 2015 в 13:19
  • 5
    Можете ли вы обновить это с помощью PyPy, теперь, когда psyco мертв, и PyPy вытеснил его? – noɥʇʎԀʎzɐɹƆ 23 December 2016 в 23:20
327
ответ дан Community 31 October 2018 в 11:49
поделиться

Связанный с этим вопрос (посвященный генераторам простых чисел и в том числе эталонам): Ускорение битстронных / битовых операций в Python?

Для быстрой версии python 3 см. код Bruno Astrolino: https://stackoverflow.com/a/46635266/350331

Faster & amp; более чистый код Python с памятью:

def primes(n):
    """ 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 primes1(n):
    """ 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]]

Faster & amp; более объемный код с памятью:

import numpy
def primesfrom3to(n):
    """ Returns a array of primes, 3 <= p < n """
    sieve = numpy.ones(n/2, dtype=numpy.bool)
    for i in xrange(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 xrange(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)]

Версия с чистым питоном A (жесткий код) из вышеприведенного кода будет:

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 xrange(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 xrange(1,n/3-correction) if sieve[i]]

К сожалению, чистый-питон не использует более простой и более быстрый способ выполнения задания Assignment, а вызов len () внутри цикла, как и в [False]*len(sieve[((k*k)/3)::2*k]), тоже медленный. Поэтому мне пришлось импровизировать, чтобы исправить ввод (и избежать большей математики) и сделать некоторую экстремальную (и больную) математическую магию. Лично я считаю, что стыдно, что numpy (который так широко используется) не является частью стандартной библиотеки python (через 2 года после версии python 3 и без совместимости с numpy), и что улучшения в синтаксисе и скорости, похоже, полностью игнорируются разработчиками python.

112
ответ дан 15 revs, 2 users 98% 20 August 2018 в 15:44
поделиться
  • 1
    +1: primesfrom3to (19,6 мс) значительно быстрее, чем ambi_sieve (29,4 мс). Потрясающе. Спасибо, что поделился. PS. Поскольку 2 является простым, рассмотрите ли вы изменение возвращаемого значения на numpy.r_[2, 2*np.nonzero(sieve)[0][1::]+1]? – unutbu 14 June 2010 в 14:11
  • 2
    я использую код таким образом, не смог изменить его для тестов, если вы хотите, возможно, с коррекцией время будет почти одинаковым для 1e6 (для 1e7 до 1e9 должно быть быстрее), также PLZ tel me how primes (n) & амп; primes1 (n) сравните вашу машину с лучшим кодом на python для 1e6 & amp; 1e7. – Robert William Hanks 14 June 2010 в 20:44
  • 3
    Я не вижу измеримого ускорения для нового primesfrom2to() ideone.com/5YJkw (сравнение производительности находится в конце файла) – jfs 25 July 2010 в 19:03
  • 4
    Теперь Numpy совместим с Python 3. Тот факт, что он не в стандартной библиотеке, хорош, таким образом, у них может быть свой собственный цикл выпуска. – Adam 25 March 2013 в 01:17
  • 5
    Для чистой версии python, совместимой с python 3, перейдите по этой ссылке: stackoverflow.com/a/33356284/2482582 – Moebius 8 April 2016 в 20:15
  • 6
    – Robert Frost 11 September 2018 в 21:18

Я знаю, что конкурс закрыт на несколько лет. ...

Тем не менее это мое предложение для чистого простого сита python, основанного на исключении кратных 2, 3 и 5 с помощью соответствующих шагов при обработке сита вперёд. Тем не менее, это на самом деле медленнее для N & lt; 10 ^ 9, чем @Robert William Hanks превосходные решения rwh_primes2 и rwh_primes1. С помощью массива ctypes.c_ushort выше 1.5 * 10 ^ 8 он каким-то образом адаптируется к ограничениям памяти.

10 ^ 6

$ python -mtimeit -s "import primeSieveSpeedComp" " PrimeSieveSpeedComp.primeSieveSeq (1000000) "10 циклов, лучше всего 3: 46,7 мсек за цикл

для сравнения: $ python -mtimeit -s" import primeSieveSpeedComp "" primeSieveSpeedComp.rwh_primes1 (1000000) "10 петли, лучше всего 3: 43,2 мсек за цикл для сравнения: $ python -m timeit -s "import primeSieveSpeedComp" "primeSieveSpeedComp.rwh_primes2 (1000000)" 10 циклов, лучше всего 3: 34,5 мсек за цикл

10 ^ 7

$ python -mtimeit -s "import primeSieveSpeedComp" "primeSieveSpeedComp.primeSieveSeq (10000000)" 10 циклов, лучше всего 3: 530 мсек за цикл

для сравнения: $ python -mtimeit -s "import primeSieveSpeedComp" "primeSieveSpeedComp.rwh_primes1 (10000000)" 10 циклов, лучше всего 3: 494 мсек за цикл для сравнения: $ python -m timeit -s "import primeSieveSpeedComp" " primeSieveSpeedComp.rwh_primes2 (+100000 00) «10 циклов, лучше всего 3: 375 мсек за цикл

10 ^ 8

$ python -mtimeit -s" import 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 primeSieveSpeedComp" "primeSieveSpeedComp.rwh_primes2 (100000000)" 10 циклов, лучше всего 3: 3,95 с за цикл

10 ^ 9

$ python -mtimeit -s "import primeSieveSpeedComp" "primeSieveSpeedComp.primeSieveSeq (1000000000)" 10 циклов, лучше всего 3: 61,2 сек за цикл

to Сравнение: $ 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
2
ответ дан ABri 20 August 2018 в 15:44
поделиться

Я предполагаю, что самый быстрый всех способов - это жестко кодировать простые числа в вашем коде.

Итак, почему бы просто не написать медленный скрипт, который генерирует другой исходный файл, который имеет все номера в нем, а затем импортирует этот исходный файл при запуске вашей реальной программы.

Конечно, это работает, только если вы знаете верхнюю границу N во время компиляции, но, таким образом, это так для (почти) всех проектных задач Эйлера.

& nbsp;

PS: Возможно, я ошибаюсь, хотя разбор источника с проводными штрихами медленнее, чем вычисление их в первую очередь, но насколько я знаю Python запускается из скомпилированных файлов .pyc, поэтому чтение двоичного массива со всеми штрихами до N должно быть быстрым в этом случае.

0
ответ дан akuhn 20 August 2018 в 15:44
поделиться

Я медленно отвечаю на этот вопрос, но это было похоже на забавное упражнение. Я использую numpy, который может быть обманом, и я сомневаюсь, что этот метод является самым быстрым, но он должен быть ясным. Он решает булевой массив, ссылаясь только на его индексы, и выдает простые числа из индексов всех значений True. Нет необходимости в модуле.

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]
0
ответ дан Alan James Salmoni 20 August 2018 в 15:44
поделиться
  • 1
    это неверно, например, ajs_primes3a(10) - & gt; array([2, 3, 5, 7, 9]). 9 не является простым – jfs 14 February 2015 в 22:06
  • 2
    Вы заметили краевой кейс, которого я не сделал - молодец! Проблема заключалась в «для idx в диапазоне (3, int (до ** 0,5), 2):« что должно быть »для idx в диапазоне (3, int (до ** 0,5) + 1, 2): '. Спасибо, но сейчас это работает. – Alan James Salmoni 15 February 2015 в 23:14
  • 3
    Причина заключалась в том, что цикл idx поднялся до «upto ** 05», который для случаев до 15 включительно включительно. Начиная с 16, он отлично работает. Это был набор крайних случаев, на которые я не тестировался. Добавление 1 означает, что он должен работать для всех чисел. – Alan James Salmoni 15 February 2015 в 23:18
  • 4
    Кажется, теперь это работает. Это самый медленный из решений, основанных на numpy, которые возвращают массив. Примечание: нет истинной реализации решета Eratosthenes по модулю - не нужно упоминать об этом. Вы можете использовать mat[idx*idx::idx] вместо mat[idx*2::idx]. И np.nonzero(mat)[0] вместо np.where(mat == True)[0]. – jfs 16 February 2015 в 00:53
  • 5
    Спасибо JF. Я протестировал против prim6 () и получил результат быстрее (IIRC) около 250 тыс., Когда занял Prime6 (). primesfrom2to () был быстрее. На расстоянии до 20 м ajs_primes3a () заняло 0.034744977951ms, prime6 () заняло 0.0222899913788ms, а primesfrom2to () заняло 0.0104751586914ms (тот же самый компьютер, одна и та же загрузка, лучшее из 10 таймингов). Это честно лучше, чем я думал! – Alan James Salmoni 16 February 2015 в 16:54

Вот интересный метод генерации простых чисел (но не самый эффективный) с использованием списков python:

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]

Здесь вы можете найти пример и некоторые объяснения здесь

0
ответ дан Alexander 20 August 2018 в 15:44
поделиться

Вот две обновленные (чистые версии Python 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:])]
2
ответ дан Bruno Astrolino 20 August 2018 в 15:44
поделиться

Я могу опоздать на вечеринку, но для этого мне придется добавить свой собственный код. Он использует приблизительно n / 2 в пространстве, потому что нам не нужно хранить четные числа, и я также использую модуль python bitarray, дополнительно сокращая потребление памяти и позволяя вычислять все простые числа до 1 000 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

0
ответ дан cobie 20 August 2018 в 15:44
поделиться
  • 1
    отправка одного времени для неизвестной машины ничего не говорит. В принятом ответе здесь говорится «без psyco», для n = 1000000, rwh_primes2 был самым быстрым ». Поэтому, если вы предоставите свои тайминги для этого кода, а также своего, на том же компьютере и на 2, 4, 10 млн., then , это будет гораздо более информативным. – Will Ness 17 April 2013 в 08:32
  • 2
    -1, Этот код зависит от особенностей битрейма, реализованного на C, поэтому код выполняется быстро, так как большая часть работы выполняется в собственном коде при назначении среза. Пакет bitarray BREAKS стандартное определение для правильных фрагментов (индексированных по диапазону) для изменяемых последовательностей в том, что он позволяет назначать одному логическому 0/1 или True / False всем элементам среза, тогда как стандартное поведение для чистого Python, похоже, не допускает этого и допускает только присвоение значения 0, и в этом случае оно рассматривается как del всех элементов среза из последовательности / массива. – GordonBGood 19 August 2013 в 17:46
  • 3
    cont'd: Если вы вызывали нестандартный собственный код, мы могли бы также написать «fastprimes». пакет генератора последовательности, основанный на C-коде, например, на primesieveieve Kim Walisch , и генерирует все простые числа в диапазоне четырех миллиардов плюс 32-разрядный номер всего за несколько секунд при одном вызове генератора последовательности. Это также почти не использует память, поскольку связанный код основан на сегментированном сите Эратосфена и, таким образом, использует только несколько десятков килобайт ОЗУ, и если последовательность была сгенерирована, не потребуется хранения списка. – GordonBGood 19 August 2013 в 18:54

Поучительно писать свой собственный код первичного поиска, но также полезно иметь быструю надежную библиотеку под рукой. Я написал обертку вокруг библиотеки C ++ primesieve , назвал ее primesieve-python

Попробуйте pip install primesieve

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

Мне было бы любопытно увидеть скорость сравнения.

41
ответ дан Colonel Panic 20 August 2018 в 15:44
поделиться
  • 1
    @jbochi, пожалуйста, но посмотрите на этот URL-адрес, включая кредиты: нам понадобилось ten для коллективного уточнения кода до этого момента, включая светильники Python-performance, такие как Tim Peters и Раймондом Хеттингером (я написал окончательный текст рецепта с тех пор, как отредактировал печатную Поваренную книгу, но с точки зрения кодирования моего вклада был наравне с другими), - в конце концов, это действительно тонкий и точно настроенный код, и это не удивительно! -) – Alex Martelli 15 January 2010 в 00:59
  • 2
    @Alex: зная, что ваш код «только» & quot; в два раза быстрее, чем у меня, делает меня довольно гордым. :) URL-адрес был также очень интересным для чтения. Еще раз спасибо. – jbochi 15 January 2010 в 01:13
  • 3
    И это можно сделать еще быстрее с небольшими изменениями: см. stackoverflow.com/questions/2211990/… – tzot 26 September 2010 в 04:02
  • 4
    ... И это можно сделать еще быстрее с дополнительным ускорением ~ 1.2x-1.3x, резким уменьшением объема памяти от O (n) до O (sqrt (n)) и улучшением эмпирического времени сложность, отложив добавление простых чисел в dict, пока их значение square не будет видно на входе. Проверьте здесь . – Will Ness 2 August 2012 в 23:28
  • 5
    См. Также github.com/jaredks/pyprimesieve – Colonel Panic 9 July 2015 в 15:50
  • 6
    Это не совсем то, что приказал OP, но я не понимаю, почему downvote. Это решение 2.8sec, в отличие от других внешних модулей. Я заметил в источнике, что он пронизан резьбой, получил какие-то тесты на то, насколько хорошо он масштабируется? – ljetibo 14 July 2015 в 07:24
  • 7
    @ljetibo приветствия. Узкое место, похоже, копирует вектор C ++ в список Python, поэтому функция count_primes намного быстрее, чем generate_primes – Colonel Panic 14 July 2015 в 08:19
  • 8
    На моем компьютере он может с комфортом генерировать простые числа до 1e8 (он дает MemoryError для 1e9) и подсчитывает числа до 1e10. @HappyLeapSecond выше сравнивает алгоритмы для 1e6 – Colonel Panic 14 July 2015 в 08:30

Для самого быстрого кода решение numpy является лучшим. Однако по чисто академическим причинам я публикую мою чистую версию python, которая немного меньше, чем на 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
ответ дан Daniel G 20 August 2018 в 15:44
поделиться

Если у вас есть контроль над N, самый быстрый способ перечислить все простые числа - это прекомпилировать их. Шутки в сторону. Предкомпиляция - это способ, который не учитывается при оптимизации.

4
ответ дан Dave W. Smith 20 August 2018 в 15:44
поделиться
  • 1
    Или загрузите их здесь primes.utm.edu/lists/small/millions , но идея состоит в том, чтобы проверить лимит python и посмотреть, появляется ли красивый код из оптимизации. – jbochi 21 January 2010 в 11:14

Если вы принимаете itertools, но не numpy, вот адаптация rwh_primes2 для Python 3, которая работает на моей машине примерно в два раза быстрее. Единственным существенным изменением является использование bytearray вместо списка для логического и использование сжатия вместо понимания списка для создания окончательного списка. (Я бы добавил это как комментарий, например moarningsun, если бы я был в состоянии.)

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
6
ответ дан Jason 20 August 2018 в 15:44
поделиться

Используя сито Сундарама , я думаю, что я сломал запись чистого Python:

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)

Сравнение:

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
29
ответ дан jbochi 20 August 2018 в 15:44
поделиться
  • 1
    Мне удалось ускорить вашу функцию примерно на 20%, добавив «ноль = 0». в верхней части функции, а затем заменяя лямбда в вашем фильтре на «ноль .__ sub __». Не самый красивый код в мире, но немного быстрее :) – truppo 20 January 2010 в 11:34
  • 2
    @truppo: Спасибо за ваш комментарий! Я просто понял, что передача None вместо исходной функции работает, и она даже быстрее, чем zero.__sub__ – jbochi 20 January 2010 в 12:08
  • 3
    Знаете ли вы, что если вы пройдете sundaram3(9), он вернет [2, 3, 5, 7, 9]? Кажется, что это происходит с многочисленными - возможно, все - нечетными числами (даже если они не являются первичными) – wrhall 22 September 2013 в 00:57
  • 4
    у него есть проблема: sundaram3 (7071) включает 7071, в то время как он не является простым – BigOther 7 January 2016 в 08:08
  • 1
    Справедливости ради следует сказать, что вам нужно было бы посчитать время загрузки, распаковки и форматирования простых чисел и сравнить их с временем генерации простых чисел с использованием алгоритма - любой из этих алгоритмов мог бы легко записать результаты в файл для последующего использовать. Я думаю, что в этом случае, учитывая достаточную память, чтобы фактически вычислить все простые числа менее 982 451 653, решение numpy все равно будет быстрее. – Daniel G 15 January 2010 в 09:49
  • 2
    @ Даниэль правильно. Однако магазин, который у вас есть, и продолжайте при необходимости, еще стоит ... – Kimvais 15 January 2010 в 11:11
  • 3
    @ Daniel G Я думаю, что время загрузки не имеет значения. Разве это не связано с генерацией чисел, поэтому вы хотели бы принять во внимание алгоритм, используемый для создания этого списка, который вы загружаете. И любая временная сложность будет игнорировать один раз из передачи файла, учитывая его O (n). – Ross 22 October 2014 в 23:56
  • 4
    FAQ для главной страницы UTM предполагает, что вычисление малых простых чисел происходит быстрее, чем чтение их с диска (вопрос в том, что означает малый). – Batman 23 May 2017 в 00:59

Все написано и протестировано. Таким образом, нет необходимости изобретать колесо.

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 мс для лучшего решения. Сравните это !!!

2
ответ дан lifolofi 20 August 2018 в 15:44
поделиться

Вот код, который я обычно использую для генерации простых чисел в Python:

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

Он не может конкурировать с более быстрыми решениями, размещенными здесь, но по крайней мере это чистый питон.

Спасибо, что опубликовал этот вопрос. Сегодня я многому научился.

4
ответ дан MAK 20 August 2018 в 15:44
поделиться

Это можно сравнить с другими.

# You have to list primes upto n
nums = xrange(2, n)
for i in range(2, 10):
    nums = filter(lambda s: s==i or s%i, nums)
print nums

Так просто ...

-3
ответ дан Nisse Engström 20 August 2018 в 15:44
поделиться

Немного отличается реализация половинного сита с помощью Numpy:

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

import math
import numpy
def prime6(upto):
    primes=numpy.arange(3,upto+1,2)
    isprime=numpy.ones((upto-1)/2,dtype=bool)
    for factor in primes[:int(math.sqrt(upto))]:
        if isprime[(factor-2)/2]: isprime[(factor*3-2)/2:(upto-1)/2:factor]=0
    return numpy.insert(primes[isprime],0,2)

Может ли кто-то сравнить это с другими таймингами? На моей машине это кажется довольно сопоставимым с другим полурешеткой Numpy.

3
ответ дан nolfonzo 20 August 2018 в 15:44
поделиться

В общем случае, если вам нужно быстрое вычисление числа, python не лучший выбор. Сегодня существует много более быстрого (и сложного) алгоритма. Например, на моем компьютере я получил 2,2 секунды для вашего кода, а Mathematica получил 0.088005.

Прежде всего: вам нужно установить?

-1
ответ дан Ruggero Turra 20 August 2018 в 15:44
поделиться
  • 1
    Как вы можете это сказать? Вы пробовали два решения на одной машине? – Ruggero Turra 15 January 2010 в 11:52
  • 2
    @wiso: Он может использовать ваши пропорции, чтобы экстраполировать, как долго Mathematica возьмет свою машину. Если его экстраполяция неверна, это может означать, что эти два алгоритма более или менее эффективны, чем обычно, в зависимости от настройки машины. – Brian 15 January 2010 в 21:54

Детерминированная реализация теста Первичности Миллера-Рабина в предположении, что N & lt; 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 & lt; 9,080,191 для a = 2,3,37 и 73 достаточно, чтобы решить, является ли N составным или нет.

И я адаптировал исходный код из вероятностной реализации оригинального теста Миллера-Рабина, найденного здесь: http://en.literateprograms.org/Miller-Rabin_primality_test_ (Python)

3
ответ дан Ruggiero Spearman 20 August 2018 в 15:44
поделиться
  • 1
    Спасибо за тест примитивности Миллера-Рабина, но этот код на самом деле медленнее и не дает правильных результатов. 37 является простым и не проходит тест. – jbochi 21 January 2010 в 11:07
  • 2
    Я думаю, 37 - это один из особых случаев, мой плохой. Я надеялся на детерминистскую версию, хотя :) – Ruggiero Spearman 21 January 2010 в 12:07
  • 3
    Специального случая для рабинового мельника нет. – Julián 27 November 2013 в 01:37
  • 4
    Вы неправильно читаете статью. Это 31, а не 37. Вот почему ваша реализация терпит неудачу. – Logan 25 December 2013 в 00:36

Первый раз, используя python, поэтому некоторые из методов, которые я использую в этом, могут показаться немного громоздкими. Я просто конвертировал свой код на C ++ в python, и это то, что у меня есть (хотя и немного медленный в python)

#!/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

Найдено 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

Найдено 664579 простых чисел за 10.230172 секунд!

#!/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

Найдено 664579 простых чисел в 7.113776 секунд!

2
ответ дан smac89 20 August 2018 в 15:44
поделиться

Для Python 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]]
1
ответ дан SmartManoj 20 August 2018 в 15:44
поделиться

С течением времени я собрал несколько простейших сит. Самый быстрый на моем компьютере следующий:

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
ответ дан Stefan Gruenwald 20 August 2018 в 15:44
поделиться

Алгоритм работает быстро, но имеет серьезный недостаток:

>>> 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() удаляет и возвращает произвольный элемент, поэтому его нельзя использовать для выбора следующего простого числа из оставшихся чисел.

18
ответ дан sth 20 August 2018 в 15:44
поделиться

Извините за беспокойство, но erat2 () имеет серьезный недостаток в алгоритме.

При поиске следующего композита нам нужно проверить только нечетные числа. q, p оба нечетны; то q + p четно и не нуждается в проверке, но q + 2 * p всегда нечетно. Это исключает проверку «если даже» в условиях цикла while и экономит около 30% времени выполнения.

Пока мы находимся в этом: вместо элегантного «D.pop (q, None)», get и delete использовать метод ', если q в D: p = D [q], del D [q]', что вдвое быстрее! По крайней мере, на моей машине (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
0
ответ дан user1016274 20 August 2018 в 15:44
поделиться

Это элегантное и более простое решение для поиска простых чисел с использованием сохраненного списка. Начинается с 4 переменных, вам нужно только проверять нечетные простые числа для делителей, и вам нужно проверить только половину того числа, которое вы тестируете как простое (нет смысла тестировать, делят ли 9, 11, 13 на 17) , Он проверяет ранее сохраненные простые числа как делители. `

    # Program to calculate Primes
 primes = [1,3,5,7]
for n in range(9,100000,2):
    for x in range(1,(len(primes)/2)):
        if n % primes[x] == 0:
            break
    else:
        primes.append(n)
print primes
-2
ответ дан user3261711 20 August 2018 в 15:44
поделиться
41
ответ дан Colonel Panic 31 October 2018 в 11:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: