Qual é a maneira mais elegante de implementar esta função:
ArrayList generatePrimes(int n)
Esta função gera os primeiros n
primos (editar: onde n>1
), então generatePrimes(5)
retornará um ArrayList
com {2, 3, 5, 7, 11}
. (Estou fazendo isso em C #, mas estou feliz com uma implementação Java - ou qualquer outra linguagem semelhante para esse assunto (portanto, não Haskell)).
Eu sei como escrever essa função, mas quando eu fiz isso na noite passada, ela não acabou tão legal quanto eu esperava. Aqui está o que eu descobri:
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;
}
Não estou muito preocupado com a velocidade, embora não queira que seja obviamente ineficiente. Não me importo com qual método é usado (ingênuo ou crivo ou qualquer outra coisa), mas eu quero que seja bastante curto e óbvio como funciona.
Edit : Obrigado a todos que responderam, embora muitos não tenham respondido minha pergunta real. Para reiterar, eu queria um código limpo e agradável que gerasse uma lista de números primos. Já sei como fazer isso de várias maneiras diferentes, mas estou propenso a escrever códigos que não são tão claros quanto poderiam ser. Neste tópico, algumas boas opções foram propostas:
- Uma versão melhor do que eu tinha originalmente (Peter Smit, jmservera e Rekreativc)
- Uma implementação muito limpa da peneira de Eratóstenes (azul da estrela)
- Use Java's
BigInteger
enextProbablePrime
para código muito simples, embora eu não possa imaginar que seja particularmente eficiente (dfa) - Use o LINQ para gerar preguiçosamente a lista de primos (Maghis)
- Coloque muitos números primos em um arquivo de texto e leia-os quando necessário (darin)
Edição 2 : implementei em C # alguns dos métodos fornecidos aqui e outro método não mencionado aqui. Todos eles encontram os primeiros n primos de forma eficaz (e eu tenho um método decente de encontrar o limite para fornecer às peneiras).
nubBy (((>1).).gcd) [2..]
. Deixa apenas não duplicatas entre os números naturais, começando de 2, enquanto considera como duplicado qualquer número cujogcd
com qualquer um dos números encontrados anteriormente seja maior que 1. É muito ineficiente, quadrático em número de primos produzidos. Mas é 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..]) ) }
mas é claro que se baseia inteiramente em opiniões .Respostas:
Use a estimativa
pi(n) = n / log(n)
para o número de primos até n para encontrar um limite e, em seguida, use uma peneira. A estimativa subestima o número de primos até n de alguma forma, então a peneira será um pouco maior do que o necessário, o que está ok.
Esta é minha peneira Java padrão, calcula o primeiro milhão de números primos em cerca de um segundo em um laptop 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; }
fonte
i <= Math.sqrt(limit)
no loop externo?BitSet
por uma classe que implementa a fatoração de roda para 2, 3 e 5, ele se torna quase 3 vezes mais rápido.Muito obrigado a todos que deram respostas úteis. Aqui estão minhas implementações de alguns métodos diferentes para localizar os primeiros n primos em C #. Os dois primeiros métodos são praticamente os que foram postados aqui. (Os nomes dos pôsteres estão ao lado do título.) Eu pretendo fazer a peneira de Atkin algum dia, embora eu suspeite que não seja tão simples quanto os métodos aqui atualmente. Se alguém puder ver alguma forma de melhorar algum desses métodos, eu adoraria saber :-)
Método Padrão ( Peter Smit , jmservera , Rekreativc )
O primeiro número primo é 2. Adicione a uma lista de primos. O próximo primo é o próximo número que não é divisível por nenhum número da 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; }
Isso foi otimizado apenas testando a divisibilidade até a raiz quadrada do número que está sendo testado; e testando apenas números ímpares. Isto pode ser ainda mais optimizado, testando apenas números da forma
6k+[1, 5]
, ou de30k+[1, 7, 11, 13, 17, 19, 23, 29]
ou assim por diante .Peneira de Eratóstenes ( azul estrelado )
Isso encontra todos os primos para k . Para fazer uma lista dos primeiros n primos, primeiro precisamos aproximar o valor do n- ésimo primo. O método a seguir, conforme descrito aqui , faz isso.
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; }
Peneira de Sundaram
Só descobri essa peneira recentemente, mas ela pode ser implementada de forma bastante simples. Minha implementação não é tão rápida quanto a peneira de Eratóstenes, mas é significativamente mais rápida do que o método ingênuo.
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; }
fonte
i+j+2*i*j
levando a uma saída incorreta.Ressuscitando uma velha questão, mas tropecei nela enquanto brincava com o LINQ.
Este código requer .NET4.0 ou .NET3.5 com extensões 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(); }
fonte
Você está no bom caminho.
Alguns comentários
primes.Add (3); faz com que esta função não funcione para número = 1
Você não precisa testar a divisão com números primários maiores que a raiz quadrada do número a ser testado.
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; }
fonte
você deve dar uma olhada nos primos prováveis . Em particular, dê uma olhada em Algoritmos Randomizados e teste de primalidade de Miller-Rabin .
Para fins de integridade, você pode apenas 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); } }
fonte
De forma alguma eficiente, mas talvez o mais legível:
public static IEnumerable<int> GeneratePrimes() { return Range(2).Where(candidate => Range(2, (int)Math.Sqrt(candidate))) .All(divisor => candidate % divisor != 0)); }
com:
public static IEnumerable<int> Range(int from, int to = int.MaxValue) { for (int i = from; i <= to; i++) yield return i; }
Na verdade, apenas uma variação de alguns posts aqui com formatação mais agradável.
fonte
Copyrights 2009 por St.Wittum 13189 Berlin ALEMANHA sob licença CC-BY-SA https://creativecommons.org/licenses/by-sa/3.0/
A maneira simples, mas mais elegante de calcular TODOS OS PRIMES seria esta, mas desta forma é lenta e os custos de memória são muito mais altos para números mais altos porque usar a função de faculdade (!) ... mas demonstra uma variação do Teorema de Wilson em uma aplicação para gerar todos os primos por algoritmo implementado em Python
#!/usr/bin/python f=1 # 0! p=2 # 1st prime while True: if f%p%2: print p p+=1 f*=(p-2)
fonte
Use um primo gerador de números para criar primes.txt e, em seguida:
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); } } }
Neste caso, eu uso Int16 na assinatura do método, então meu arquivo primes.txt contém números de 0 a 32767. Se você quiser estender isso para Int32 ou Int64, seu primes.txt pode ser significativamente maior.
fonte
Posso oferecer a seguinte solução C #. Não é nada rápido, mas é muito claro sobre o que faz.
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; }
Eu deixei de fora quaisquer verificações - se o limite for negativo ou menor que dois (no momento, o método sempre retornará pelo menos dois como primo). Mas tudo isso é fácil de consertar.
ATUALIZAR
Com os dois métodos de extensão a seguir
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; } }
você pode reescrevê-lo da seguinte maneira.
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; }
É menos eficiente (porque a raiz quadrada é reavaliada com frequência), mas é um código ainda mais limpo. É possível reescrever o código para enumerar preguiçosamente os primos, mas isso bagunçará um pouco o código.
fonte
Aqui está uma implementação do Sieve de Eratóstenes em 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 }
fonte
Usando o mesmo algoritmo, você pode fazer um pouco mais curto:
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); }
fonte
Eu sei que você pediu uma solução não-Haskell, mas estou incluindo isso aqui, pois se refere à pergunta e também Haskell é bonito para esse tipo de coisa.
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
fonte
Escrevi uma implementação simples de Eratóstenes em c # usando LINQ.
Infelizmente o LINQ não fornece uma sequência infinita de ints, então você deve usar int.MaxValue :(
Tive que armazenar em cache em um tipo anônimo o sqrt candidato para evitar calculá-lo para cada primo armazenado em cache (parece um pouco feio).
Eu uso uma lista de primos anteriores até sqrt do candidato
cache.TakeWhile(c => c <= candidate.Sqrt)
e verifique cada Int começando de 2 contra ele
.Any(cachedPrime => candidate.Current % cachedPrime == 0)
Aqui está o 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; } }
Outra otimização é evitar a verificação de números pares e retornar apenas 2 antes de criar a Lista. Dessa forma, se o método de chamada pedir apenas 1 primo, ele evitará toda a confusão:
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; } }
fonte
Para torná-lo mais elegante, você deve refatorar seu teste IsPrime em um método separado e lidar com o loop e incrementos fora dele.
fonte
Fiz isso em Java usando uma biblioteca funcional que escrevi, mas como minha biblioteca usa os mesmos conceitos de Enumerações, tenho certeza de que o código é adaptável:
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; } }); } });
fonte
Este é o mais elegante que consigo pensar em pouco tempo.
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 isso ajude você a ter uma ideia. Tenho certeza de que isso pode ser otimizado, mas deve dar uma ideia de como sua versão poderia ser mais elegante.
EDIT: Conforme observado nos comentários, este algoritmo realmente retorna valores errados para numberToGenerate <2. Eu só quero salientar que não estava tentando postar para ele um ótimo método para gerar números primos (veja a resposta de Henri para isso), Eu estava claramente apontando como seu método poderia ser mais elegante.
fonte
Usando programação baseada em fluxo em Functional Java , eu vim com o seguinte. O tipo
Natural
é essencialmente 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()));
Agora você tem um valor, que pode carregar, que é um fluxo infinito de números primos. Você pode fazer coisas assim:
// 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));
Uma explicação da peneira:
Você precisa ter as seguintes importações:
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;
fonte
Pessoalmente, acho que esta é uma implementação bastante curta e limpa (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; }
fonte
Tente esta consulta LINQ, ela gera números primos conforme você esperava
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();
fonte
// 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("");
fonte
Aqui está um exemplo de código Python que imprime a soma de todos os primos abaixo de dois milhões:
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
fonte
O método mais simples é a tentativa e erro: você tenta se qualquer número entre 2 e n-1 divide seu primo candidato n.
Os primeiros atalhos são, obviamente, a) você só precisa verificar os números ímpares eb) você só precisa verificar os divisores até sqrt (n).
No seu caso, em que você também gera todos os primos anteriores no processo, você só precisa verificar se algum dos primos em sua lista, até sqrt (n), divide n.
Deve ser o mais rápido que você pode conseguir com seu dinheiro :-)
editar
Ok, código, você pediu. Mas estou avisando :-), este é um código Delphi de 5 minutos rápidos e sujos:
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;
fonte
Para descobrir os primeiros 100 números primos, considere o seguinte 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);
fonte
Eu consegui isso pela primeira vez em que li "Sieve of Atkin" no Wikki, além de algumas reflexões anteriores que dei a isso - eu gasto muito tempo codificando do zero e fico totalmente zerado com as pessoas que criticam minha codificação semelhante a um compilador e muito densa style + Eu nem fiz uma primeira tentativa de rodar o código ... muitos dos paradigmas que aprendi a usar estão aqui, apenas leia e chore, pegue o que puder.
Esteja absolutamente e totalmente certo de realmente testar tudo isso antes de qualquer uso, com certeza não mostre a ninguém - é para ler e considerar as idéias. Preciso fazer a ferramenta de primalidade funcionar, então é aqui que começo sempre que preciso fazer algo funcionar.
Faça uma compilação limpa e comece a remover o que está com defeito - eu tenho quase 108 milhões de pressionamentos de teclas de código utilizável fazendo isso dessa maneira ... use o que puder.
Vou trabalhar na minha versão amanhã.
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
fonte
Experimente 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(); }
Aqui está o 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: 10.000 números primos em menos de um segundo
100.000 números primos em 63 segundos
Captura de tela dos primeiros 100 números primos
fonte
isPrimeNubmer
fato implementa a divisão tril subótima; suas assimptotípicas irão piorar para cerca de n ^ 2 (ou até acima disso) quando você tentar gerar ainda mais primos.