Сито Эратосфена будет очень похоже на простое. Но вам нужно начать со списка простых чисел.
С простыми числами у вас есть набор i * prime(k)
членов, где prime
- наша последовательность, а i
- то, что мы увеличиваем для каждого элемента в последовательности.
Здесь у вас есть набор prime(i) + a(k)
членов, где a
- наша последовательность, а i
- то, что мы увеличиваем для каждого элемента в последовательности.
Конечно, +
вместо *
сильно влияет на общую эффективность.
Приведенный ниже код увеличивается до 100 000 за несколько секунд, поэтому он будет медленным, если вы хотите генерировать особенно большие числа.
Вы можете подождать и посмотреть, придумает ли кто-нибудь более быстрый метод.
# taken from https://stackoverflow.com/questions/3939660
def primes_sieve(limit):
a = [True] * limit
a[0] = a[1] = False
for (i, isprime) in enumerate(a):
if isprime:
yield i
for n in range(i*i, limit, i):
a[n] = False
def a_sieve(limit, primes):
a = [True] * limit
for (i, in_seq) in enumerate(a):
if in_seq:
yield i
for n in primes:
if i+n >= limit:
break
a[i+n] = False
primes = list(primes_sieve(100000))
a = list(a_sieve(100000, primes))
# a = [0, 1, 9, 10, 25, 34, 35, 49, 55, 85, 91, 100, 115, 121, 125, 133, 145, ...]
Для сравнения я написал следующие методы грубой силы, один из которых перебирает простые числа и проверяет, вычитает ли он элемент в нашей последовательности, а другой - перебирает нашу последовательность и проверяет, получим ли мы простое число, оба из которых требуют примерно вдвое длиннее для 100 тыс.
Он выглядит несколько похожим на сито, но смотрит назад, а не устанавливает значения вперед.
def a_brute(limit, primes):
a = [True] * limit
for i in range(limit):
for p in primes:
if i-p < 0:
yield i
break
if a[i-p]:
a[i] = False
break
else:
yield i
def a_brute2(limit, primes_sieve):
a = [True] * limit
l = []
for i in range(limit):
for j in l:
if i-j < 0:
l.append(i)
break
if primes_sieve[i-j]:
a[i] = False
break
else:
l.append(i)
return l
Результат:
Primes sieve: 0.02 seconds
Sieve: 6.26 seconds
Brute force 1: 14.14 seconds
Brute force 2: 12.34 seconds