Tengo que calcular algunas variables de punto flotante y mi colega me sugiere que lo use en BigDecimal
lugar de hacerlo, double
ya que será más preciso. ¿Pero quiero saber qué es y cómo aprovecharlo al máximo BigDecimal
?
java
floating-point
double
bigdecimal
Truong Ha
fuente
fuente
Respuestas:
A
BigDecimal
es una forma exacta de representar números. ADouble
tiene una cierta precisión. Trabajar con dobles de varias magnitudes (digamosd1=1000.0
yd2=0.001
) podría provocar que0.001
se caiga por completo al sumar, ya que la diferencia de magnitud es tan grande. ConBigDecimal
esto no sucedería.La desventaja de
BigDecimal
es que es más lento, y es un poco más difícil de algoritmos del programa de esa manera (debido a+
-
*
, y/
no se sobrecargue).Si está tratando con dinero, o la precisión es imprescindible, úsela
BigDecimal
. De lo contrario,Doubles
tienden a ser lo suficientemente buenos.Yo recomiendo la lectura del javadoc de
BigDecimal
como lo hacen explicar las cosas mejor que yo aquí :)fuente
if (Math.abs(loadPerServer - maxLoadPerServer) < 0.000001d) {
BigDecimal
", un Doble tendría más "precisión" (más dígitos).Mi inglés no es bueno, así que escribiré un ejemplo simple aquí.
Salida del programa:
¿Alguien todavía quiere usar el doble? ;)
fuente
System.out.println(0.003f - 0.002f);
BigDecimal es exacto:System.out.println(new BigDecimal("0.003").subtract(new BigDecimal("0.002")));
Hay dos diferencias principales con respecto al doble:
La razón por la que debe usar BigDecimal para los cálculos monetarios no es que pueda representar cualquier número, sino que puede representar todos los números que pueden representarse en noción decimal y que incluyen prácticamente todos los números en el mundo monetario (nunca transfiere 1/3 $ a alguien).
fuente
Si escribe un valor fraccionario como un valor
1 / 7
decimal, obtendrácon una secuencia infinita de
142857
. Como solo puede escribir un número finito de dígitos, inevitablemente introducirá un error de redondeo (o truncamiento).Los números similares
1/10
o1/100
expresados como números binarios con una parte fraccionaria también tienen un número infinito de dígitos después del punto decimal:Doubles
almacenar valores como binarios y, por lo tanto, podría introducir un error únicamente al convertir un número decimal en un número binario, sin siquiera hacer ninguna aritmética.Los números decimales (como
BigDecimal
), por otro lado, almacenan cada dígito decimal tal como está. Esto significa que un tipo decimal no es más preciso que un punto flotante binario o un tipo de punto fijo en un sentido general (es decir, no puede almacenar1/7
sin pérdida de precisión), pero es más preciso para números que tienen un número finito de dígitos decimales como A menudo es el caso de los cálculos de dinero.Java
BigDecimal
tiene la ventaja adicional de que puede tener un número arbitrario (pero finito) de dígitos en ambos lados del punto decimal, limitado solo por la memoria disponible.fuente
BigDecimal es la biblioteca numérica de precisión arbitraria de Oracle. BigDecimal es parte del lenguaje Java y es útil para una variedad de aplicaciones que van desde lo financiero a lo científico (ahí es donde estoy).
No hay nada de malo en usar dobles para ciertos cálculos. Sin embargo, suponga que desea calcular Math.Pi * Math.Pi / 6, es decir, el valor de la función Riemann Zeta para un argumento real de dos (un proyecto en el que estoy trabajando actualmente). La división de punto flotante le presenta un doloroso problema de error de redondeo.
BigDecimal, por otro lado, incluye muchas opciones para calcular expresiones con precisión arbitraria. Los métodos de agregar, multiplicar y dividir como se describe en la documentación de Oracle a continuación "toman el lugar" de +, * y / en BigDecimal Java World:
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
El método compareTo es especialmente útil en while y para bucles.
Sin embargo, tenga cuidado al usar constructores para BigDecimal. El constructor de cadenas es muy útil en muchos casos. Por ejemplo, el código
BigDecimal onethird = nuevo BigDecimal ("0.33333333333");
utiliza una representación de cadena de 1/3 para representar ese número que se repite infinitamente con un grado específico de precisión. Es muy probable que el error de redondeo esté en algún lugar tan profundo dentro de la JVM que los errores de redondeo no perturben la mayoría de sus cálculos prácticos. Sin embargo, por experiencia personal, he visto un avance gradual. El método setScale es importante a este respecto, como se puede ver en la documentación de Oracle.
fuente
/* * Portions Copyright IBM Corporation, 2001. All Rights Reserved. */
Si está tratando con el cálculo, existen leyes sobre cómo debe calcular y qué precisión debe usar. Si fallas, harás algo ilegal. La única razón real es que la representación en bits de los casos decimales no es precisa. Como dijo Basilio, la mejor explicación es un ejemplo. Solo para complementar su ejemplo, esto es lo que sucede:
Salida:
También tenemos que:
Nos da la salida:
Pero:
Tiene la salida:
fuente