Vous êtes sur la page 1sur 10

Criba de Eratstenes: Cmo colar nmeros primos.

Implementacin en Java y VBA para Excel.

Walter Mora F.
Escuela de Matemtica
Instituto Tecnolgico de Costa Rica
wmora2@yahoo.com.mx

Resumen:La Criba de Eratstenes es un algoritmo que permite hallar todos los nmeros
primos menores que un nmero natural dado n eliminando los nmeros compuestos de
la lista {2, 3, ..., n}. Es simple y razonablemente eficiente. En este trabajo se presenta un
algoritmo (explicado en detalle) y la respectiva implementacin. Al final se explica como
manejar la memoria para el caso de nmeros grandes.
Palabras claves: Nmeros primos, algoritmo, criba de Eratstenes.

Introduccin

La criba1 de Eratstenes es un algoritmo que permite colar todos los nmeros primos
menores que un nmero natural dado n, eliminando los nmeros compuestos de la lista
{2, ..., n}. Es simple y razonablemente eficiente.

1 Criba, tamiz y zaranda son sinnimos.

Una criba es un herramienta que consiste de un cedazo usada para limpiar


el trigo u otras semillas, de impurezas. Esta accin de limpiar se le dice cribar o tamizar.

Primero tomamos una lista de nmeros {2, 3, ..., n} y eliminamos de la lista los mltiplos de 2. Luego tomamos el primer entero despus de 2 que no fue borrado (el 3 ) y
eliminamos de la lista sus mltiplos, y as sucesivamente. Los nmeros que permanecen
en la lista son los primos {2, 3, 5, 7, ...}.
Recordemos que un nmero n o es primo o es divisible por un primo

n.

+
Lema
1.1 Si n Z admite la factorizacin n = ab, con a, b Z entonces a
b n.

Prueba. Por contradiccin, si a >


por hiptesis, no es cierto.

n y b>

n entonces ab >

n o


n n = n lo cual,

Del lema anterior se puede deducir que


Si n es un nmero compuesto entonces uno de sus factores d cumple 1 d
Si n no tiene factores d con 1 < d

n , entonces n es primo.

Por lo tanto, si un nmero en el conjunto {2, 3, ..., n}no es divisible por un primo n
entonces es primo. En lo que sigue en vez de usar d n usamos la expresin equivalente
(en este contexto) d 2 n.

EJEMPLO 1.1

Encontrar los primos menores que 30. El proceso termina cuando el cuadrado del mayor
nmero confirmado como primo es < 30.
La lista es
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
2 es primo, eliminamos todos los mltiplos de 2. La lista actualizada es
2 3
19

5
21

7
23

9
25

11
27

13
29

15

17

El siguiente nmero (despus del 2 ) es el 3. Como 32 < 30, las cosas no terminan aqu.
Eliminamos los mltiplos de 3.
La lista actualizada es
2 Criba de Eratstenes: Cmo colar nmeros primos. Java y VBA.. Walter Mora F.
c 2008 Revista digital Matemtica, Educacin e Internet (www.cidse.itcr.ac.cr)
Derechos Reservados

2 3 5
19

7
23

11
25

13
29

17

El siguiente nmero (despus del 3 ) es el 5. Como 52 < 30, las cosas no terminan aqu.
Eliminamos los mltiplos de 5.
La lista actualizada es
2 3 5
19

7
23

11

13
29

17

El siguiente nmero (despus del 5 ) es el 7. Como 72 > 30, El proceso termin.

Los mltiplos del k simo primo pk se eliminan desde p2k en adelante. Esto es as
pues cuando llegamos a pk ya se han eliminado 2 pk , 3 pk , ..., pk1 pk . Por ejemplo,
cuando llegamos al primo 7, ya se han eliminado los mltiplos de 2, 3 y 5, es decir, ya se
han eliminado 2 7, 3 7, 4 7, 5 7 y 6 7. Por eso iniciamos en 72 .
Hasta aqu, la implementacin podra hacerse con un arreglo booleano de tamao n. El
cdigo Java sera
int n = 100000000;
boolean[] esPrimo = new boolean[n + 1];
for (int i = 2; i <= n; i++)
esPrimo[i] = true;
for (int i = 2; i*i <= n; i++)
{
if (esPrimo[i])
{
for (int j = i; i*j <= n; j++)
esPrimo[i*j] = false;
}
}

Como los pares no son primos (excepto 2 ), solo analizamos los nmeros impares 2

n3
2i + 3 : i = 0, 1, ...
= {3, 5, 7, 9, ...}
2
Por cada primo p = 2i + 3 (tal que p2 < n ), debemos eliminar los mltiplos impares de
p menores que n, a saber
(2k + 1)p = (2k + 1)(2i + 3), k = i + 1, i + 2, ...

2 Si

n = 2k + 1 es impar,

n3
n3
= k 1 N. Si n = 2k es par,
= k2
2
2

Revista Digital Matemtica, Educacin e Internet (www.itcr.ac.cr/revistamate/) Vol 7, N2, 2006.

Observe que si k = i + 1 entonces el primer mltiplo en ser eliminado es


p2 = (2i + 3)(2i + 3)
Esto nos dice que para implementar el algoritmo solo necesitamos un arreglo (booleano)
de tamao (n-3)/23 . El arreglo lo llamamos EsPrimo[i], i=0,1,...,(n-3)/2.
Cada entrada del arreglo EsPrimo[i] indica si el nmero 2i + 3 es primo o no. As, si el
nmero s = 2i + 3 es primo entonces EsPrimo[(s-3)/2]=true. Por tanto, lo nico que
debemos hacer es inicializar el arreglo con todos sus valores en true y luego asignar el valor
false a las entradas que representan a los nmeros (2k + 1)(2i + 3), k = i + 1, i + 2, ... es
decir, debemos hacer la asignacin
EsPrimo[((2k+1)(2i+3) - 3)/2] = false

1.0.1

Algoritmo e Implementacin.

Algoritmo 1.1: Criba de Eratstenes


Entrada: n N
Salida: Primos entre 2 y n
1 max = [ (n 3)/2 ] ;
2 boolean esPrimo[i], i = 1, 2, ...,max;
3 for j = 1, 2, ..., max do
4
esPrimo[ j] =True;
5
6
7
8
9
10

i = 0;
while (2i + 3)(2i + 3) n do
k = i+1;
while (2k + 1)(2i + 3) n do
esPrimo[((2k + 1)(2i + 3) 3)/2] =False;
k = k + 1;
i = i + 1;

11
12
13
14
15

Imprimir;
for j = 1, 2, ..., max do
if esPrimo[ j] =True then
Imprima j

1.0.1.1 Implementacin en Java. Vamos a implementar una clase que recibe el


nmero natural n > 2 y devuelve un vector con los nmeros primos n. Para colar los
nmeros compuestos usamos un arreglo

3 En

Java esta divisin es entera

Criba de Eratstenes: Cmo colar nmeros primos. Java y VBA.. Walter Mora F.
c 2008 Revista digital Matemtica, Educacin e Internet (www.cidse.itcr.ac.cr)
Derechos Reservados

boolean [] esPrimo = new boolean[(n-3)/2].


Al final llenamos un vector con los primos que quedan.
import java.util.Vector;
public class cribaEratostenes
{
//constructor
cribaEratostenes(){ }
//m\etodo que calcula la lista
Vector HacerlistaPrimos(int n)
{
Vector
salida = new Vector(1);
int k
= 1;
int max = (n-3)/2;
boolean[]
esPrimo = new boolean[max+1];
for(int i = 0; i <= max; i++)
esPrimo[i]=true;
for(int i = 0; (2*i+3)*(2*i+3) <= n; i++)
{
k = i+1;
while( ((2*k+1)*(2*i+3)) <= n)
{
esPrimo[((2*k+1)*(2*i+3)-3)/2]=false;
k++;
}
}
salida.addElement(new Integer(2));
for(int i = 0; i <=max; i++)
{ if(esPrimo[i])
salida.addElement(new Integer(2*i+3));
}
salida.trimToSize();
return salida;
}
//C\omo usar esta clase?
public static void main(String[] args)
{
int n = 100;
Vector lista_de_primos;
cribaEratostenes criba = new cribaEratostenes();
//usar el metodo HacerlistaPrimos

Revista Digital Matemtica, Educacin e Internet (www.itcr.ac.cr/revistamate/) Vol 7, N2, 2006.

lista_de_primos = criba.HacerlistaPrimos(n);
//Cantidad de primos <= n
System.out.println("Primos <="+ n+": "+lista_de_primos.size()+"\n");
//imprimir vector (lista de primos)
for(int p = 1; p < lista_de_primos.size(); p++)
{
Integer num = (Integer)lista_de_primos.elementAt(p);
System.out.println(""+(int)num.intValue());
}
}
}

1.0.1.2 Uso de la memoria En teora, los arreglos pueden tener tamao mximo
Integer.MAX_INT = 231 1 = 2 147 483 647 (pensemos tambin en la posibilidad de un
arreglo multidimensional!). Pero en la prctica, el mximo tamao del array depende del
hardware de la computadora. El sistema le asigna una cantidad de memoria a cada aplicacin; para valores grandes de n puede pasar que se nos agote la memoria (veremos el
mensaje OutOfMemory Error). Podemos asignar una cantidad de memoria apropiada
para el programa cribaEratostenes.java desde la lnea de comandos, si n es muy grande.
Por ejemplo, para calcular los primos menores que n = 100 000 000, se puede usar la
instruccin
C:\usrdir> java -Xmx1000m -Xms1000m cribaEratostenes
suponiendo que el archivo cribaEratostenes.java se encuentra en C:\usrdir.
Esta instruccin asigna al programa una memoria inicial (Xmx) de 1000 MB y una
memoria mxima (Xms) de 1000 MB (siempre y cuando existan tales recursos de memoria
en nuestro sistema).
En todo caso hay que tener en cuenta los siguientes datos

n
Primos <= n
-------------------------------------10
4
100
25
1 000
168
10 000
1 229
100 000
9 592
1 000 000
78 498
10 000 000
664 579
100 000 000
5 761 455
1 000 000 000
50 847 534

10
100
1 000
10 000

000
000
000
000

000
000
000
000

000
000
000
000

455 052 511


4 118 054 813
37 607 912 018
346 065 536 839

1.0.2 Implementacin en VBA para Excel.


Vamos a hacer un cuaderno como el de la figura 1.1.

Figura 1.1 Cuaderno de Excel

El cdigo VBA sera


Private Sub CommandButton1_Click()
Call ERATOSTENES
End Sub

Sub
Dim
Dim
Dim

ERATOSTENES()
n, p, k, j, pos, cols, fila, col
max As Integer
esPrimo() As Boolean

Call limpiaCeldas(7, 1, 1, 10)


n = Cells(2, 3)
max = Round((n - 3) / 2)
ReDim esPrimo(max + 1)
For i = 1 To max
esPrimo(i) = True
Next i
j = 0

Revista Digital Matemtica, Educacin e Internet (www.itcr.ac.cr/revistamate/) Vol 7, N2, 2006.

While (2 * j + 3) * (2 * j + 3) <= n
k = j + 1
While (2 * k + 1) * (2 * j + 3) <= n
pos = Round(((2 * k + 1) * (2 * j + 3) - 3) / 2)
esPrimo(pos) = False
k = k + 1
Wend
j = j + 1
Wend
Imprimir
Cells(5, 1) = 2
Cells(6, 1) = 3
fila = 7
col = 1
For i = 1 To max
If esPrimo(i) Then
Cells(fila, col) = 2 * i + 3
col = col + 1
If col = 10 Then cambio de fila
fila = fila + 1
col = 1
End If
End If
Next i

End Sub

limpia celdas
f
= fila en que inicia la limpieza
cini
= columna en inicia la limpieza
ccontrol = columna ms larga
nc
= nmero de columnas a borrar desde cini inclusive
Private Sub limpiaCeldas(f, cini, ccontrol, nc)
k = 0
While LenB(Cells(f + k, ccontrol)) <> 0 por rapidez!
For j = 0 To nc
Cells(f + k, cini + j) = ""
Next j
k = k + 1
Wend
End Sub

1.0.3

Primos entre m y n.

Para encontrartodos los primos entre m y n (con m < n ), eliminamos los mltiplos de
los primos nque estn entre m y n. Para hacer esto notemos que si p es un nmero
primo inferior a n y si pq es el primer mltiplo de p mayor o igual a m 1, entonces
como m 1 = pq + r (con 0 r < p ), tenemos que m 1 r + p = p(q + 1) es el primer
mltiplo de p que supera a m. Luego m 1 r + kp = p(q + k) es el ksimo mltiplo
de p que supera a m.
En resumen, los mltiplos de p ms grandes que m son
m 1 r + p, m 1 r + 2p, m 1 r + 3p, ...
siendo m 1 = pq + r con 0 r < p.

EJEMPLO 1.2

Para encontrar los


primos entre m = 10 y n = 30, debemos eliminar los mltiplos
de los primos 30 5. Es decir, los mltiplos de los primos p = 2, 3, 5.

Como 10 1 = 2 4 + 1, el 2 elimina elimina los nmeros m 1 r + kp = 8 + 2k,


es decir {10, 12, ..., 30}
Como 10 1 = 3 3 + 0, el 3 elimina los nmeros m 1 r + kp = 9 + 3k, es decir
{12, 15, 18, 21, 24, 27, 30}
Como 10 1 = 5 1 + 4, el 5 elimina los nmeros m 1 r + kp = 5 + 5k, es decir
{10, 15, 20, 25.}
Finalmente nos quedan los primos 11, 13, 17, 19, 23, 29.

1.0.3.1 Algoritmo. El algoritmo que se presenta es una versin ms bien cruda. En


los ejercicios se pide una implementacin ms eficiente.
Usamos un arreglo esPrimo de tamao n m + 1. Si esPrimo[j]=True entonces m + j es un primo en la lista. Con las restricciones impuestas en el ciclo while,
1 r + k pi {0, 1, ..., n m} as que podemos declarar esPrimo[-1-r+k pi]=False
para colar los primos.

10

Revista Digital Matemtica, Educacin e Internet (www.itcr.ac.cr/revistamate/) Vol 7, N2, 2006.

Algoritmo 1.2: Colado de primos entre m y n.


Entrada: n, m N con m < n.
Salida: Primos entre m y n

1 Primos = una lista de primos


n;
2 for j = 0, 1, ..., n m do
3
esPrimo[ j] =True;
4
5
6
7
8
9
10
11
12
13
14
15
16

np = cantidad de primos en la lista Primos;


for i = 1, 2, ..., np do
k = 1;
r = residuo(m 1, Primos[i]) ;
if m 1 r = 0 then
k = 2;
while m 1 r + kp n do
esPrimo[1 r + k Primos[i]] = False;
k = k + 1;
Imprimir;
for j = 0, 1, ..., n m do
if esPrimo[ j] =True then
Imprima j + m

Para que la criba opere entre m y n necesitamos tener un arreglo con todos los primos

n . Observe adems que podemos obviar los pares y trabajar con arreglos ms pequeos
de solo impares.
Observe que si m 1 r = 0 debemos empezar a eliminar con k = 2. Tambin
podemos empezar a eliminar desde p2 si m p2 n, para esto debemos iniciar en
k = (1 m + p2 + r)/p pues con este valor de k, m 1 r + kp = p2 .

REFERENCIAS
[Childs95]

Lindsay N. Childs. A Concrete Introduction to Higher Algebra. Springer-Verlag


New York, 1995.

[Riesel94]

Hans Riesel. Prime Numbers and Computer Methods for Factorization. Springer;
2 edition. 1994.

[Ribenboim95]

Paulo Ribenboim. The New Book of Prime Number Records. 3rd ed. Springer.
1995.

[Sedgewick08]

R. Sedgewick, K. Wayne. Introduction to Programming in Java. An Interdisciplinary Approach. Addison-Wiley. 2008.

Criba de Eratstenes: Cmo colar nmeros primos. Java y VBA.. Walter Mora F.
c 2008 Revista digital Matemtica, Educacin e Internet (www.cidse.itcr.ac.cr)
Derechos Reservados