Wikipedia article tiene una explicación:
- "El algoritmo ignora por completo cualquier número divisible por dos, tres o cinco Todos los números con una aún módulo-sesenta resto son divisible por dos y no. primo. Todos los números con módulo-sesenta restantes divisibles por tres también son divisibles por tres y no primos. Todos los números con módulo-sesenta restantes divisibles por cinco son divisibles por cinco y no primos. Todos estos residuos se ignoran.
Vamos a empezar con el famoso
primes = sieve [2..] = sieve (2:[3..])
-- primes are sieve of list of 2,3,4... , i.e. 2 prepended to 3,4,5...
sieve (x:xs) = x : sieve [y | y <- xs, rem y x /= 0] -- set notation
-- sieve of list of (x prepended to xs) is x prepended to the sieve of
-- list of `y`s where y is drawn from xs and y % x /= 0
Vamos a ver cómo se procede por unos primeros pasos:
primes = sieve [2..] = sieve (2:[3..])
= 2 : sieve p2 -- list starting w/ 2, the rest is (sieve p2)
p2 = [y | y <- [3..], rem y 2 /= 0] -- for y from 3 step 1: if y%2 /= 0: yield y
p2
es que no contienen múltiplos de .IOW solo contendrá los números coprime con — sin número en p2
tiene como factor. Para encontrar p2
que en realidad no necesitamos probar dividir por 2 cada número en [3..]
(que es y arriba, 3,4,5,6,7, ...), ya que podemos enumerar todas los múltiplos de de antelación:
rem y 2 /= 0 === not (ordElem y [2,4..]) -- "y is not one of 2,4,6,8,10,..."
ordElem
es como elem
(es decir es elemento prueba), sólo asume que la lista de parámetros es una ordenada, aumentando la lista de los números, por lo que puede detectar la falta de presencia afely así como la presencia:
ordElem y xs = take 1 (dropWhile (< y) xs) == [y] -- = elem y (takeWhile (<= y) xs)
La ordinaria elem
no asume nada, así que hay que inspeccionar cada elemento de su argumento de la lista, por lo que no puede manejar listas infinitas. ordElem
puede. Así, pues,
p2 = [y | y <- [3..], not (ordElem y [2,4..])] -- abstract this as a function `diff`:
= diff [3..] [2,4..] -- diff ys xs = [y | y <- ys, not (ordElem y xs)]
-- 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
-- . 4 . 6 . 8 . 10 . 12 . 14 . 16 . 18 . 20 . 22 .
= diff [3..] (map (2*) [2..]) -- y > 2, so [4,6..] is enough
= diff [2*k+x | k <- [0..], x <- [3,4]] -- "for k from 0 step 1: for x in [3,4]:
[2*k+x | k <- [0..], x <- [ 4]] -- yield (2*k+x)"
= [ 2*k+x | k <- [0..], x <- [3 ]] -- 2 = 1*2 = 2*1
= [3,5..] -- that's 3,5,7,9,11,...
p2
es sólo una lista de todos los pronósticos anterior . Bueno, sabíamos que. ¿Qué pasa con el siguiente paso?
sieve p2 = sieve [3,5..] = sieve (3:[5,7..])
= 3 : sieve p3
p3 = [y | y <- [5,7..], rem y 3 /= 0]
= [y | y <- [5,7..], not (ordElem y [3,6..])] -- 3,6,9,12,...
= diff [5,7..] [6,9..] -- but, we've already removed the multiples of 2, (!)
-- 5 . 7 . 9 . 11 . 13 . 15 . 17 . 19 . 21 . 23 . 25 . 27 .
-- . 6 . . 9 . . 12 . . 15 . . 18 . . 21 . . 24 . . 27 .
= diff [5,7..] (map (3*) [3,5..]) -- so, [9,15..] is enough
= diff [2*k+x | k <- [0..], x <- [5]] (map (3*)
[2*k+x | k <- [0..], x <- [3]])
= diff [6*k+x | k <- [0..], x <- [5,7,9]] -- 6 = 2*3 = 3*2
[6*k+x | k <- [0..], x <- [ 9]]
= [ 6*k+x | k <- [0..], x <- [5,7 ]] -- 5,7,11,13,17,19,...
y el siguiente,
sieve p3 = sieve (5 : [6*k+x | k <- [0..], x <- [7,11]])
= 5 : sieve p5
p5 = [y | y <- [6*k+x | k <- [0..], x <- [7,11]], rem y 5 /= 0]
= diff [ 6*k+x | k <- [0..], x <- [7,11]] (map (5*)
[ 6*k+x | k <- [0..], x <- [5, 7]] ) -- no mults of 2 or 3!
= diff [30*k+x | k <- [0..], x <- [7,11,13,17,19,23,25,29,31,35]] -- 30 = 6*5 = 5*6
[30*k+x | k <- [0..], x <- [ 25, 35]]
= [ 30*k+x | k <- [0..], x <- [7,11,13,17,19,23, 29,31 ]]
Esta es la secuencia con la que el tamiz de Atkin está funcionando. No hay presentes múltiplos de 2, 3 o . Atkin y Bernstein trabajan módulo 60, es decir que el doble de la gama:
p60 = [ 60*k+x | k <- [0..], x <- [1, 7,11,13,17,19,23,29,31, 37,41,43,47,49,53,59]]
A continuación, utilizan algunos teoremas sofisticados conocer algunas propiedades de cada uno de esos números y hacer frente a cada uno en consecuencia. Todo se repite (a la la "rueda") con un período de .
- "todos los números n con el módulo-sesenta resto 1, 13, 17, 29, 37, 41, 49, o 53 (...) son primo si y sólo si el número de soluciones que se
4x^2 + y^2 = n
impar y el número es cuadrado libre. "
¿Qué significa eso? Si sabemos que el número de soluciones para esa ecuación es impar para dicho número, entonces es primordial si es libre de cuadrados. Eso significa que no tiene factores repetidos (como 49, 121,, etc.).
Atkin y Bernstein utilizan esto para reducir el número de operaciones en general: para cada primo (de y más), enumeramos (y la marca para la eliminación) los múltiplos de su plaza, por lo que son mucho más lejos aparte de en el tamiz de Eratóstenes, por lo que hay menos de ellos en un rango determinado.
El resto de las reglas son:
"Todos los números n con el módulo-sesenta resto 7, 19, 31, o 43 (...) son primo si y sólo si el número de las soluciones a 3x^2 + y^2 = n
son impares y el número es libre de cuadrados. "
"Todos los números n con el módulo-sesenta resto 11, 23, 47, o 59 (...) son primo si y sólo si el número de soluciones que 3x^2 − y^2 = n
es impar y el número es sin cuadrados."
Este se encarga de todos los números de núcleo 16 en la definición de p60
.
ver también: Which is the fastest algorithm to find prime numbers?
El tiempo de complejidad de la criba de Eratóstenes en números primos producir hasta N es O (N log log N), mientras que la del tamiz de Atkin es O (N) (dejando de lado las optimizaciones adicionales log log N
que no se escalan bien). Sin embargo, la sabiduría aceptada es que los factores constantes en el tamiz de Atkin son mucho más altos y, por lo tanto, solo pueden pagar muy por encima de los números de 32 bits (N> 2), if at all.
Esto se parece mucho a una pregunta de la universidad ... – Spence
o una pregunta del Proyecto Euler –
relacionado: http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n -in-python – jfs