Eu tenho que calcular algumas variáveis de ponto flutuante e meu colega sugere que eu use em BigDecimal
vez de, double
pois será mais preciso. Mas quero saber o que é e como tirar o máximo proveito BigDecimal
?
java
floating-point
double
bigdecimal
Truong Ha
fonte
fonte
Respostas:
A
BigDecimal
é uma maneira exata de representar números. ADouble
tem uma certa precisão. Trabalhar com dobras de várias magnitudes (digamosd1=1000.0
ed2=0.001
) pode resultar em uma0.001
queda total ao somar uma vez que a diferença de magnitude é muito grande. ComBigDecimal
isso não aconteceria.A desvantagem
BigDecimal
é que é mais lento e é um pouco mais difícil programar algoritmos dessa maneira (devido+
-
*
e/
sem sobrecarregar).Se você está lidando com dinheiro, ou a precisão é uma obrigação, use
BigDecimal
. Caso contrário,Doubles
tendem a ser bons o suficiente.Eu recomendo a leitura do javadoc de
BigDecimal
como eles fazem explicar as coisas melhor do que eu aqui :)fonte
if (Math.abs(loadPerServer - maxLoadPerServer) < 0.000001d) {
BigDecimal
", um Double teria mais "precisão" (mais dígitos).Meu inglês não é bom, então vou escrever um exemplo simples aqui.
Saída do programa:
Alguém ainda quer usar o dobro? ;)
fonte
System.out.println(0.003f - 0.002f);
BigDecimal é exata:System.out.println(new BigDecimal("0.003").subtract(new BigDecimal("0.002")));
Existem duas diferenças principais em relação ao dobro:
O motivo pelo qual você deve usar o BigDecimal para cálculos monetários não é que ele possa representar qualquer número, mas que ele possa representar todos os números que podem ser representados na noção decimal e que incluem praticamente todos os números do mundo monetário (você nunca transfere 1/3 $ para alguém).
fonte
Se você escrever um valor fracionário como
1 / 7
valor decimal, obtémcom uma sequência infinita de
142857
. Como você só pode escrever um número finito de dígitos, inevitavelmente introduzirá um erro de arredondamento (ou truncamento).Números como
1/10
ou1/100
expressos como números binários com uma parte fracionária também têm um número infinito de dígitos após o ponto decimal:Doubles
armazene valores como binários e, portanto, poderá introduzir um erro apenas convertendo um número decimal em um número binário, sem fazer aritmética.Os números decimais (como
BigDecimal
), por outro lado, armazenam cada dígito decimal como está. Isso significa que um tipo decimal não é mais preciso que um ponto flutuante binário ou tipo de ponto fixo em um sentido geral (ou seja, não pode ser armazenado1/7
sem perda de precisão), mas é mais preciso para números que tenham um número finito de dígitos decimais como é frequentemente o caso dos cálculos de dinheiro.O Java
BigDecimal
tem a vantagem adicional de poder ter um número arbitrário (mas finito) de dígitos em ambos os lados do ponto decimal, limitado apenas pela memória disponível.fonte
BigDecimal é a biblioteca numérica de precisão arbitrária da Oracle. O BigDecimal faz parte da linguagem Java e é útil para uma variedade de aplicativos que variam do financeiro ao científico (é aí que estou).
Não há nada de errado em usar o dobro para determinados cálculos. Suponha, no entanto, que você queira calcular Math.Pi * Math.Pi / 6, ou seja, o valor da função Riemann Zeta para um argumento real de dois (um projeto no qual estou trabalhando atualmente). A divisão de ponto flutuante apresenta um problema doloroso de erro de arredondamento.
O BigDecimal, por outro lado, inclui muitas opções para calcular expressões com precisão arbitrária. Os métodos de adição, multiplicação e divisão, conforme descrito na documentação do Oracle abaixo "substituem", +, * e / no BigDecimal Java World:
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
O método compareTo é especialmente útil em loops while e for.
Tenha cuidado, no entanto, ao usar construtores para BigDecimal. O construtor de strings é muito útil em muitos casos. Por exemplo, o código
BigDecimal onethird = new BigDecimal ("0.33333333333");
utiliza uma representação em cadeia de 1/3 para representar esse número de repetição infinita com um grau especificado de precisão. O erro de arredondamento provavelmente está em algum lugar tão profundo na JVM que os erros de arredondamento não perturbarão a maioria dos seus cálculos práticos. Eu, por experiência própria, vi o arredondamento surgir, no entanto. O método setScale é importante nesses aspectos, como pode ser visto na documentação do Oracle.
fonte
/* * Portions Copyright IBM Corporation, 2001. All Rights Reserved. */
Se você está lidando com cálculos, existem leis sobre como você deve calcular e qual precisão você deve usar. Se você falhar, estará fazendo algo ilegal. A única razão real é que a representação de bits das casas decimais não é precisa. Como Basil simplesmente coloca, um exemplo é a melhor explicação. Apenas para complementar seu exemplo, eis o que acontece:
Resultado:
Também temos que:
Nos dá a saída:
Mas:
Possui a saída:
fonte