Cuál es la forma más elegante de implementar esta función:
ArrayList generatePrimes(int n)
Esta función genera los primeros n
números primos (editar: donde n>1
), por generatePrimes(5)
lo que devolverá un ArrayList
con {2, 3, 5, 7, 11}
. (Estoy haciendo esto en C #, pero estoy contento con una implementación de Java, o cualquier otro lenguaje similar para el caso (así que no Haskell)).
Sé cómo escribir esta función, pero cuando lo hice anoche no terminó tan bien como esperaba. Esto es lo que se me ocurrió:
ArrayList generatePrimes(int toGenerate)
{
ArrayList primes = new ArrayList();
primes.Add(2);
primes.Add(3);
while (primes.Count < toGenerate)
{
int nextPrime = (int)(primes[primes.Count - 1]) + 2;
while (true)
{
bool isPrime = true;
foreach (int n in primes)
{
if (nextPrime % n == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
break;
}
else
{
nextPrime += 2;
}
}
primes.Add(nextPrime);
}
return primes;
}
No me preocupa demasiado la velocidad, aunque no quiero que sea obviamente ineficiente. No me importa qué método se use (ingenuo o tamiz o cualquier otra cosa), pero quiero que sea bastante breve y obvio cómo funciona.
Editar : Gracias a todos los que han respondido, aunque muchos no respondieron mi pregunta real. Para reiterar, quería un buen código limpio que generara una lista de números primos. Ya sé cómo hacerlo de diferentes maneras, pero soy propenso a escribir código que no es tan claro como podría ser. En este hilo se han propuesto algunas buenas opciones:
- Una versión más bonita de lo que tenía originalmente (Peter Smit, jmservera y Rekreativc)
- Una implementación muy limpia del tamiz de Eratosthenes (starblue)
- Use Java's
BigInteger
synextProbablePrime
para un código muy simple, aunque no puedo imaginar que sea particularmente eficiente (dfa) - Utilice LINQ para generar perezosamente la lista de números primos (Maghis)
- Coloque muchos números primos en un archivo de texto y léalos cuando sea necesario (darin)
Edición 2 : implementé en C # un par de los métodos que se dan aquí y otro método que no se menciona aquí. Todos encuentran los primeros n números primos de manera efectiva (y tengo un método decente para encontrar el límite para proporcionar a los tamices).
nubBy (((>1).).gcd) [2..]
. Deja solo no duplicados entre los números naturales, comenzando desde 2, considerando como duplicado cualquier número cuyogcd
con cualquiera de los números encontrados anteriormente sea mayor que 1. Es muy ineficiente, cuadrático en el número de primos producidos. Pero es elegante .import Data.List.Ordered ; let { _Y g = g (_Y g) ; primes = 2 : _Y( (3:) . minus [5,7..] . unionAll . map (\p-> [p*p, p*p+p*2..]) ) }
pero eso, por supuesto , se basa totalmente en opiniones .Respuestas:
Usa la estimación
pi(n) = n / log(n)
para el número de primos hasta n para encontrar un límite, y luego use un tamiz. La estimación subestima un poco el número de números primos hasta n, por lo que el tamiz será un poco más grande de lo necesario, lo cual está bien.
Este es mi tamiz Java estándar, calcula el primer millón de números primos en aproximadamente un segundo en una computadora portátil normal:
public static BitSet computePrimes(int limit) { final BitSet primes = new BitSet(); primes.set(0, false); primes.set(1, false); primes.set(2, limit, true); for (int i = 0; i * i < limit; i++) { if (primes.get(i)) { for (int j = i * i; j < limit; j += i) { primes.clear(j); } } } return primes; }
fuente
i <= Math.sqrt(limit)
en el bucle exterior?BitSet
por una clase que implementa la factorización de rueda para 2, 3 y 5, se vuelve casi 3 veces más rápido.Muchas gracias a todos los que dieron respuestas útiles. Aquí están mis implementaciones de algunos métodos diferentes para encontrar los primeros n números primos en C #. Los dos primeros métodos son prácticamente los que se publicaron aquí. (Los nombres de los carteles están al lado del título). Planeo hacer el tamiz de Atkin en algún momento, aunque sospecho que no será tan simple como los métodos aquí actualmente. Si alguien puede ver alguna forma de mejorar alguno de estos métodos, me encantaría saberlo :-)
Método estándar ( Peter Smit , jmservera , Rekreativc )
El primer número primo es 2. Agregue esto a una lista de primos. El siguiente primo es el siguiente número que no es divisible de manera uniforme por ningún número de esta lista.
public static List<int> GeneratePrimesNaive(int n) { List<int> primes = new List<int>(); primes.Add(2); int nextPrime = 3; while (primes.Count < n) { int sqrt = (int)Math.Sqrt(nextPrime); bool isPrime = true; for (int i = 0; (int)primes[i] <= sqrt; i++) { if (nextPrime % primes[i] == 0) { isPrime = false; break; } } if (isPrime) { primes.Add(nextPrime); } nextPrime += 2; } return primes; }
Esto se ha optimizado probando solo la divisibilidad hasta la raíz cuadrada del número que se está probando; y solo probando números impares. Esto se puede optimizar aún más probando solo números del formulario
6k+[1, 5]
,30k+[1, 7, 11, 13, 17, 19, 23, 29]
o así sucesivamente .Tamiz de Eratóstenes ( azul estrella )
Esto encuentra todos los números primos de k . Para hacer una lista de los primeros n primos, primero necesitamos aproximar el valor del n- ésimo primo. El siguiente método, como se describe aquí , hace esto.
public static int ApproximateNthPrime(int nn) { double n = (double)nn; double p; if (nn >= 7022) { p = n * Math.Log(n) + n * (Math.Log(Math.Log(n)) - 0.9385); } else if (nn >= 6) { p = n * Math.Log(n) + n * Math.Log(Math.Log(n)); } else if (nn > 0) { p = new int[] { 2, 3, 5, 7, 11 }[nn - 1]; } else { p = 0; } return (int)p; } // Find all primes up to and including the limit public static BitArray SieveOfEratosthenes(int limit) { BitArray bits = new BitArray(limit + 1, true); bits[0] = false; bits[1] = false; for (int i = 0; i * i <= limit; i++) { if (bits[i]) { for (int j = i * i; j <= limit; j += i) { bits[j] = false; } } } return bits; } public static List<int> GeneratePrimesSieveOfEratosthenes(int n) { int limit = ApproximateNthPrime(n); BitArray bits = SieveOfEratosthenes(limit); List<int> primes = new List<int>(); for (int i = 0, found = 0; i < limit && found < n; i++) { if (bits[i]) { primes.Add(i); found++; } } return primes; }
Tamiz de Sundaram
Recientemente descubrí este tamiz , pero se puede implementar de manera bastante simple. Mi implementación no es tan rápida como el tamiz de Eratóstenes, pero es significativamente más rápida que el método ingenuo.
public static BitArray SieveOfSundaram(int limit) { limit /= 2; BitArray bits = new BitArray(limit + 1, true); for (int i = 1; 3 * i + 1 < limit; i++) { for (int j = 1; i + j + 2 * i * j <= limit; j++) { bits[i + j + 2 * i * j] = false; } } return bits; } public static List<int> GeneratePrimesSieveOfSundaram(int n) { int limit = ApproximateNthPrime(n); BitArray bits = SieveOfSundaram(limit); List<int> primes = new List<int>(); primes.Add(2); for (int i = 1, found = 1; 2 * i + 1 <= limit && found < n; i++) { if (bits[i]) { primes.Add(2 * i + 1); found++; } } return primes; }
fuente
i+j+2*i*j
lo que conduce a una salida incorrecta.Resolviendo una vieja pregunta, pero me tropecé con ella mientras jugaba con LINQ.
Este código requiere .NET4.0 o .NET3.5 con extensiones paralelas
public List<int> GeneratePrimes(int n) { var r = from i in Enumerable.Range(2, n - 1).AsParallel() where Enumerable.Range(1, (int)Math.Sqrt(i)).All(j => j == 1 || i % j != 0) select i; return r.ToList(); }
fuente
Estás en el buen camino.
Algunos comentarios
primos.Añadir (3); hace que esta función no funcione para número = 1
No tiene que probar la división con números primos más grandes que la raíz cuadrada del número que se va a probar.
Código sugerido:
ArrayList generatePrimes(int toGenerate) { ArrayList primes = new ArrayList(); if(toGenerate > 0) primes.Add(2); int curTest = 3; while (primes.Count < toGenerate) { int sqrt = (int) Math.sqrt(curTest); bool isPrime = true; for (int i = 0; i < primes.Count && primes.get(i) <= sqrt; ++i) { if (curTest % primes.get(i) == 0) { isPrime = false; break; } } if(isPrime) primes.Add(curTest); curTest +=2 } return primes; }
fuente
debería echar un vistazo a probables números primos . En particular, eche un vistazo a los algoritmos aleatorios y la prueba de primaria de Miller-Rabin .
En aras de la integridad, puede usar java.math.BigInteger :
public class PrimeGenerator implements Iterator<BigInteger>, Iterable<BigInteger> { private BigInteger p = BigInteger.ONE; @Override public boolean hasNext() { return true; } @Override public BigInteger next() { p = p.nextProbablePrime(); return p; } @Override public void remove() { throw new UnsupportedOperationException("Not supported."); } @Override public Iterator<BigInteger> iterator() { return this; } } @Test public void printPrimes() { for (BigInteger p : new PrimeGenerator()) { System.out.println(p); } }
fuente
De ninguna manera eficiente, pero quizás el más legible:
public static IEnumerable<int> GeneratePrimes() { return Range(2).Where(candidate => Range(2, (int)Math.Sqrt(candidate))) .All(divisor => candidate % divisor != 0)); }
con:
public static IEnumerable<int> Range(int from, int to = int.MaxValue) { for (int i = from; i <= to; i++) yield return i; }
De hecho, solo una variación de algunas publicaciones aquí con un formato más agradable.
fuente
Derechos de autor 2009 de St. Wittum 13189 Berlín ALEMANIA bajo licencia CC-BY-SA https://creativecommons.org/licenses/by-sa/3.0/
La forma simple pero más elegante de calcular TODOS LOS PRIMES sería esta, pero de esta manera es lenta y los costos de memoria son mucho más altos para números más altos porque se usa la función de facultad (!) ... generar todos los primos por algoritmo implementado en Python
#!/usr/bin/python f=1 # 0! p=2 # 1st prime while True: if f%p%2: print p p+=1 f*=(p-2)
fuente
Utilice un generador de números primos para crear primes.txt y luego:
class Program { static void Main(string[] args) { using (StreamReader reader = new StreamReader("primes.txt")) { foreach (var prime in GetPrimes(10, reader)) { Console.WriteLine(prime); } } } public static IEnumerable<short> GetPrimes(short upTo, StreamReader reader) { int count = 0; string line = string.Empty; while ((line = reader.ReadLine()) != null && count++ < upTo) { yield return short.Parse(line); } } }
En este caso, utilizo Int16 en la firma del método, por lo que mi archivo primes.txt contiene números del 0 al 32767. Si desea extender esto a Int32 o Int64, su primes.txt podría ser significativamente mayor.
fuente
Puedo ofrecer la siguiente solución de C #. De ninguna manera es rápido, pero es muy claro lo que hace.
public static List<Int32> GetPrimes(Int32 limit) { List<Int32> primes = new List<Int32>() { 2 }; for (int n = 3; n <= limit; n += 2) { Int32 sqrt = (Int32)Math.Sqrt(n); if (primes.TakeWhile(p => p <= sqrt).All(p => n % p != 0)) { primes.Add(n); } } return primes; }
Dejé todos los controles, si el límite es negativo o menor que dos (por el momento, el método siempre devolverá al menos dos como primo). Pero todo eso es fácil de arreglar.
ACTUALIZAR
Con los siguientes dos métodos de extensión
public static void Do<T>(this IEnumerable<T> collection, Action<T> action) { foreach (T item in collection) { action(item); } } public static IEnumerable<Int32> Range(Int32 start, Int32 end, Int32 step) { for (int i = start; i < end; i += step) } yield return i; } }
puede reescribirlo de la siguiente manera.
public static List<Int32> GetPrimes(Int32 limit) { List<Int32> primes = new List<Int32>() { 2 }; Range(3, limit, 2) .Where(n => primes .TakeWhile(p => p <= Math.Sqrt(n)) .All(p => n % p != 0)) .Do(n => primes.Add(n)); return primes; }
Es menos eficiente (porque la raíz cuadrada se reevalúa con bastante frecuencia) pero es un código aún más limpio. Es posible reescribir el código para enumerar perezosamente los números primos, pero esto saturará un poco el código.
fuente
Aquí hay una implementación de Sieve of Eratosthenes en C #:
IEnumerable<int> GeneratePrimes(int n) { var values = new Numbers[n]; values[0] = Numbers.Prime; values[1] = Numbers.Prime; for (int outer = 2; outer != -1; outer = FirstUnset(values, outer)) { values[outer] = Numbers.Prime; for (int inner = outer * 2; inner < values.Length; inner += outer) values[inner] = Numbers.Composite; } for (int i = 2; i < values.Length; i++) { if (values[i] == Numbers.Prime) yield return i; } } int FirstUnset(Numbers[] values, int last) { for (int i = last; i < values.Length; i++) if (values[i] == Numbers.Unset) return i; return -1; } enum Numbers { Unset, Prime, Composite }
fuente
Usando su mismo algoritmo, puede hacerlo un poco más corto:
List<int> primes=new List<int>(new int[]{2,3}); for (int n = 5; primes.Count< numberToGenerate; n+=2) { bool isPrime = true; foreach (int prime in primes) { if (n % prime == 0) { isPrime = false; break; } } if (isPrime) primes.Add(n); }
fuente
Sé que solicitó una solución que no sea de Haskell, pero incluyo esto aquí en lo que respecta a la pregunta y también Haskell es hermoso para este tipo de cosas.
module Prime where primes :: [Integer] primes = 2:3:primes' where -- Every prime number other than 2 and 3 must be of the form 6k + 1 or -- 6k + 5. Note we exclude 1 from the candidates and mark the next one as -- prime (6*0+5 == 5) to start the recursion. 1:p:candidates = [6*k+r | k <- [0..], r <- [1,5]] primes' = p : filter isPrime candidates isPrime n = all (not . divides n) $ takeWhile (\p -> p*p <= n) primes' divides n p = n `mod` p == 0
fuente
Escribí una implementación simple de Eratóstenes en c # usando algo de LINQ.
Desafortunadamente, LINQ no proporciona una secuencia infinita de entradas, por lo que debe usar int.MaxValue :(
Tuve que almacenar en caché en un tipo anónimo el sqrt candidato para evitar calcularlo para cada primo almacenado en caché (se ve un poco feo).
Utilizo una lista de primos anteriores hasta sqrt del candidato
cache.TakeWhile(c => c <= candidate.Sqrt)
y comprobar cada Int a partir de 2 contra él
.Any(cachedPrime => candidate.Current % cachedPrime == 0)
Aquí está el código:
static IEnumerable<int> Primes(int count) { return Primes().Take(count); } static IEnumerable<int> Primes() { List<int> cache = new List<int>(); var primes = Enumerable.Range(2, int.MaxValue - 2).Select(candidate => new { Sqrt = (int)Math.Sqrt(candidate), // caching sqrt for performance Current = candidate }).Where(candidate => !cache.TakeWhile(c => c <= candidate.Sqrt) .Any(cachedPrime => candidate.Current % cachedPrime == 0)) .Select(p => p.Current); foreach (var prime in primes) { cache.Add(prime); yield return prime; } }
Otra optimización es evitar verificar números pares y devolver solo 2 antes de crear la lista. De esta manera, si el método de llamada solo pide 1 primo, evitará todo el desorden:
static IEnumerable<int> Primes() { yield return 2; List<int> cache = new List<int>() { 2 }; var primes = Enumerable.Range(3, int.MaxValue - 3) .Where(candidate => candidate % 2 != 0) .Select(candidate => new { Sqrt = (int)Math.Sqrt(candidate), // caching sqrt for performance Current = candidate }).Where(candidate => !cache.TakeWhile(c => c <= candidate.Sqrt) .Any(cachedPrime => candidate.Current % cachedPrime == 0)) .Select(p => p.Current); foreach (var prime in primes) { cache.Add(prime); yield return prime; } }
fuente
Para hacerlo más elegante, debe refactorizar su prueba IsPrime en un método separado y manejar el bucle y los incrementos fuera de eso.
fuente
Lo hice en Java usando una biblioteca funcional que escribí, pero como mi biblioteca usa los mismos conceptos que las Enumeraciones, estoy seguro de que el código es adaptable:
Iterable<Integer> numbers = new Range(1, 100); Iterable<Integer> primes = numbers.inject(numbers, new Functions.Injecter<Iterable<Integer>, Integer>() { public Iterable<Integer> call(Iterable<Integer> numbers, final Integer number) throws Exception { // We don't test for 1 which is implicit if ( number <= 1 ) { return numbers; } // Only keep in numbers those that do not divide by number return numbers.reject(new Functions.Predicate1<Integer>() { public Boolean call(Integer n) throws Exception { return n > number && n % number == 0; } }); } });
fuente
Este es el más elegante que se me ocurre a corto plazo.
ArrayList generatePrimes(int numberToGenerate) { ArrayList rez = new ArrayList(); rez.Add(2); rez.Add(3); for(int i = 5; rez.Count <= numberToGenerate; i+=2) { bool prime = true; for (int j = 2; j < Math.Sqrt(i); j++) { if (i % j == 0) { prime = false; break; } } if (prime) rez.Add(i); } return rez; }
Espero que esto ayude a darte una idea. Estoy seguro de que esto se puede optimizar, sin embargo, debería darte una idea de cómo tu versión podría ser más elegante.
EDITAR: Como se señaló en los comentarios, este algoritmo de hecho devuelve valores incorrectos para numberToGenerate <2. Solo quiero señalar que no estaba tratando de publicarle un gran método para generar números primos (mire la respuesta de Henri para eso), Al principio estaba señalando cómo su método podría ser más elegante.
fuente
Usando programación basada en flujo en Functional Java , se me ocurrió lo siguiente. El tipo
Natural
es esencialmente aBigInteger
> = 0.public static Stream<Natural> sieve(final Stream<Natural> xs) { return cons(xs.head(), new P1<Stream<Natural>>() { public Stream<Natural> _1() { return sieve(xs.tail()._1() .filter($(naturalOrd.equal().eq(ZERO)) .o(mod.f(xs.head())))); }}); } public static final Stream<Natural> primes = sieve(forever(naturalEnumerator, natural(2).some()));
Ahora tiene un valor, que puede llevar consigo, que es un flujo infinito de números primos. Puedes hacer cosas como esta:
// Take the first n primes Stream<Natural> nprimes = primes.take(n); // Get the millionth prime Natural mprime = primes.index(1000000); // Get all primes less than n Stream<Natural> pltn = primes.takeWhile(naturalOrd.lessThan(n));
Una explicación del tamiz:
Necesita tener las siguientes importaciones:
import fj.P1; import static fj.FW.$; import static fj.data.Enumerator.naturalEnumerator; import fj.data.Natural; import static fj.data.Natural.*; import fj.data.Stream; import static fj.data.Stream.*; import static fj.pre.Ord.naturalOrd;
fuente
Personalmente, creo que esta es una implementación bastante corta y limpia (Java):
static ArrayList<Integer> getPrimes(int numPrimes) { ArrayList<Integer> primes = new ArrayList<Integer>(numPrimes); int n = 2; while (primes.size() < numPrimes) { while (!isPrime(n)) { n++; } primes.add(n); n++; } return primes; } static boolean isPrime(int n) { if (n < 2) { return false; } if (n == 2) { return true; } if (n % 2 == 0) { return false; } int d = 3; while (d * d <= n) { if (n % d == 0) { return false; } d += 2; } return true; }
fuente
Pruebe esta consulta LINQ, genera números primos como esperaba
var NoOfPrimes= 5; var GeneratedPrime = Enumerable.Range(1, int.MaxValue) .Where(x => { return (x==1)? false: !Enumerable.Range(1, (int)Math.Sqrt(x)) .Any(z => (x % z == 0 && x != z && z != 1)); }).Select(no => no).TakeWhile((val, idx) => idx <= NoOfPrimes-1).ToList();
fuente
// Create a test range IEnumerable<int> range = Enumerable.Range(3, 50 - 3); // Sequential prime number generator var primes_ = from n in range let w = (int)Math.Sqrt(n) where Enumerable.Range(2, w).All((i) => n % i > 0) select n; // Note sequence of output: // 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, foreach (var p in primes_) Trace.Write(p + ", "); Trace.WriteLine("");
fuente
Aquí hay un ejemplo de código de Python que imprime la suma de todos los números primos por debajo de dos millones:
from math import * limit = 2000000 sievebound = (limit - 1) / 2 # sieve only odd numbers to save memory # the ith element corresponds to the odd number 2*i+1 sieve = [False for n in xrange(1, sievebound + 1)] crosslimit = (int(ceil(sqrt(limit))) - 1) / 2 for i in xrange(1, crosslimit): if not sieve[i]: # if p == 2*i + 1, then # p**2 == 4*(i**2) + 4*i + 1 # == 2*i * (i + 1) for j in xrange(2*i * (i + 1), sievebound, 2*i + 1): sieve[j] = True sum = 2 for i in xrange(1, sievebound): if not sieve[i]: sum = sum + (2*i+1) print sum
fuente
El método más simple es el de prueba y error: pruebe si cualquier número entre 2 y n-1 divide su candidato primo n.
Los primeros atajos son, por supuesto, a) solo tiene que verificar los números impares, yb) solo tiene que verificar los divisores hasta sqrt (n).
En su caso, donde también genera todos los primos anteriores en el proceso, solo tiene que verificar si alguno de los primos en su lista, hasta sqrt (n), divide n.
Debería ser lo más rápido que pueda obtener por su dinero :-)
editar
Ok, código, lo pediste. Pero te advierto :-), este es un código Delphi rápido y sucio de 5 minutos:
procedure TForm1.Button1Click(Sender: TObject); const N = 100; var PrimeList: TList; I, J, SqrtP: Integer; Divides: Boolean; begin PrimeList := TList.Create; for I := 2 to N do begin SqrtP := Ceil(Sqrt(I)); J := 0; Divides := False; while (not Divides) and (J < PrimeList.Count) and (Integer(PrimeList[J]) <= SqrtP) do begin Divides := ( I mod Integer(PrimeList[J]) = 0 ); inc(J); end; if not Divides then PrimeList.Add(Pointer(I)); end; // display results for I := 0 to PrimeList.Count - 1 do ListBox1.Items.Add(IntToStr(Integer(PrimeList[I]))); PrimeList.Free; end;
fuente
Para averiguar los primeros 100 números primos, se puede considerar el siguiente código java.
int num = 2; int i, count; int nPrimeCount = 0; int primeCount = 0; do { for (i = 2; i <num; i++) { int n = num % i; if (n == 0) { nPrimeCount++; // System.out.println(nPrimeCount + " " + "Non-Prime Number is: " + num); num++; break; } } if (i == num) { primeCount++; System.out.println(primeCount + " " + "Prime number is: " + num); num++; } }while (primeCount<100);
fuente
Lo obtuve leyendo por primera vez "Sieve of Atkin" en Wikki, además de un pensamiento previo que le he dado a esto: paso mucho tiempo codificando desde cero y me fijo completamente en que la gente sea crítica con mi codificación muy densa, similar a un compilador style + Ni siquiera he hecho un primer intento de ejecutar el código ... muchos de los paradigmas que he aprendido a usar están aquí, solo lee y llora, consigue lo que puedas.
Esté absolutamente y totalmente seguro de probar todo esto antes de cualquier uso, seguro que no se lo muestre a nadie, es para leer y considerar las ideas. Necesito que la herramienta de primalidad funcione, así que aquí es donde comienzo cada vez que tengo que hacer que algo funcione.
Obtenga una compilación limpia, luego comience a eliminar lo que está defectuoso: tengo casi 108 millones de pulsaciones de teclas de código utilizable haciéndolo de esta manera, ... use lo que pueda.
Trabajaré en mi versión mañana.
package demo; // This code is a discussion of an opinion in a technical forum. // It's use as a basis for further work is not prohibited. import java.util.Arrays; import java.util.HashSet; import java.util.ArrayList; import java.security.GeneralSecurityException; /** * May we start by ignores any numbers divisible by two, three, or five * and eliminate from algorithm 3, 5, 7, 11, 13, 17, 19 completely - as * these may be done by hand. Then, with some thought we can completely * prove to certainty that no number larger than square-root the number * can possibly be a candidate prime. */ public class PrimeGenerator<T> { // Integer HOW_MANY; HashSet<Integer>hashSet=new HashSet<Integer>(); static final java.lang.String LINE_SEPARATOR = new java.lang.String(java.lang.System.getProperty("line.separator"));// // PrimeGenerator(Integer howMany) throws GeneralSecurityException { if(howMany.intValue() < 20) { throw new GeneralSecurityException("I'm insecure."); } else { this.HOW_MANY=howMany; } } // Let us then take from the rich literature readily // available on primes and discount // time-wasters to the extent possible, utilizing the modulo operator to obtain some // faster operations. // // Numbers with modulo sixty remainder in these lists are known to be composite. // final HashSet<Integer> fillArray() throws GeneralSecurityException { // All numbers with modulo-sixty remainder in this list are not prime. int[]list1=new int[]{0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30, 32,34,36,38,40,42,44,46,48,50,52,54,56,58}; // for(int nextInt:list1) { if(hashSet.add(new Integer(nextInt))) { continue; } else { throw new GeneralSecurityException("list1");// } } // All numbers with modulo-sixty remainder in this list are are // divisible by three and not prime. int[]list2=new int[]{3,9,15,21,27,33,39,45,51,57}; // for(int nextInt:list2) { if(hashSet.add(new Integer(nextInt))) { continue; } else { throw new GeneralSecurityException("list2");// } } // All numbers with modulo-sixty remainder in this list are // divisible by five and not prime. not prime. int[]list3=new int[]{5,25,35,55}; // for(int nextInt:list3) { if(hashSet.add(new Integer(nextInt))) { continue; } else { throw new GeneralSecurityException("list3");// } } // All numbers with modulo-sixty remainder in // this list have a modulo-four remainder of 1. // What that means, I have neither clue nor guess - I got all this from int[]list4=new int[]{1,13,17,29,37,41,49,53}; // for(int nextInt:list4) { if(hashSet.add(new Integer(nextInt))) { continue; } else { throw new GeneralSecurityException("list4");// } } Integer lowerBound=new Integer(19);// duh Double upperStartingPoint=new Double(Math.ceil(Math.sqrt(Integer.MAX_VALUE)));// int upperBound=upperStartingPoint.intValue();// HashSet<Integer> resultSet=new HashSet<Integer>(); // use a loop. do { // One of those one liners, whole program here: int aModulo=upperBound % 60; if(this.hashSet.contains(new Integer(aModulo))) { continue; } else { resultSet.add(new Integer(aModulo));// } } while(--upperBound > 20); // this as an operator here is useful later in your work. return resultSet; } // Test harness .... public static void main(java.lang.String[] args) { return; } } //eof
fuente
Prueba este código.
protected bool isPrimeNubmer(int n) { if (n % 2 == 0) return false; else { int j = 3; int k = (n + 1) / 2 ; while (j <= k) { if (n % j == 0) return false; j = j + 2; } return true; } } protected void btn_primeNumbers_Click(object sender, EventArgs e) { string time = ""; lbl_message.Text = string.Empty; int num; StringBuilder builder = new StringBuilder(); builder.Append("<table><tr>"); if (int.TryParse(tb_number.Text, out num)) { if (num < 0) lbl_message.Text = "Please enter a number greater than or equal to 0."; else { int count = 1; int number = 0; int cols = 11; var watch = Stopwatch.StartNew(); while (count <= num) { if (isPrimeNubmer(number)) { if (cols > 0) { builder.Append("<td>" + count + " - " + number + "</td>"); } else { builder.Append("</tr><tr><td>" + count + " - " + number + "</td>"); cols = 11; } count++; number++; cols--; } else number++; } builder.Append("</table>"); watch.Stop(); var elapsedms = watch.ElapsedMilliseconds; double seconds = elapsedms / 1000; time = seconds.ToString(); lbl_message.Text = builder.ToString(); lbl_time.Text = time; } } else lbl_message.Text = "Please enter a numberic number."; lbl_time.Text = time; tb_number.Text = ""; tb_number.Focus(); }
Aquí está el código aspx.
<form id="form1" runat="server"> <div> <p>Please enter a number: <asp:TextBox ID="tb_number" runat="server"></asp:TextBox></p> <p><asp:Button ID="btn_primeNumbers" runat="server" Text="Show Prime Numbers" OnClick="btn_primeNumbers_Click" /> </p> <p><asp:Label ID="lbl_time" runat="server"></asp:Label></p> <p><asp:Label ID="lbl_message" runat="server"></asp:Label></p> </div> </form>
Resultados: 10000 números primos en menos de un segundo
100000 números primos en 63 segundos
Captura de pantalla de los primeros 100 números primos
fuente
isPrimeNubmer
hecho, implementa la división tril subóptima; sus asintóticos empeorarán a aproximadamente n ^ 2 (o incluso más) cuando intente generar aún más números primos.