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.
[quote=thingol]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.
[/quote]
Nossa cara o java me parece ser um pouco burocratico para números com [b]exatidão/b …
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 …
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.
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.)
[quote=thingol]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.
[/quote]
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.
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.
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
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.
[quote=sergiotaborda]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)
[/quote]
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?
É 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.