Boa tarde galera,
estava trabalhando com um probleminha aqui que inclui cálculo de raiz e depois de um tempo quebrando a cabeça percebi que o java (pelo menos usando netbeans) tem problema ao calcular raiz na quinta potência maiores que 5.
Estou resolvendo um problema que depende da resolução da raiz e não estava dando certo, aí depois de um tempo notei que a partir do número 6 o java não dá o resultado exato da raiz. Eu dei um System.out.println(Math.pow(7776,1.0/5.0)), e o resultado deveria ser 6, já que esse número é igual a 6^5 , mas o java retorna 6.000000000000001. E para os números seguintes acontece a mesma coisa…
Isso está dificultando a minha vida, alguém sabe alguma coisa a respeito? como posso contornar? XD
vlw.
Isto acontece não por causa do java mas sim por uma lei matemática. Onde em uma operação de um número inteiro e um real o resultado sempre será um número real.
Segue abaixo a utilização do método da classe Math o round. Ele arredonda um número decimal e retorna um long:
System.out.println(Math.round(Math.pow(7776,1.0/5.0)));
Ok, sim, a lei matemática faz sentido, mas o número real que o java está me retornando é um número errado. O número que deveria ser retornado seria 6.000000000 não seria?
Eu fiz esse teste usando a linguagem C++ e ele me retornou um número inteiro (: …
Mas então, eu não posso arredondar o número, porque eu faço outra coisa com ele. O que eu faço é Math.pow(i, 0.2)%1==0), a fim de verificar se a raiz na quinta potência do número corrente é uma raiz exata. Sendo assim, se eu arrendondar o número isso não vai dar muito certo 
Alguma outra coisa que eu possa fazer?
obs: (Eu não faço isso em C/C++ porque o C++ não me permite fazer essa comparação com o % , pois nessa linguagem eu só posso fazer essa comparação entre números inteiros, já o java me permite usar o % entre números reais e inteiros (: ).
Acho que consegui resolver…
Estou salvando o valor resultante de do operação em uma variável float com um cast.
variavelfloat = (float) Math.pow(7776,1.0/5.0);
Funciona bem. (:
Pois é galera, havia fechado o o tópico agora a pouco pois achei que já tinha resolvido, mas nem tudo são flores.
O contorno acima funciona para os números menores, mas quando chega há números muito grandes esse método é falho. Por exemplo:
Seu eu fizer isso:
catw = (float) Math.pow(i,q);
if (catw%1==0)
O seguinte intervalo será avaliado como true:
divisivel por 5 254803968 = 48.000000000000014
divisivel por 5 254803969 = 48.00000003767603
divisivel por 5 254803970 = 48.000000075352055
divisivel por 5 254803971 = 48.00000011302808
divisivel por 5 254803972 = 48.000000150704096
divisivel por 5 254803973 = 48.00000018838012
divisivel por 5 254803974 = 48.000000226056144
divisivel por 5 254803975 = 48.00000026373216
divisivel por 5 254803976 = 48.000000301408186
divisivel por 5 254803977 = 48.00000033908421
divisivel por 5 254803978 = 48.00000037676023
divisivel por 5 254803979 = 48.00000041443625
divisivel por 5 254803980 = 48.000000452112275
divisivel por 5 254803981 = 48.00000048978829
divisivel por 5 254803982 = 48.00000052746431
divisivel por 5 254803983 = 48.00000056514033
divisivel por 5 254803984 = 48.00000060281636
divisivel por 5 254803985 = 48.000000640492374
divisivel por 5 254803986 = 48.00000067816839
divisivel por 5 254803987 = 48.000000715844415
divisivel por 5 254803988 = 48.00000075352043
divisivel por 5 254803989 = 48.000000791196456
divisivel por 5 254803990 = 48.00000082887247
divisivel por 5 254803991 = 48.00000086654849
divisivel por 5 254803992 = 48.000000904224514
divisivel por 5 254803993 = 48.00000094190053
divisivel por 5 254803994 = 48.000000979576555
divisivel por 5 254803995 = 48.00000101725257
divisivel por 5 254803996 = 48.00000105492859
divisivel por 5 254803997 = 48.000001092604606
divisivel por 5 254803998 = 48.00000113028063
divisivel por 5 254803999 = 48.00000116795665
divisivel por 5 254804000 = 48.000001205632664
divisivel por 5 254804001 = 48.00000124330869
divisivel por 5 254804002 = 48.000001280984705
divisivel por 5 254804003 = 48.00000131866072
divisivel por 5 254804004 = 48.00000135633674
divisivel por 5 254804005 = 48.000001394012756
divisivel por 5 254804006 = 48.00000143168877
divisivel por 5 254804007 = 48.00000146936479
divisivel por 5 254804008 = 48.00000150704081
divisivel por 5 254804009 = 48.000001544716824
divisivel por 5 254804010 = 48.00000158239285
divisivel por 5 254804011 = 48.000001620068865
divisivel por 5 254804012 = 48.00000165774488
divisivel por 5 254804013 = 48.0000016954209
divisivel por 5 254804014 = 48.000001733096916
divisivel por 5 254804015 = 48.00000177077293
divisivel por 5 254804016 = 48.00000180844895
divisivel por 5 254804017 = 48.00000184612497
divisivel por 5 254804018 = 48.00000188380098
Onde o número após o “divisil por 5” é o " i " e o número após o ’ = ’ é o número double, sem o cast para float.
Alguém sabe alguma outra solução?
Conversa. Vou lhe mostrar que o tal número inteiro não é inteiro em C++ e o seu problema não é o Java e sim que você não está entendendo a parte de fazer contas com ponto-flutuante.
#include <stdio.h>
#include <math.h>
int main (int argc, char *argv[]) {
double d = pow (7776, 1.0 / 5.0);
double e = d - 6.0;
// O equivalente exato, no C, de :
// System.out.println(Math.pow(7776,1.0/5.0))
// eh:
printf ("%.15f\n", d); // imprime 6.000000000000001
// Para comprovar que esse 1 nao eh um erro de impressao, vamos achar a diferenca em
// relacao ao resultado esperado:
printf ("%e\n", e); // imprime 8.881784e-016
// Ou seja, na verdade foi calculado o valor "6.0000000000000008881784"
}
E quando você faz as contas com float (4 bytes) em vez de double ( 8 ), você piora a sua situação, em vez de melhorá-la.
Mais uma coisinha. Qual é seu problema? É o de determinar se um número inteiro tem uma raiz sexta (por exemplo) inteira? Isso deve ser feito de uma maneira semelhante a esta (não separei a parte importante em uma função - você deve identificar as duas linhas, no código abaixo, que fazem o teste correto), se você precisar usar números de ponto-flutuante em vez de números “BigInteger”.
class TestePotencia {
public static void main (String[] args) {
for (int i = 1; i < 100000000; ++i) {
double d = Math.pow (i, 1.0 / 6.0);
if (Math.pow (Math.round (d), 6.0) == i) {
System.out.printf ("%d %f\n", i, d);
}
}
}
}
A saída do programa acima é:
1 1.000000
64 2.000000
729 3.000000
4096 4.000000
15625 5.000000
46656 6.000000
117649 7.000000
262144 8.000000
531441 9.000000
1000000 10.000000
1771561 11.000000
2985984 12.000000
4826809 13.000000
7529536 14.000000
11390625 15.000000
16777216 16.000000
24137569 17.000000
34012224 18.000000
47045881 19.000000
64000000 20.000000
85766121 21.000000
Note que para números um pouco grandes, mesmo fazer isso não funciona muito bem, devido à precisão limitada de um double.
Pois é, eu apenas dei um print em pow (7776, 1.0 / 5.0); e o C me retornou o número inteiro achei que estivesse certo, mas você tem razão \o.
De qualquer forma, não é possível então eu fazer essa validação? Extrair a raiz na quinta potência de um número muito grande e verificar se é uma raiz exata.
Vlw pela explicação (:
[quote=entanglement]Mais uma coisinha. Qual é seu problema? É o de determinar se um número inteiro tem uma raiz sexta (por exemplo) inteira? Isso deve ser feito de uma maneira semelhante a esta (não separei a parte importante em uma função - você deve identificar as duas linhas, no código abaixo, que fazem o teste correto), se você precisar usar números de ponto-flutuante em vez de números “BigInteger”.
[/quote]
Obrigado entanglement. Essa solução funcionou bem pra mim.
Sim, é mais ou menos isso que eu queria fazer, pegar um número e ver se a raiz quinta dele é exata. Isso na verdade é parte de um outro problema, mas essa solução que vc me passou a principio funciona, e também as explicações acima me esclareceram algumas coisas sobre representação que me serão úteis.
vlw (:
abraço.