| Autor |
Mensagem |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 10:50:31
|
bdoweb
Thread.start()
![[Avatar]](/images/avatar/ed1f65a161ee1de13bf41dac2781af4f.jpg)
Membro desde: 31/10/2006 20:38:29
Mensagens: 29
Offline
|
Olá Pessoal,
bom como todo iniciante há sempre algumas dúvidas.
Bom eu tenho um método que implementa conforme abaixo:
Porém o resultado é uma dizima periódica de 0.19999999999999996 quando deveria me dar 0.2.
Com quais tipos de objetos devo trabalhar para obter números pecisos com Java?
Obrigado
|
|
|
 |
|
|
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 10:53:40
|
nbluis
GUJ Master
![[Avatar]](/images/avatar/f0682320ccbbb1f1fb1e795de5e5639a.jpg)
Membro desde: 27/05/2006 01:31:51
Mensagens: 1531
Localização: Porto Alegre - RS
Offline
|
java.math.BigDecimal
|
Luis Eduardo Bohrer
Any fool can write code that a computer can understand. Good programmers write code that humans can understand. |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 10:55:03
|
everson_z
Virtual Machine Man
![[Avatar]](/images/avatar/d240cb4a3e3d2ed5250ac2e1480422f0.jpg)
Membro desde: 05/07/2005 18:12:25
Mensagens: 590
Localização: SP - São Paulo
Offline
|
|
Primeiro pensamento POG Existe casos e casos!
Segundo pensamento POG Do meu jeito é mais fácil e rápido!
Primeira merda POG Fazer as merdas que muitos fizeram por defender o primeiro pensamento POG.
Segunda merda POG Limitar o projeto ao escopo inicial.
Terceira merda POG Se basear em absurdos para defender seu desenvolvimento.
Quarta merda POG Não entender que padrão é beneficio e usar o primeiro pensamento POG.
Quinta merda POG Achar um absurdo eu escrever isso. |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 10:59:10
|
thingol
Moderador
Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline
|
Como você deve saber, existe diferença entre "precisão" e "exatidão".
"Precisão" é a quantidade de dígitos, e "exatidão" é quão próximo está o resultado em relação ao resultado "real".
O "double" é preciso no Java com a precisão de 15 dígitos, ou seja, se o número tiver mais de 15 dígitos (0,199.999.999.999.999.96 tem 17 dígitos - não me pergunte porque o Java mostra mais dígitos que a sua precisão), você tem de arredondar para 15 dígitos para ter o resultado mais exato (ou seja, 0,200.000.000.000.000).
Para você fazer contas matematicamente exatas, você não pode usar ponto flutuante, e se for só contas de soma, subtração, multiplicação e divisão, por incrível que pareça você também não pode usar java.lang.BigDecimal; você precisa construir uma clsse que lida com frações a partir de java.lang.BigInteger. Por exemplo, para obter o resultado "exato" de 1 - 3 * (1 / 3), que é 0, não é suficiente usar BigDecimal (como você deve saber, a divisão em BigDecimal de 1/3 gera uma exceção porque esse número gera uma dízima periódica; mas se você limitar a precisão a, por exemplo, 15 casas, então 1 - 3 * (1 / 3) volta o número 0,000.000.000.000.001 que não é zero como você estava esperando se o resultado fosse exato.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 11:01:59
|
nielsen.tekla
Thread.start()
![[Avatar]](/images/avatar/005fa89da7d48e0c0cd6536000ed2cb5.jpg)
Membro desde: 16/07/2007 22:41:14
Mensagens: 31
Localização: Natal-RN
Offline
|
cara substitua double por float dai vai dar certo
float i = 1.2f;
float j = 1;
System.out.println(i-j);
|
Nielsen C. Damasceno |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 11:18:17
|
bdoweb
Thread.start()
![[Avatar]](/images/avatar/ed1f65a161ee1de13bf41dac2781af4f.jpg)
Membro desde: 31/10/2006 20:38:29
Mensagens: 29
Offline
|
thingol wrote:Como você deve saber, existe diferença entre "precisão" e "exatidão".
"Precisão" é a quantidade de dígitos, e "exatidão" é quão próximo está o resultado em relação ao resultado "real".
O "double" é preciso no Java com a precisão de 15 dígitos, ou seja, se o número tiver mais de 15 dígitos (0,199.999.999.999.999.96 tem 17 dígitos - não me pergunte porque o Java mostra mais dígitos que a sua precisão), você tem de arredondar para 15 dígitos para ter o resultado mais exato (ou seja, 0,200.000.000.000.000).
Para você fazer contas matematicamente exatas, você não pode usar ponto flutuante, e se for só contas de soma, subtração, multiplicação e divisão, por incrível que pareça você também não pode usar java.lang.BigDecimal; você precisa construir uma clsse que lida com frações a partir de java.lang.BigInteger. Por exemplo, para obter o resultado "exato" de 1 - 3 * (1 / 3), que é 0, não é suficiente usar BigDecimal (como você deve saber, a divisão em BigDecimal de 1/3 gera uma exceção porque esse número gera uma dízima periódica; mas se você limitar a precisão a, por exemplo, 15 casas, então 1 - 3 * (1 / 3) volta o número 0,000.000.000.000.001 que não é zero como você estava esperando se o resultado fosse exato.
Nossa cara o java me parece ser um pouco burocratico para números com exatidão(rs) ...
Não entendi muito bem como poderia utilizar o BigInteger você pode me dar um exemplo.
Bom a Sun disponibiliza alguma pacote para tratar de valores monetários ... Pois meu intuito é tratar de valores monetários ...
Muito Obrigado
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 11:25:22
|
thingol
Moderador
Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline
|
Para valores monetários você não precisa de exatidão (por incrível que pareça), só de precisão fixa (2 algarismos depois da vírgula), se você vai lidar só com centavos, ou 4 algarismos, dependendo do tipo de coisa que você vai fazer.
Nesse caso, é necessário saber se você precisa lidar com mais de 15 algarismos significativos (incluindo os centavos).
Se for precisar de mais de 15 algarismos (normalmente é porque você está interfaceando com alguma base que precisa de mais de 15 dígitos), então você precisa do tal BigDecimal, e saber que ele é um pouco chato para usar.
Se precisar de menos, use double mesmo, que é mais fácil e muito mais rápido, e lembre-se de mostrar os dados sempre corretamente formatados.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 11:27:38
|
thingol
Moderador
Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline
|
Outra coisa chata com double que já vou lhe avisando: dois valores double normalmente não podem ser comparados facilmente.
Por exemplo, 0.0 != 1.0 - 3.0 * (1.0 / 3.0) (é o tal exemplo chato que eu sempre dou).
Você precisa pôr uma tolerância (no seu caso de valores monetários, coisa de meio centavo de tolerância, para evitar ter de fazer análises muito complicadas de erros.)
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 11:37:04
|
bdoweb
Thread.start()
![[Avatar]](/images/avatar/ed1f65a161ee1de13bf41dac2781af4f.jpg)
Membro desde: 31/10/2006 20:38:29
Mensagens: 29
Offline
|
thingol wrote:Para valores monetários você não precisa de exatidão (por incrível que pareça), só de precisão fixa (2 algarismos depois da vírgula), se você vai lidar só com centavos, ou 4 algarismos, dependendo do tipo de coisa que você vai fazer.
Nesse caso, é necessário saber se você precisa lidar com mais de 15 algarismos significativos (incluindo os centavos).
Se for precisar de mais de 15 algarismos (normalmente é porque você está interfaceando com alguma base que precisa de mais de 15 dígitos), então você precisa do tal BigDecimal, e saber que ele é um pouco chato para usar.
Se precisar de menos, use double mesmo, que é mais fácil e muito mais rápido, e lembre-se de mostrar os dados sempre corretamente formatados.
Ahhh certo acho que entendi ... então vou poder usar números primitivos porém terei de formatar o numero igual everson_z escreveu lá em cima.
Muito obrigado
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 11:54:48
|
ricardosoares
JavaEvangelist
![[Avatar]](/images/avatar/1cc8a8ea51cd0adddf5dab504a285915.jpg)
Membro desde: 03/12/2004 09:49:13
Mensagens: 318
Localização: São Paulo, SP, Brasil
Offline
|
Para fins científicos, computação gráfica e afins, esse "detalhe" não passa de um detalhe. Não influi sensivelmente no resultado.
Já se tratando de dinheiro... é nessas horas que damos valor ao Cobol. Para esses fins, é fácil, preciso e confiável.
Em Java não encontrei outra saída senão trabalhar com o java.math.BigDecimal. Convenhamos: é um saco!
Bem, como eu sempre fui adepto da notação polonesa reversa (RPN), criei uma classe para facilitar o uso do BigDecimal com RPN conforme:
em notação algébrica: 1.2 - 1 =
em RPN : 1.2 = 1 -
com a classe RpnCalculator
| Nome do arquivo |
RpnCalculator.java |
Download
|
| Descrição |
RpnCalculator.java |
| Tamanho |
5 Kbytes
|
| Baixado: |
168 vez(es) |
|
Ricardo Soares |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 12:15:37
|
thingol
Moderador
Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline
|
De fato é mais fácil usar essa classe do Ricardo Soares que usar diretamente BigDecimal porque no caso de BigDecimal é necessário prestar atenção a um monte de coisas chatas. Por exemplo, quando você faz:
BigDecimal bd1 = new BigDecimal (0.2);
você cria um número diferente de
BigDecimal bd2 = new BigDecimal ("0.2");
Se você subtrair um número do outro, vai descobrir que a diferença é 0.000000000000000011102230246251565404236316680908203125, que não é zero como esperado.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 14:32:25
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline
|
Para trabalhar com dinheiro o melhor é usar o padrão Money.
É um classe que faz as vezes de bigdecimal mas usa um long internamente. Todos os calculos são feitos com numeros inteiros e portanto não ha problemas de arredondamento , já que a divisão é tratada de forma especial.
O dinheiro sempre é distribuido em unidades inteiras. Logo, dividir 100 reais por 3 pessoas é dar a cada um 33,33 centavos e ficar com um centado insdistribuivel. Centavos porque é a menor unidade monetária ( só que isso depende de moeda para moeda e se vc for usar moedas diferentes o seu objeto Money tem que ser mais inteligente, mas dá para fazer). A multiplicação tb é especial já que 3 * (1/3) == 3/3
Enfim, se está pensando em dinheiro use o padrão Money. Fica até mais claro que BigDecimal ou qq outra coisa, compare
paga ( BigDecimal valor)
paga (Money valor)
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/11/2007 14:35:08
|
thingol
Moderador
Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline
|
Se alguém conhece o tipo Currency do VB, vai ver que ele internamente é um long do Java (64 bits) com as contas feitas em centésimos de centavos (4 casas depois da vírgula). Por isso é semelhante ao padrão Money mencionado pelo Sergio Taborda.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 15/01/2008 18:08:53
|
ricardosoares
JavaEvangelist
![[Avatar]](/images/avatar/1cc8a8ea51cd0adddf5dab504a285915.jpg)
Membro desde: 03/12/2004 09:49:13
Mensagens: 318
Localização: São Paulo, SP, Brasil
Offline
|
sergiotaborda wrote:Para trabalhar com dinheiro o melhor é usar o padrão Money.
É um classe que faz as vezes de bigdecimal mas usa um long internamente. Todos os calculos são feitos com numeros inteiros e portanto não ha problemas de arredondamento , já que a divisão é tratada de forma especial.
O dinheiro sempre é distribuido em unidades inteiras. Logo, dividir 100 reais por 3 pessoas é dar a cada um 33,33 centavos e ficar com um centado insdistribuivel. Centavos porque é a menor unidade monetária ( só que isso depende de moeda para moeda e se vc for usar moedas diferentes o seu objeto Money tem que ser mais inteligente, mas dá para fazer). A multiplicação tb é especial já que 3 * (1/3) == 3/3
Enfim, se está pensando em dinheiro use o padrão Money. Fica até mais claro que BigDecimal ou qq outra coisa, compare
paga ( BigDecimal valor)
paga (Money valor)
A única classe chamada Money que encontrei foi uma presente no pacote do JUnit.
É a esta que vc ser refere ? Esta tem os métodos add, subtract e multiply. Falta o divide.
Rola uma no neoframework. Mas não encontrei o apidoc dela. Seria esta?
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 15/01/2008 18:40:12
|
thingol
Moderador
Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline
|
Ele está falando em "padrão", não "classe".
É que ele está dizendo, em resumo, que seria interessante que você criasse uma classe Money (ou sei lá que nome você quer dar a ela) que seguisse o padrão Money que ele está descrevendo.
|
|
|
 |
|
|