Wikipedia article a une explication:
- « L'algorithme ne tient aucun compte des nombres divisibles par deux, trois ou cinq Tous les numéros avec un même reste modulo soixante sont divisible par deux et non. Tous les nombres avec modulo-soixante reste divisible par trois sont également divisibles par trois et non premiers Tous les nombres avec modulo-soixante reste divisible par cinq sont divisibles par cinq et non premier Tous ces restes sont ignorés. "
Commençons par la célèbre
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
Voyons voir comment il procède pour quelques premiers pas:
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
doit contenir aucun multiple de .IOW il ne contiendra que des nombres coprime avec — aucun numéro dans p2
a comme son facteur. Pour trouver p2
nous ne devons pas vraiment tester diviser par 2 chaque numéro dans [3..]
(c'est et plus, 3,4,5,6,7, ...), parce que nous pouvons énumérer tous les multiples de à l'avance:
rem y 2 /= 0 === not (ordElem y [2,4..]) -- "y is not one of 2,4,6,8,10,..."
ordElem
est comme elem
(c.-à-est-élément test), il suffit suppose que son argument de liste est une ordonnée, liste croissante de nombres, de sorte qu'il peut détecter la non-présence s afely ainsi que la présence:
ordElem y xs = take 1 (dropWhile (< y) xs) == [y] -- = elem y (takeWhile (<= y) xs)
Le elem
ordinaire ne suppose rien, donc il faut inspecter chaque élément de son argument de liste, ne peut pas gérer des listes infinies. ordElem
peut. Ainsi donc,
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
est juste une liste de toutes les chances ci-dessus . Eh bien, nous savions que. Qu'en est-il de la prochaine étape?
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,...
Et l'autre,
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 ]]
C'est la séquence avec laquelle le tamis de Atkin travaille. Aucun multiple de 2, 3 ou sont présents dans celui-ci. Atkin et Bernstein travaillent modulo , à savoir qu'ils doublent la gamme:
p60 = [ 60*k+x | k <- [0..], x <- [1, 7,11,13,17,19,23,29,31, 37,41,43,47,49,53,59]]
Ensuite, ils utilisent des théorèmes sophistiqués pour connaître quelques propriétés de chacun de ces nombres et traiter chacun en conséquence. Le tout est répété (a-la la "roue") avec une période de .
- « Tous les numéros de n avec modulo soixante reste 1, 13, 17, 29, 37, 41, 49, ou 53 (...) sont premiers si et seulement si le nombre de solutions à
4x^2 + y^2 = n
est impair et le nombre est squarefree. "
Qu'est-ce que cela signifie? Si nous savons que le nombre de solutions à cette équation est impair pour un tel nombre, alors il est premier si il est squarefree. Cela signifie qu'il n'a pas de facteurs répétés (comme 49, 121, etc).
Atkin et Bernstein utilisent pour réduire le nombre d'opérations d'ensemble: pour chaque prime (de et plus), nous énumérons (et la marque pour l'enlèvement) les multiples de sa place, donc ils sont beaucoup plus à part dans le tamis d'Ératosthène, il y en a moins dans une gamme donnée.
Le reste des règles sont:
« Tous les numéros n modulo soixante reste 7, 19, 31 ou 43 (...) sont premiers si et seulement si le nombre de solutions à 3x^2 + y^2 = n
est impair et le nombre est squarefree. "
« Tous les numéros n modulo soixante reste 11, 23, 47 ou 59 (...) sont premiers si et seulement si le nombre de solutions à 3x^2 − y^2 = n
est impair et le nombre est quadratfrei. »
Cela prend soin de tous les 16 numéros de base dans la définition de p60
.
voir aussi: Which is the fastest algorithm to find prime numbers?
La complexité temporelle du tamis d'Eratosthène en produisant des nombres premiers jusqu'à N est O (N log log N), tandis que celle du tamis de Atkin est O (N) (en mettant de côté les optimisations supplémentaires log log N
qui ne sont pas bien à l'échelle). La sagesse acceptée cependant est que les facteurs constants dans le tamis d'Atkin sont beaucoup plus élevés et donc il pourrait seulement payer haut au-dessus des nombres de 32 bits (N> 2), if at all.
Cela ressemble beaucoup à une question universitaire ... – Spence
ou une question de projet Euler –
connexes: http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n -in-python – jfs