Так как настоящего сита еще никто не показал и не объяснил, попробую.
Основной метод - начать отсчет с 2 и исключить 2 * 2 и все более высокие числа, кратные 2 (например, 4, 6, 8 ...), поскольку ни одно из них не может быть простым. 3 пережил первый раунд, поэтому он прост, и теперь мы исключаем 3 * 3 и все более высокие числа, кратные 3 (то есть 9, 12, 15 ...). 4 было исключено, 5 уцелело и т.д. Возведение в квадрат каждого простого числа - это оптимизация, которая использует тот факт, что все меньшие кратные каждого нового простого числа будут исключены в предыдущих раундах. При подсчете и удалении непростых чисел с помощью этого процесса останутся только простые числа.
Вот очень простая версия, обратите внимание, что она не использует деление по модулю или корни:
def primes(n): # Sieve of Eratosthenes
prime, sieve = [], set()
for q in xrange(2, n+1):
if q not in sieve:
prime.append(q)
sieve.update(range(q*q, n+1, q))
return prime
>>> primes(100)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73
79, 83, 89, 97]
Вышеупомянутый простой подход на удивление быстр, но не использует тот факт, что простые числа могут быть только нечетными числами.
Вот версия на основе генератора, которая работает быстрее, чем любая другая, которую я нашел, но достигает лимита памяти Python на n = 10 ** 8 на моей машине.
def pgen(n): # Fastest Eratosthenes generator
yield 2
sieve = set()
for q in xrange(3, n+1, 2):
if q not in sieve:
yield q
sieve.update(range(q*q, n+1, q+q))
>>> timeit('n in pgen(n)', setup="from __main__ import pgen; n=10**6", number=10)
5.987867565927445
Вот немного более медленная, но гораздо более эффективная по памяти версия генератора:
def pgen(maxnum): # Sieve of Eratosthenes generator
yield 2
np_f = {}
for q in xrange(3, maxnum+1, 2):
f = np_f.pop(q, None)
if f:
while f != np_f.setdefault(q+f, f):
q += f
else:
yield q
np = q*q
if np < maxnum:
np_f[np] = q+q
>>> timeit('n in pgen(n)', setup="from __main__ import pgen; n=10**6", number=10)
7.420101730225724
>>> list(pgen(10))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
Чтобы проверить, является ли число простым, просто выполните:
>>> 539 in pgen(539)
False
>>> 541 in pgen(541)
True
Вот несколько советов о том, как работает эта версия с более эффективным использованием памяти. Он использует dict
для хранения только самого минимума информации, следующих непростых чисел (в качестве ключей) вместе с их множителями (в качестве значений). Поскольку каждый непростой ключ находится в dict
, он удаляется, а следующий непростой ключ добавляется с тем же значением множителя.
person
dansalmo
schedule
17.10.2013