![]() |
11 millones de números primos
1 Archivos Adjunto(s)
"11 millones de números primos" o "sobre la evolución personal en la programación".
Muy buenas. Pasaba por aquí, y no he podido evitar dar a conocer un pequeño proyecto sin importancia al que me he estado dedicando últimamente. Bueno, tendría que contaros la historia, ¡y es que a 11 millones de números primos no se llega así como así! Y menos con los pocos conocimientos de programación con los que empecé. Procedure ContarHistoria(AQuien: TDestinatario); begin If AQuien=GenteDelClubDelphi then begin PedirAlgo('¡Camarero, una ronda y un platico de jamón y queso!'); SoltarElRollo(' En fin, "once upon a time in my home", cuando llevaba poco tiempo en el fascinante mundo de la programación en Delphi (bueno, la programación en general) se me ocurrió hacer un simple programa que pudiera descomponer un número en sus factores primos. Pero entonces pensé «Necesitaré una lista de números primos», así que al programa tuve que añadirle un generador de números primos. Le indicabas un rango de números (del 2 al 1000, por ejemplo), e iba comprobando si todos los números comprendidos en ese rango eran primos. Observé que me salió bastante bien: el rango 2-1000 me lo sacaba en muy pocos segundos. Los números se almacenaban en un TMemo, y yo me encargaba de añadirlos a un archivo llamado "primos.txt". Después, cada vez que abría el programa, "primos.txt" se cargaba en otro TMemo (para hacerlo bonito, más que nada), y esa era la lista de primos a la que accedía el descomponedor en factores primos. Todo iba "bien", hasta que, claro, no tenía suficientes números primos, a la hora de calcular descomposiciones de números muy grandes. Así que tuve que agrandar la lista de números primos, pero a partir del 100.000, el cálculo empezaba a resultar demasiado lento. Y ahí fue donde realicé las primeras optimizaciones al código: dejé de comprobar los números pares (pues obviamente no son primos), a la hora de comprobarlos tampoco probaba con divisores pares (pues si el número a comprobar no era par pues perdía el tiempo con esos cálculos). Además descubrí el "Memo.Lines.BeginUpdate". ¡Violá! De repente tenía ante mí un código que me pareció tremendamente rápido. Empecé a calcular primos hasta que, cuando iba por el rango 2.000.000-2.100.000 (me parece recordar) la cosa se volvía otra vez lenta: tardaba alrededor de un minuto en calcularlo. A partir de ahí la cosa quedó un poco abandonada, si eso de vez en cuando hacía crecer el rango 100.000 más, sacando unos pocos miles de números primos. Pero hace poco, anteayer concretamente, lo vi y me dije «¿Y si aplico todo lo que he aprendido y realizado estos años para optimizar el código al máximo?». Y así hice. Primero pasé del TStringList al TIntegers, un objeto que creé hace tiempo con otra necesidad, y que se puede deducir qué es y cómo funciona (y si no, pues lo digo, es como TStringList, pero en vez de Strings almacena Integers). Además me dejé de interfaz gráfica (porque llevo tres días sin mouse y el IDE de Delphi sin mouse...). Así que creaba un .dpr vacío, y empezaba el programa de cero. La entrada y salida de datos la hacía con parámetros (que son fáciles de utilizar con la consola o teniendo instalado FileMenuTools). Lo primero fue crear dos programas, el ttn.exe y el ntt.exe, que transforman un archivo de texto con números listados en un archivo con números listados (que es el que puede cargar y guarda el TIntegers). Después optimicé un poco más el código para comprobar si un número es primo o no (antes comprobaba si era divisible por todos los números impares hasta su mitad, pero matemáticamente sólo es necesaria esta comprobación hasta llegar a su raíz cuadrada truncada). Además desarrollé otro método (que con el TStringList resultaba lentísimo), y es comprobar que el número no es divisible por ningún número primo menor que su raíz cuadrada truncada. Pero lo de crear un programa que creara primos en un rango ya no me era suficiente, y realicé otro que aumenta el rango de los primos ya calculados. Por ejemplo, ahora que ya había calculado primos del 1 al 3.500.000, pues con sólo decirle que aumentara el rango en 500.000, ya tenía los primos del 1 al 4.000.000, pero ¡ya!, porque no tardó casi nada en realizar el cálculo. Así que fui probando (esto ya ayer por la tarde) y... en unos pocos minutos... ¡ya tenía 11 millones y pico de números primos! Los que van del 1 al 200.000.000. '); end; end; Si cuando empecé con la idea de descomponer un número en sus factores primos alguien me hubiese dicho que en un par de años (o tres) habría realizado un programa que va por comandos, que utiliza un objeto tan potente como TStringList pero que funciona con Integers y que está hecho por mí, y que los primeros 11 millones de números primos se calcularían en unos 10 minutos, no sé cómo habría reaccionado. Supongo que no me lo habría creído. O habría pensado que habría necesitado miles de líneas de código, ¡cuando sólo tiene unas 250!. Y eso que me dedico a la programación por afición (bueno, ahora en la universidad doy C en clase de informática). ¡Ah! Casi se me olvida. Subo el código de los programas, con una breve explicación de su funcionamiento, y una lista de los primeros números primos (los que puedo decir de cabeza) en formato lista de texto y en formato lista numérica. ¡A ver si alguien se anima y lo optimiza un poco más!. Saludos a todos (y espero no haberos aburrido con la historia). |
Pues muy interesante tu relato, :), lo que mas me llama la atención es tu perseverancia con dicho proyecto.
|
Bonito entretenimiento, yo tambien me apunto :D
Con esto calculo los 15.000.000 primeros primos en 20 minutos Es una aplicacion de consola:
El programa anterior muestra algo como esto: Código:
Generando numeros primos ... Alguno se anima a mejorar el tiempo :p:D |
¿Mejorar el tiempo usando otro algoritmo?
|
Cita:
|
Cita:
Salud OS |
Cita:
|
Invertí algo más de 18 minutos, la salida es como lo habías dicho un monstruoso archivo de cerca de 150 mb.
Siempre me pregunté si los números primos servían para algo..., algo útil quiero decir. Saludos |
Cita:
|
Seoane: tu código compilado en FreePascal bajo windows fue 5 min y medio más rápido que el compilado con delphi.
Me gustaría probar que pasa compilandolo con Freepascal bajo linux pero hay partes del código que no se como modificar para que compile sin errores Saludos |
Cita:
(primos.pas)
|
Tube que cambiar una cosa debido aun error:
{$apptype console} por {$mode objfpc} En linux tardó 00:23:06 y el archivo de salida fue de 7.3 mb En windows usando el mismo código 00:15:39 y el archivo de salida 136 mb. No puedo creer que el código en linux ande más lento. Un saludo y gracias |
Cita:
Revísalo, anda. Saludos :) |
Cita:
Saludos. |
Holas...
El relato es interesante; pero el metodo que aplicas para buscar numeros primos comprobando si es divisible un numero entre numeros primos anteriores incluso hasta la raiz cuadrada de este sera exageradamente lento cuando busques mas alla de 1.000.000.000 ni que decir cuandopases del Billon. El metodo que uso es PRI-BASE me genera una serie de numeros casi primos directos de los cuales se depuran algunos, el proceso para buscar 10.000.000.000 tarda unos 00:21:37 (21 minutos) de los cuales 3-4 min son de la busqueda en si y el resto es lo que se demora en archivarlos, ya que con este rango encuentra mas de 36.000.000 de numeros primos. Otro detalle es que el tiempo de busqueda y archivo va disminuyendo al ir avanzando y encontrando primos mas grandes; en cambio con el metodo de factorizacion cada vez tendra que hacer calculos mas largos y complejos, lo que hara mas lento el proceso. Este metodo es totalmente arbitrario a la logica que nos enseñaron para determinar numeros primos, no necesita tener todos los primos sacados para seguir avanzando en la busqueda,para lo que se necesitarian varias computadoras, con una basta, claro con disco duro de 1 Tera. Para finalizar te diria que hay muchas maneras de encontrar numeros primos y son simples... piensa y analiza... Suerte Victor Luis |
Cita:
|
La franja horaria es GMT +2. Ahora son las 07:28:43. |
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi