Qual o melhor modo de testar se um número é primo?
27 respostas
DavidUser
Gente meu objetivo era testar de 1 a 2 milhões quais são os primos então o objetivo é encontrar o modo mais rápido para a máquina processar julgando se o número é primo ou não meu método é esse:
public static boolean primos(long x){
int z=0;
boolean res;
for(long i=1;i<=x;i++)if((x%i)==0)z++;//adiciona o numero de divisores perfeitos para x
return((z==2)? true:false);//se é divisivel por apenas 2 números(é primo:1 e ele mesmo)retorna seu valor
}
Existe algum pacote que teste mais rápido pois do modo que estou fazendo vai demorar muito! pra terminar a execução! :?
:x
Não é o mesmo do outro tópico!
O problema é que aki eu não tenho que calcular os fatores primos mais tenho de somar todos os primos existentes de 1 a 2000000 exemplo com números menores:
de 1 a 10
2+3+5+7=17
se eu fizer a raiz do número a soma não sera a mesma olha:
de 1 a 100(a raiz se 100 é 10)
publicstaticbooleanprimos(longx){if(x==1){//1écasoespecial,enãoéprimoreturnfalse;}
//sabemosqueo1édivisordetodososnúmeros,podemoscomeçaraprocurarnodois//bastapercorreralistaatéx/2.Omáximodivisorqueumnúmerotem,semserelepróprioéasuametade.
for(longi=2;i<=x/2;i++) { if((x%i)==0){
returnfalse; //Assim que encontra um divisor, sabe que o número não é primo.}
}
returntrue; //não encontrou divisores, o número é primo}
B
BrunoBastos
Na verdade você já tem um algoritmo eficiente naquele outro tópico.
E só para corrigir o pmlm em questão da eficiência, quando estamos falando de números primos você pode começar pela raiz quadrada do número, não precisa ser da metade. O que torna o algoritmo realmente bastante eficiente.
tnaires
O crivo de Eratóstenes funciona de forma eficiente para números primos menores que 10 milhões.
T
thingol
DavidUser:
Não é o mesmo do outro tópico!
O problema é que aki eu não tenho que calcular os fatores primos mais tenho de somar todos os primos existentes de 1 a 2000000 exemplo com números menores:
de 1 a 10
2+3+5+7=17
se eu fizer a raiz do número a soma não sera a mesma olha:
de 1 a 100(a raiz se 100 é 10)
O Bruno Bastos indicou o caminho correto: modifique o meu programa que acha os números primos, para poder calcular a soma.
Calcular essa soma de 1 até 2000000 vai levar cerca de 5 a 10 segundos, dependendo da velocidade do seu computador.
Não é necessário testar cada primo um por um; se fizer do jeito que você quer fazer, vai levar cerca de 10 a 15 horas, e isso não é legal.
DavidUser
BrunoBastos:
Na verdade você já tem um algoritmo eficiente naquele outro tópico.
E só para corrigir o pmlm em questão da eficiência, quando estamos falando de números primos você pode começar pela raiz quadrada do número, não precisa ser da metade. O que torna o algoritmo realmente bastante eficiente.
Dinovo!.. :x
se calulo os de 1 a 10: 2+3+5+7=17
ja os de 100 é bem diferente da muito mais intendeu! eu quero a soma de todos os primos entre eles.
T
thingol
De novo, vou mostrar o resultado pra você conferir se é isso mesmo.
A soma dos primos de 0 até 2.000.000 é 142.913.828.922 (use um long para fazer a totalização; esse número estoura um int).
Pela sua definição, 1 não é primo nem não-primo e não será considerado na somatória.
DavidUser
deu não!
usei o método de erastoteles e ficou em 999998000002
DavidUser
olha ai:
publicclassp10{publicBitSetbs;publicstaticvoidmain(String[]args){p10s=newp10();intnum=2000000;//num é o valor finallongsum=0;s.findprimes((int)num+1);for(inti=2;i<=num-2;i++)if(s.isprime(i)==true)sum+=i;System.out.println(sum);}//pelo método de erastoteles:publicvoidfindprimes(intn){bs=newBitSet(n+1);intpz=(int)Math.sqrt(n);bs.set(0,n);intx=2;//primo inícialwhile(x<=2){for(inti=x+x;i<=n;i+=x)bs.clear(i);x=bs.nextSetBit(x+1);}}publicbooleanisprime(intn){returnbs.get(n);}}
T
thingol
Teste sua rotina para n = 10 e n = 100, para ver se dá 17 ou 1020, conforme você mesmo postou.
Dica: você não copiou direito meu programa. Veja o que você fez no “while”.
E de qualquer maneira o grego chato que inventou o tal método é Eratóstenes, não Erastoteles (ele não é um mestiço de Aristóteles e Eros).
DavidUser
tem algo errado?
Lavieri
minha rotina....
publicclassNumerosPrimos{publicstaticbooleanisPrimo(intnumero){if(numero<2)returnfalse;booleanresult=true;intmetade=numero/2;for(inti=2;i<=metade;i++){if(numero%i==0){result=false;break;//putz tinha eskecido o break ... restartei agora ta + rapido}}returnresult;}publicstaticvoidmain(String...args){longsoma=0;for(inti=0;i<=2000000;i++)if(isPrimo(i)){soma+=i;System.out.println(i+": "+soma);}System.out.println(soma);}}
init:
deps-jar:
Compiling 1 source file to C:\Users\Administrador\Documents\NetBeansProjects\GujForunsTest\build\classes
compile-single:
run-single:
142913828922
CONSTRUÍDO COM SUCESSO (tempo total: 1 segundo)
Lavieri
posta o teu código… aki o meu demorou mais o.O, com o Crivo
Lavieri
publicstaticfinalint[]primos=newint[1000000];publicstaticintnext=0;publicstaticbooleanisPrimoOptimizade(intnumero){if(numero<2)returnfalse;intcount=0;while(primos[count]!=0&&//ou seja não há mais primos a testarprimos[count]*2<=numero){//com certeza não é divisivel pelos proximos primos...if(numero%primos[count]==0)returnfalse;count++;}primos[next++]=numero;//System.out.println("primos["+next+"] = " + numero);returntrue;}publicstaticvoidmain(String...args){longsoma=0;for(inti=0;i<=2000000;i++)if(isPrimoOptimizade(i)){soma+=i;//System.out.println(i + ": " + soma);}System.out.println(soma);}
run:
142913828922
CONSTRUÍDO COM SUCESSO (tempo total: 1 minuto 40 segundos)
DavidUser
publicclassp10{publicBitSetbs;publicstaticvoidmain(String[]args){p10s=newp10();intnum=2000000;//num é o valor finallongsum=0;s.findprimes(num+1);for(inti=2;i<=num-2;i++)if(s.isprime(i)==true)sum+=i;System.out.println(sum);}//pelo método de erastoteles:publicvoidfindprimes(intn){bs=newBitSet(n+1);intpz=(int)Math.sqrt(n);bs.set(0,n,true);intx=2;//primo inícialwhile(x<=pz){for(inti=x+x;i<=n;i+=x)bs.clear(i);x=bs.nextSetBit(x+1);}}publicbooleanisprime(intn){returnbs.get(n);}}
while(primos[count] != 0 && //ou seja não há mais primos a testar
primos[count] <= (int)Math.sqrt(numero)) { //com certeza não é divisivel pelos proximos primos...
agora foi em 1s
DavidUser
ai sabe como eu posso herdar todas as declarações de um método para um outro método que estão na mesma classe?
Lavieri
e sim, DavidUser, da pra ser mais eficiente ainda… so precisa testar os números impares… os pares já são primos…
então no lugar de incrementar o teste de 1 em 1… so iniciar do 3, e testar de 2 em 2