Discussion:
Número de números primos entre 1000 y 3000
(demasiado antiguo para responder)
Jorge S. de Lis
2006-07-20 12:54:33 UTC
Permalink
Necesito ayuda.

Me parece un intervalo demasiado exagerado como para probarlos uno a uno.
¿Alguien conoce alguna regla que me permita saberlo? (sólo el número, no
cuáles son).

Por si acaso, empiezo ya probando con el 1000...

Muchas gracias :-)
Sergio
2006-07-20 14:06:56 UTC
Permalink
On Thu, 20 Jul 2006 14:54:33 +0200, "Jorge S. de Lis"
Post by Jorge S. de Lis
Necesito ayuda.
Me parece un intervalo demasiado exagerado como para probarlos uno a uno.
¿Alguien conoce alguna regla que me permita saberlo? (sólo el número, no
cuáles son).
Me temo que no, que nadie la conoce :-)

A priori, el número de primos comprendido entre dos enteros m y n
es bastante imprevisible. La única aproximación factible es, ni más
ni menos, que contarlos. Ahora bien, como has accedido a enviar
un mensaje a este newsgroup, doy por supuesto que tienes acceso
a un ordenador digital. En tal caso, contar los números primos
entre 1000 y 3000 es sencillo, en cualquier lenguaje de programación
de alto nivel se hace un programa para ello en dos patadas.

Puede haber mejores o peores algoritmos, si bien, si sólo pretendemos
llegar a un número tan pequeño como 3000, la aproximación más
trivial es perfectamente válida y en cualquier computador
contemporáneo tardará un tiempo muy breve: basta iterar sobre todos
los números entre 1000 y 3000 y, para cada uno de ellos, tratar de
dividirlo por todos los enteros entre 2 y la raíz cuadrada del número.
Si hallamos un divisor, no es primo.

Una mejora obvia es ir almacenando una lista de los primos que
vamos encontrando y tratar de dividir los nuevos candidatos
solamente entre los números primos menores que él. Si es divisible por
algún número distinto de sí mismo y la unidad que no sea primo,
también será divisible por los factores primos de dicho número, de
modo que no tiene sentido intentarlo con números compuestos salvo
por simplicidad y rapidez de implementación del algoritmo ( un momento
versus un poquito más). También se puede aplicar un procedimiento
de criba de eratóstenes, para determinar todos los primos que deseas,
o como paso inicial para un cierto subconjunto inicial de los
candidatos, cosa que eliminará muchas divisiones inútiles.

Ahora bien, aunque no conocemos ninguna forma de determinar cuántos
primos existen en un pequeño intervalo numérico, sí sabemos cómo se
comporta el número de primos cuando vamos considerando intervalos
mayores, donde las irregularidades de la frecuencia de primos en los
sucesivos tramos se van compensando en favor de una tendencia general.
Como seguramente sabes, se suele llamar pi a la función que , para
cada n, nos da el número de primos menor o igual que n. Se tiene que
pi(n) es aproximadamente n / ln n, y, notablemente, que el límite
cuando n tiende a infinito de pi (n) / ( n / ln n) es 1 ( de la Vallèe
Poussin y Hadamard, 1896). Una aproximación aún mejor a la
función pi que nos permite estimar el número de primos en un tramo
es 1 + SUMA en k, k=1, infinito ( 1 / ( k zeta(k+1) * (log n)^k / k!
),
con zeta representando la función zeta de Riemann.

Espero que eso ayude. Si no sueles programar y quieres, coméntalo
y te escribo aquí un programilla diminuto en C que cuenta el número
de primos, como te digo es brevísimo.

Saludos, S.
gamo
2006-07-20 14:24:53 UTC
Permalink
Post by Sergio
Espero que eso ayude. Si no sueles programar y quieres, coméntalo
y te escribo aquí un programilla diminuto en C que cuenta el número
de primos, como te digo es brevísimo.
Saludos, S.
Venga ese programa para animar el grupo.
Saludos
--
http://www.telecable.es/personales/gamo/
perl -e 'print 111_111_111**2,"\n";'
Sergio
2006-07-20 19:58:54 UTC
Permalink
Post by gamo
Venga ese programa para animar el grupo.
Saludos
No creo que con cosa tan trivial pueda animar el grupo, pero bueno,
así, "su due piedi", que dicen por las Italias, me puede salir,
implementando el algoritmo más burro posible, algo como lo siguiente:

Mirando uno a uno cada número y viendo si tiene divisores menores que
él, aparte del 1:

#include <stdio.h>
#define HASTA 1000

int main (void)
{
int i, j, esprimo, numerodeprimos;
numerodeprimos=0;
for (i=2; i<=HASTA; i++)
{
esprimo=1; /* en principio, sí es primo (in dubbio pro reo) */
for (j=2; j<i; j++)
if ( i%j==0)
esprimo=0;
if (esprimo==1)
numerodeprimos++;
}
printf ("\nEl número de primos entre 2 y %d es %d.\n", HASTA,
numerodeprimos);


return 0;
}


Haciendo una criba de Eratóstenes, pero también a lo bruto, "tachamos"
(electrónicamente, en una matriz donde 0 es NO ES PRIMO, 1, es SÍ ES
PRIMO), todos los múltiplos de 2, 3,... hasta el número deseado:

#include <stdio.h>
#define HASTA 1000

int main (void)
{
int esprimo[HASTA+1];
int i, j, numerodeprimos;

for (i=1; i<=HASTA; i++)
esprimo[i]=1; /* de nuevo in dubbio pro reo */
for (i=2; i<=HASTA; i++)
{
for (j=i*2; j<=HASTA; j+=i)
esprimo[j]=0;
}
numerodeprimos=0;
for (i=2; i<=HASTA; i++)
if (esprimo[i]==1)
numerodeprimos++;
printf ("\nEl número de primos entre 2 y %d es %d.\n", HASTA,
numerodeprimos);
return 0;
}

Obviamente, está codificado de manera que usa pura fuerza bruta, en
ambos casos, y obvia mejoras triviales, como evitar comprobar si un
número "candidato" tiene por divisor números que ya hemos determinado
que no son primos. Pero para HASTA= 1000, mi patata de ordenador,
comparado con los que se venden hoy, a poco más de 1 GHz de frecuencia
de reloj y con 256 MBs de RAM tarda una fracción de segundo. Huelga
decir que para HASTAs grandes, deberíamos introducir al menos mejoras
sencillas (comprobar sólo los divisores hasta la raíz cuadrada de los
candidatos, y mirar sólo qué números que sabemos primos son divisores,
no los compuestos)

Como se encuentra fácil en la web y en la literatura, para 1000
tenemos 168 números primos menores. 3000 no suele venir
en las tablas (suelen dar 10,100,1000,10000... para que se vea
la progresión en n/pi(n) del orden de 2,3 por cada factor de diez).
No obstante, los programas dan 430, lo que da 430-168 primos
entre 1000 y 3000. Para otros números, se ruega compilar
y ejecutar ^___^

Saludos,

S.
gamo
2006-07-21 14:03:27 UTC
Permalink
Post by Sergio
Haciendo una criba de Eratóstenes, pero también a lo bruto, "tachamos"
(electrónicamente, en una matriz donde 0 es NO ES PRIMO, 1, es SÍ ES
Hago una correción para que sea en un intervalo y otra en un bucle.
Saludos

#include <stdio.h>
#include <stdlib.h>
#define MIN(a,b) (a)<(b) ? (a) : (b)

int main (int argc, char **argv)
{
int DESDE=atoi(argv[1]);
int HASTA=atoi(argv[2]);
DESDE=MIN(DESDE,HASTA);
int esprimo[HASTA+1];
int i, j, numerodeprimos;

if (DESDE==HASTA || DESDE<2){ exit(1); }

for (i=1; i<=HASTA; i++)
esprimo[i]=1; /* de nuevo in dubbio pro reo */
for (i=2; i<=1+HASTA/2; i++) /* para que tarde menos */
{
for (j=i*2; j<=HASTA; j+=i)
esprimo[j]=0;
}
numerodeprimos=0;
for (i=DESDE; i<=HASTA; i++)
if (esprimo[i]==1)
numerodeprimos++;
printf ("\nEl número de primos entre %d y %d es %d.\n", DESDE,HASTA,
numerodeprimos);
return 0;
}
gamo
2006-07-21 15:12:55 UTC
Permalink
Post by gamo
for (i=2; i<=1+HASTA/2; i++) /* para que tarde menos */
{
if (esprimo[i]==1) /* esto también lo hace mejor */
Post by gamo
for (j=i*2; j<=HASTA; j+=i)
esprimo[j]=0;
}
Saludos
Sergio
2006-07-21 19:21:19 UTC
Permalink
Post by gamo
Post by gamo
for (i=2; i<=1+HASTA/2; i++) /* para que tarde menos */
{
if (esprimo[i]==1) /* esto también lo hace mejor */
(...)
Post by gamo
Post by gamo
}
¡ Excelente sintética implementación de una de las
mejoras triviales que propuse ! ^__^
S.

Ignacio Larrosa Cañestro
2006-07-20 14:44:40 UTC
Permalink
Post by Sergio
On Thu, 20 Jul 2006 14:54:33 +0200, "Jorge S. de Lis"
Post by Jorge S. de Lis
Necesito ayuda.
Me parece un intervalo demasiado exagerado como para probarlos uno a
uno. ¿Alguien conoce alguna regla que me permita saberlo? (sólo el
número, no cuáles son).
Me temo que no, que nadie la conoce :-)
A priori, el número de primos comprendido entre dos enteros m y n
es bastante imprevisible. La única aproximación factible es, ni más
ni menos, que contarlos. Ahora bien, como has accedido a enviar
un mensaje a este newsgroup, doy por supuesto que tienes acceso
a un ordenador digital. En tal caso, contar los números primos
entre 1000 y 3000 es sencillo, en cualquier lenguaje de programación
de alto nivel se hace un programa para ello en dos patadas.
Puede haber mejores o peores algoritmos, si bien, si sólo pretendemos
llegar a un número tan pequeño como 3000, la aproximación más
trivial es perfectamente válida y en cualquier computador
contemporáneo tardará un tiempo muy breve: basta iterar sobre todos
los números entre 1000 y 3000 y, para cada uno de ellos, tratar de
dividirlo por todos los enteros entre 2 y la raíz cuadrada del número.
Si hallamos un divisor, no es primo.
Una mejora obvia es ir almacenando una lista de los primos que
vamos encontrando y tratar de dividir los nuevos candidatos
solamente entre los números primos menores que él. Si es divisible por
algún número distinto de sí mismo y la unidad que no sea primo,
también será divisible por los factores primos de dicho número, de
modo que no tiene sentido intentarlo con números compuestos salvo
por simplicidad y rapidez de implementación del algoritmo ( un momento
versus un poquito más). También se puede aplicar un procedimiento
de criba de eratóstenes, para determinar todos los primos que deseas,
o como paso inicial para un cierto subconjunto inicial de los
candidatos, cosa que eliminará muchas divisiones inútiles.
Ahora bien, aunque no conocemos ninguna forma de determinar cuántos
primos existen en un pequeño intervalo numérico, sí sabemos cómo se
comporta el número de primos cuando vamos considerando intervalos
mayores, donde las irregularidades de la frecuencia de primos en los
sucesivos tramos se van compensando en favor de una tendencia general.
Como seguramente sabes, se suele llamar pi a la función que , para
cada n, nos da el número de primos menor o igual que n. Se tiene que
pi(n) es aproximadamente n / ln n, y, notablemente, que el límite
cuando n tiende a infinito de pi (n) / ( n / ln n) es 1 ( de la Vallèe
Poussin y Hadamard, 1896). Una aproximación aún mejor a la
función pi que nos permite estimar el número de primos en un tramo
es 1 + SUMA en k, k=1, infinito ( 1 / ( k zeta(k+1) * (log n)^k / k!
),
con zeta representando la función zeta de Riemann.
Espero que eso ayude. Si no sueles programar y quieres, coméntalo
y te escribo aquí un programilla diminuto en C que cuenta el número
de primos, como te digo es brevísimo.
Saludos, S.
Añadiendo a lo que te ha dicho Sergio, se me ocurren otras dos posibilidades
para contarlos:

i) Criba de Eratóstenes. Hazte una tabla con los números del 1001 al 3000, y
tacha el segundo, cuarto, .... A continuación elimina el primer múltiplo de
3, y a partir de él ve tachando el tercero. Luego lo mismo con 5, 7, 11, 13,
17, 19, 23, 29, 31, 37, 41, 43, 47 y 53, que son todos los primos menores
que rq(3000) (esto supongo que enlaza con tu pregunta anterior). Cuando
hablo de tachar el tercero, el quinto, etc..., naturalmente se cuentan los
que ya están tachados, y si toca tachar uno que ya lo está, no se hace nada.
Luego solo hay que contar los sobrevivientes.

Esto se puede implementar muy fácilmente. Normalmente se consideran solo los
impares y se utiliza un bit para cada uno, poniedolos en principio a 1, y
pasandolos a 0 cuando se tachan. Pero para números de este orden,
posiblemente no compense, con utilizar un array de enteros sería suficiente.
No entro en más detalles de programación, porque la tengo un poco oxidada,
pero un programa muy sencillo y 'ad hoc', no general, se reduce simplemente
a 14 bucles for ... next, por ejemplo.

ii) Utilizar el principio de inclusiones y exclusiones. De los 2000 números,
descontamos los 1000 múltiplos de 2, los 2000/3 múltiplos de 3 (ojo a los
detalles), etc.... Como los múltiplos de 6 = 2*3, 10 = 2*5, 14 = 2*7, 15 =
3*5, ... se han descontado dos veces, hay que sumarlos una. Pero entonces
hay que descontar. Pero los múltiplos de 2*3*5 los acabamos de sumar tres
veces no una, por lo que habrá que descontarlos 2, etc...

Si se trata de una práctica de programación, indudablemente la solución i)
debe ser la mejor.

Para que puedas comprobar, hay 262 primos entre 1000 y 3000.
--
Saludos,

Ignacio Larrosa Cañestro
A Coruña (España)
***@mundo-r.com
gamo
2006-07-20 18:47:41 UTC
Permalink
On Thu, 20 Jul 2006, Ignacio Larrosa Cañestro wrote:

...
Post by Ignacio Larrosa Cañestro
Si se trata de una práctica de programación, indudablemente la solución i)
debe ser la mejor.
Para que puedas comprobar, hay 262 primos entre 1000 y 3000.
Otra opción es implementar una subrutina is_prime()
según Miller & Rabin.
Saludos,
--
http://www.telecable.es/personales/gamo/
perl -e 'print 111_111_111**2,"\n";'
j***@gmail.com
2006-07-21 13:17:14 UTC
Permalink
Post by gamo
...
Post by Ignacio Larrosa Cañestro
Si se trata de una práctica de programación, indudablemente la solución i)
debe ser la mejor.
Para que puedas comprobar, hay 262 primos entre 1000 y 3000.
Otra opción es implementar una subrutina is_prime()
según Miller & Rabin.
Saludos,
A menos que se trate de un ejercicio de programación, yo respondería
Post by gamo
pi(3000) - pi(1000);
262

Saludos,

jhn
Loading...