stringtranslate.com

Tamiz de Eratóstenes

Criba de Eratóstenes: pasos del algoritmo para números primos menores de 121 (incluida la optimización a partir del cuadrado del número primo).

En matemáticas , la criba de Eratóstenes es un antiguo algoritmo para encontrar todos los números primos hasta un límite dado.

Lo hace marcando iterativamente como compuestos (es decir, no primos) los múltiplos de cada primo, comenzando con el primer número primo, 2. Los múltiplos de un primo dado se generan como una secuencia de números comenzando desde ese primo, con una diferencia constante entre ellos que es igual a ese primo. [1] Esta es la distinción clave del tamiz con respecto al uso de la división de prueba para probar secuencialmente cada número candidato para la divisibilidad por cada primo. [2] Una vez que todos los múltiplos de cada primo descubierto se han marcado como compuestos, los números restantes sin marcar son primos.

La primera referencia conocida al tamiz ( griego antiguo : κόσκινον Ἐρατοσθένους , kóskinon Eratosthénous ) se encuentra en la Introducción a la aritmética de Nicómaco de Gerasa , [3] un libro de principios del siglo II d. C. que lo atribuye a Eratóstenes de Cirene , un matemático griego del siglo III a. C. , aunque describe el tamizado por números impares en lugar de primos. [4]

Uno de los muchos tamices de números primos , es una de las formas más eficientes de encontrar todos los primos más pequeños. Puede usarse para encontrar primos en progresiones aritméticas . [5]

Descripción general

Tamizar los dos y tamizar los tres:
la criba de Eratóstenes.
Cuando los múltiplos subliman,
los números que quedan son primos.

Anónimo [6]

Un número primo es un número natural que tiene exactamente dos divisores naturales distintos : el número 1 y él mismo.

Para encontrar todos los números primos menores o iguales a un entero dado n mediante el método de Eratóstenes:

  1. Crea una lista de números enteros consecutivos del 2 al n : (2, 3, 4, ..., n ) .
  2. Inicialmente, sea p igual a 2, el número primo más pequeño.
  3. Enumere los múltiplos de p contando en incrementos de p desde 2 p hasta n , y márquelos en la lista (estos serán 2 p , 3 p , 4 p , ... ; el p en sí no debe marcarse).
  4. Encuentre el número más pequeño de la lista que sea mayor que p y que no esté marcado. Si no existe tal número, deténgase. De lo contrario, suponga que p es ahora igual a este nuevo número (que es el siguiente primo) y repita desde el paso 3.
  5. Cuando el algoritmo termina, los números que quedan sin marcar en la lista son todos los primos menores que n .

La idea principal aquí es que cada valor dado a p será primo, porque si fuera compuesto se marcaría como múltiplo de algún otro primo más pequeño. Tenga en cuenta que algunos de los números pueden marcarse más de una vez (por ejemplo, 15 se marcará tanto para 3 como para 5).

Como refinamiento, es suficiente marcar los números en el paso 3 comenzando desde p 2 , ya que todos los múltiplos más pequeños de p ya habrán sido marcados en ese punto. Esto significa que el algoritmo puede terminar en el paso 4 cuando p 2 sea mayor que n . [1]

Otro refinamiento es listar inicialmente solo los números impares, (3, 5, ..., n ) y contar en incrementos de 2 p en el paso 3, marcando así solo los múltiplos impares de p . Esto en realidad aparece en el algoritmo original. [1] [4] Esto se puede generalizar con la factorización de rueda , formando la lista inicial solo a partir de números coprimos con los primeros primos y no solo a partir de impares (es decir, números coprimos con 2), y contando en los incrementos ajustados correspondientes de modo que solo se generen los múltiplos de p que son coprimos con esos primos pequeños, en primer lugar. [7]

Ejemplo

Para encontrar todos los números primos menores o iguales a 30, proceda de la siguiente manera.

Primero, genere una lista de números enteros del 2 al 30:

 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

El primer número de la lista es 2; tacha cada segundo número de la lista después del 2 contando hacia arriba desde 2 en incrementos de 2 (estos serán todos los múltiplos de 2 en la lista):

 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

El siguiente número en la lista después del 2 es 3; tacha cada tercer número en la lista después del 3 contando hacia arriba desde 3 en incrementos de 3 (estos serán todos los múltiplos de 3 en la lista):

 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

El siguiente número que aún no ha sido tachado en la lista después del 3 es el 5; tache cada quinto número en la lista después del 5 contando hacia arriba desde 5 en incrementos de 5 (es decir, todos los múltiplos de 5):

 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

El siguiente número que aún no está tachado en la lista después del 5 es el 7; el siguiente paso sería tachar cada séptimo número de la lista después del 7, pero todos ellos ya están tachados en este punto, ya que estos números (14, 21, 28) también son múltiplos de primos más pequeños porque 7 × 7 es mayor que 30. Los números que no están tachados en este punto de la lista son todos los números primos menores a 30:

 2 3 5 7 11 13 17 19 23 29

Algoritmo y variantes

Pseudocódigo

La criba de Eratóstenes se puede expresar en pseudocódigo , de la siguiente manera: [8] [9]

El algoritmo Criba de Eratóstenes tiene  como entrada : un entero n > 1. Salida : todos los números primos del 2 al n . Sea  A una matriz de valores booleanos , indexada por el entero s 2 a n , Inicialmente todo configurado como verdadero .  para  i = 2, 3, 4, ..., sin exceder n  hacer  si  A [ i ] es  verdadero  para  j = i 2 , i 2 + i , i 2 +2 i , i 2 +3 i , ..., sin exceder n hacer A  [  j ] : = falso  devuelve todos los i tales que A [ i ] sea  verdadero .

Este algoritmo produce todos los números primos no mayores que n . Incluye una optimización común, que consiste en comenzar a enumerar los múltiplos de cada primo i a partir de i 2. La complejidad temporal de este algoritmo es O ( n log log n ) , [9] siempre que la actualización de la matriz sea una operación O (1) , como suele ser el caso.

Tamiz segmentado

Como señala Sorenson, el problema con el tamiz de Eratóstenes no es el número de operaciones que realiza sino más bien sus requisitos de memoria. [9] Para un valor n grande , el rango de primos puede no caber en la memoria; peor aún, incluso para un valor n moderado , su uso de caché es altamente subóptimo. El algoritmo recorre toda la matriz A , sin exhibir casi ninguna localidad de referencia .

Una solución a estos problemas la ofrecen los tamices segmentados , en los que sólo se tamizan porciones del rango a la vez. [10] Estos se conocen desde la década de 1970 y funcionan de la siguiente manera: [9] [11]

  1. Divida el rango 2 a n en segmentos de algún tamaño Δ ≤ n .
  2. Encuentra los números primos en el primer segmento (es decir, el más bajo), utilizando la criba regular.
  3. Para cada uno de los siguientes segmentos, en orden creciente, siendo m el valor más alto del segmento, encuentre los primos en él de la siguiente manera:
    1. Configurar una matriz booleana de tamaño Δ .
    2. Marcar como no primos las posiciones en la matriz correspondientes a los múltiplos de cada primo pm encontrados hasta el momento, enumerando sus múltiplos en pasos de p comenzando desde el múltiplo de p más bajo entre m - Δ y m .
    3. Las posiciones restantes no marcadas en la matriz corresponden a los primos del segmento. No es necesario marcar ningún múltiplo de estos primos, porque todos estos primos son mayores que m , ya que para k ≥ 1 , se tiene .

Si se elige que Δ sea n , la complejidad espacial del algoritmo es O ( n ) , mientras que la complejidad temporal es la misma que la del tamiz regular. [9]

Para rangos con límite superior n tan grande que los primos de tamizado por debajo de n requeridos por el tamiz segmentado de páginas de Eratóstenes no caben en la memoria, se puede utilizar en su lugar un tamiz más lento pero mucho más eficiente en términos de espacio como el tamiz de primos pseudocuadrados, desarrollado por Jonathan P. Sorenson. [12]

Tamiz incremental

Una formulación incremental del tamiz [2] genera primos indefinidamente (es decir, sin un límite superior) al intercalar la generación de primos con la generación de sus múltiplos (de modo que los primos se puedan encontrar en los huecos entre los múltiplos), donde los múltiplos de cada primo p se generan directamente contando hacia arriba desde el cuadrado del primo en incrementos de p (o 2 p para primos impares). La generación debe iniciarse solo cuando se alcanza el cuadrado del primo, para evitar efectos adversos en la eficiencia. Puede expresarse simbólicamente bajo el paradigma del flujo de datos como

primos = [ 2 , 3 , ...] \ [[ p ², p ²+ p , ...] para p en primos ],

utilizando notación de comprensión de listas\ para denotar la resta de conjuntos de progresiones aritméticas de números.

Los primos también pueden producirse mediante el tamizado iterativo de los compuestos a través de pruebas de divisibilidad por primos secuenciales, un primo a la vez. No es el tamiz de Eratóstenes, pero a menudo se confunde con él, a pesar de que el tamiz de Eratóstenes genera directamente los compuestos en lugar de realizar pruebas para ellos. La división por tanteo tiene una complejidad teórica peor que la del tamiz de Eratóstenes a la hora de generar rangos de primos. [2]

Al probar cada primo, el algoritmo de división por tanteo óptimo utiliza todos los números primos que no excedan su raíz cuadrada, mientras que la criba de Eratóstenes produce cada compuesto a partir de sus factores primos únicamente y obtiene los primos "gratis" entre los compuestos. El código de criba funcional de 1975 de David Turner [13] se presenta a menudo como un ejemplo de la criba de Eratóstenes [7], pero en realidad es una criba de división por tanteo subóptima. [2]

Complejidad algorítmica

La criba de Eratóstenes es una forma popular de evaluar el rendimiento de las computadoras. [14] La complejidad temporal de calcular todos los primos por debajo de n en el modelo de máquina de acceso aleatorio es O ( n log log n ) operaciones, una consecuencia directa del hecho de que la serie armónica de primos se acerca asintóticamente a log log n . Sin embargo, tiene una complejidad temporal exponencial con respecto a la longitud de la entrada, lo que lo convierte en un algoritmo pseudopolinomial . El algoritmo básico requiere O ( n ) de memoria.

La complejidad de bits del algoritmo es O ( n (log n ) (log log n ) ) operaciones de bits con un requisito de memoria de O ( n ) . [15]

La versión segmentada de página implementada normalmente tiene la misma complejidad operativa de O ( n log log n ) que la versión no segmentada, pero reduce los requisitos de espacio al tamaño mínimo de la página de segmento más la memoria requerida para almacenar los primos base menores que la raíz cuadrada del rango utilizado para seleccionar compuestos de segmentos de página sucesivos de tamaño O (√n/registro n) ​​.

Una versión segmentada especial (raramente implementada, si es que alguna vez se implementa) del tamiz de Eratóstenes, con optimizaciones básicas, utiliza operaciones O ( n ) y O (nregistro registro n/registro n) bits de memoria. [16] [ 17] [18]

El uso de la notación O grande ignora los factores constantes y los desplazamientos que pueden ser muy significativos para los rangos prácticos: la criba de variación de Eratóstenes conocida como la criba de rueda de Pritchard [16] [17] [18] tiene un rendimiento de O ( n ) , pero su implementación básica requiere un algoritmo de "una gran matriz" que limita su rango utilizable a la cantidad de memoria disponible, de lo contrario, debe segmentarse en páginas para reducir el uso de memoria. Cuando se implementa con segmentación de páginas para ahorrar memoria, el algoritmo básico aún requiere aproximadamente O (norte/registro n) bits de memoria (mucho más que el requerimiento del tamiz segmentado de página básica de Eratóstenes usando O (√n/registro n) bits de memoria). El trabajo de Pritchard redujo el requerimiento de memoria a costa de un gran factor constante. Aunque el tamiz de rueda resultante tiene un rendimiento de O ( n ) y un requerimiento de memoria aceptable, no es más rápido que un tamiz básico de Eratóstenes con factor de rueda razonable para rangos de tamizado prácticos.

Tamiz de Euler

La prueba de Euler de la fórmula del producto zeta contiene una versión de la criba de Eratóstenes en la que cada número compuesto se elimina exactamente una vez. [9] La misma criba fue redescubierta y observada por Gries y Misra (1978) que toma tiempo lineal . [19] También comienza con una lista de números del 2 al n en orden. En cada paso, el primer elemento se identifica como el siguiente primo, se multiplica con cada elemento de la lista (empezando por sí mismo) y los resultados se marcan en la lista para su posterior eliminación. Luego, el elemento inicial y los elementos marcados se eliminan de la secuencia de trabajo y el proceso se repite:

 [2] (3) 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 ... [3] (5) 7 11 13 17 19 23 25 29 31 35 37 41 43 47 49 53 55 59 61 65 67 71 73 77 79 ... [4] (7) 11 13 17 19 23 29 31 37 41 43 47 49 53 59 61 67 71 73 77 79 ... [5] (11) 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 ... [...]

Aquí se muestra el ejemplo partiendo de los números impares, después del primer paso del algoritmo. Así, en el k- ésimo paso se eliminan de la lista todos los múltiplos restantes del k -ésimo primo, que a partir de entonces contendrá solo números coprimos con los primeros k primos (cf. factorización de rueda ), de modo que la lista comenzará con el primo siguiente y todos los números que se encuentren en ella por debajo del cuadrado de su primer elemento también serán primos.

Por lo tanto, al generar una secuencia acotada de números primos, cuando el siguiente número primo identificado excede la raíz cuadrada del límite superior, todos los números restantes en la lista son primos. [9] En el ejemplo dado anteriormente, esto se logra al identificar 11 como el siguiente número primo, lo que da una lista de todos los números primos menores o iguales a 80.

Téngase en cuenta que los números que se descartarán en un paso se siguen utilizando al marcar los múltiplos en ese paso, por ejemplo, para los múltiplos de 3 es 3 × 3 = 9 , 3 × 5 = 15 , 3 × 7 = 21 , 3 × 9 = 27 , ..., 3 × 15 = 45 , ..., por lo que se debe tener cuidado al tratar esto. [9]

Véase también

Referencias

  1. ^ abc Horsley, Rev. Samuel, FRS, " Κόσκινον Ερατοσθένους o El tamiz de Eratóstenes. Un relato de su método para encontrar todos los números primos", Philosophical Transactions (1683-1775), vol. 62. (1772), págs. 327–347.
  2. ^ abcd O'Neill, Melissa E., "The Genuine Sieve of Eratosthenes", Journal of Functional Programming , publicado en línea por Cambridge University Press el 9 de octubre de 2008 doi :10.1017/S0956796808007004, pp. 10, 11 (contiene dos tamices incrementales en Haskell: uno basado en colas de prioridad de O'Neill y uno basado en listas, de Richard Bird).
  3. ^ Hoche, Richard , ed. (1866), Nicomachi Geraseni Pythagorei Introducciónis arithmeticae libri II, capítulo XIII, 3, Leipzig: BG Teubner, p. 30
  4. ^ ab Nicomachus de Gerasa (1926), Introducción a la aritmética; traducido al inglés por Martin Luther D'Ooge; con estudios de aritmética griega de Frank Egleston Robbins y Louis Charles Karpinski, capítulo XIII, 3 , Nueva York: The Macmillan Company, pág. 204
  5. ^ JC Morehead, "Extensión de la criba de Eratóstenes a progresiones aritméticas y aplicaciones", Anales de Matemáticas, Segunda Serie 10:2 (1909), págs. 88-104.
  6. ^ Clocksin, William F., Christopher S. Mellish, Programación en Prolog , 1984, pág. 170. ISBN 3-540-11046-1
  7. ^ ab Runciman, Colin (1997). "Perla funcional: tamices de rueda perezosa y espirales de primos" (PDF) . Revista de programación funcional . 7 (2): 219–225. doi :10.1017/S0956796897002670. S2CID  2422563.
  8. ^ Sedgewick, Robert (1992). Algoritmos en C++ . Addison-Wesley. ISBN 978-0-201-51059-1., pág. 16.
  9. ^ abcdefgh Jonathan Sorenson, An Introduction to Prime Number Sieves, Computer Sciences Technical Report #909, Department of Computer Sciences University of Wisconsin-Madison, 2 de enero de 1990 (se muestra el uso de la optimización a partir de los cuadrados y, por lo tanto, utilizando solo los números cuyo cuadrado está por debajo del límite superior).
  10. ^ Crandall y Pomerance, Números primos: una perspectiva computacional , segunda edición, Springer: 2005, págs. 121–24.
  11. ^ Bays, Carter; Hudson, Richard H. (1977). "La criba segmentada de Eratóstenes y los números primos en progresiones aritméticas hasta 10 12 ". BIT . 17 (2): 121–127. doi :10.1007/BF01932283. S2CID  122592488.
  12. ^ J. Sorenson, "El tamiz primo de pseudocuadrados", Actas del 7º Simposio Internacional sobre Teoría Algorítmica de Números . (ANTS-VII, 2006).
  13. ^ Turner, David A. SASL language manual. Tech. rept. CS/75/1. Department of Computational Science, University of St. Andrews 1975. ( ). Pero véase también Peter Henderson, Morris, James Jr., A Lazy Evaluator, 1976, donde encontramos lo siguiente, atribuido a P. Quarendon: ; la prioridad no está clara.primes = sieve [2..]; sieve (p:nos) = p:sieve (remove (multsof p) nos); remove m = filter (not . m); multsof p n = rem n p==0primeswrt[x;l] = if car[l] mod x=0 then primeswrt[x;cdr[l]] else cons[car[l];primeswrt[x;cdr[l]]] ; primes[l] = cons[car[l];primes[primeswrt[car[l];cdr[l]]]] ; primes[integers[2]]
  14. ^ Peng, TA (otoño de 1985). "Un millón de números primos a través del tamiz". BYTE . págs. 243–244 . Consultado el 19 de marzo de 2016 .
  15. ^ Pritchard, Paul, "Tamices lineales de números primos: un árbol genealógico", Sci. Comput. Programming 9 :1 (1987), págs. 17–35.
  16. ^ de Paul Pritchard, "Un tamiz aditivo sublineal para encontrar números primos", Communications of the ACM 24 (1981), 18-23. MR 600730
  17. ^ de Paul Pritchard, Explicación del tamiz de rueda, Acta Informatica 17 (1982), 477–485. MR 685983
  18. ^ de Paul Pritchard, "Tamices de números primos compactos y rápidos" (entre otros), Journal of Algorithms 4 (1983), 332–344. MR 729229
  19. ^ Gries, David ; Misra, Jayadev (diciembre de 1978), "Un algoritmo de tamiz lineal para encontrar números primos" (PDF) , Communications of the ACM , 21 (12): 999–1003, doi :10.1145/359657.359660, hdl : 1813/6407 , S2CID  11990373.

Enlaces externos