Почему моя реализация сита Аткин с видом на номера близко к указанному пределу?
-
25-09-2019 - |
Вопрос
Моя реализация Сито ушки либо упускают простые простуды рядом с пределом или композитами вблизи предела. в то время как некоторые ограничивает работу и другие не. Я полностью запутался как к тому, что не так.
def AtkinSieve (limit):
results = [2,3,5]
sieve = [False]*limit
factor = int(math.sqrt(lim))
for i in range(1,factor):
for j in range(1, factor):
n = 4*i**2+j**2
if (n <= lim) and (n % 12 == 1 or n % 12 == 5):
sieve[n] = not sieve[n]
n = 3*i**2+j**2
if (n <= lim) and (n % 12 == 7):
sieve[n] = not sieve[n]
if i>j:
n = 3*i**2-j**2
if (n <= lim) and (n % 12 == 11):
sieve[n] = not sieve[n]
for index in range(5,factor):
if sieve[index]:
for jndex in range(index**2, limit, index**2):
sieve[jndex] = False
for index in range(7,limit):
if sieve[index]:
results.append(index)
return results
Например, когда я генерирую простые простые просты на пределе 1000, Sieve Atkin пропускается Prime 997, но включает в себя композит 965. Но если я генерирую до предела 5000, список его возврата, полностью правильно.
Решение
- Изменять
lim
кlimit
. Отказ Конечно, вы, должно быть, знали это. - С
sieve = [False]*limit
, самый большой индекс, допустимыйlimit-1
.Однако на этой линии
if (n <= limit) and (n % 12 == 1 or n % 12 == 5):
Вы проверяете, если
n<=limit
. Отказ Еслиn==limit
тогдаsieve[n]
поднимает индексэрмер. Попробуйте свой алгоритм с небольшим значениемlimit
(например, n = 50). Вы увидите эту ошибку. Простое исправление - использоватьsieve = [False]*(limit+1)
Легкое исправление немного расточительно, поскольку сито [0] никогда не используется. Так что вы могли бы подумать лучшее решение, чтобы сохранить
sieve = [False]*limit
, но исправьте все свой другой код, наступив индекс наsieve
вниз за другим. (Например, изменитьsieve[n]
кsieve[n-1]
Везде и т. Д.) Однако это заставит вас сделать ряд дополнительных вычитаний, которые не будут хорошими для скорости. Таким образом, простое / расточительное решение на самом деле, вероятно, лучший вариант. - Согласно с http://en.wikipedia.org/wiki/sieve_of_Atkin.X должен быть целым числом в [1, SQRT (LIMIT)], включительно в конечных точках.
В вашем коде
factor = int(math.sqrt(limit))
а также
int
берет пол изmath.sqrt(limit)
. Отказ Более того,range(1,factor)
Идет от 1 до фактора-1. Итак, вы выходите на 1.Так что вам нужно изменить это на
factor = int(math.sqrt(limit))+1
- Видеть Самый быстрый способ перечислить все простыни ниже n Для альтернативы (и быстрее) внедрения сита Аткина из-за Стива Кренель.
def AtkinSieve (limit):
results = [2,3,5]
sieve = [False]*(limit+1)
factor = int(math.sqrt(limit))+1
for i in range(1,factor):
for j in range(1, factor):
n = 4*i**2+j**2
if (n <= limit) and (n % 12 == 1 or n % 12 == 5):
sieve[n] = not sieve[n]
n = 3*i**2+j**2
if (n <= limit) and (n % 12 == 7):
sieve[n] = not sieve[n]
if i>j:
n = 3*i**2-j**2
if (n <= limit) and (n % 12 == 11):
sieve[n] = not sieve[n]
for index in range(5,factor):
if sieve[index]:
for jndex in range(index**2, limit, index**2):
sieve[jndex] = False
for index in range(7,limit):
if sieve[index]:
results.append(index)
return results