Precisión en Java: BigDecimal

Publicado en Java el 17 de October, 2007 por Lek.

No sé si lo sabéis, pero la máquina virtual de Sun es como Excel y de números sabe lo justo. Por eso, si en vuestros proyectos estáis utilizando valores de tipo double la estáis cagando, deberíais utilizar BigDecimal, que tiene más precisión y no comete errores de bulto al multiplicar 141’48 por 100 y cosas así.

Imaginemos el siguiente código:

int total = 5642;
String valor = "878";
Math.rint ((Double.parseDouble (valor) * 100 / total) * 100) / 100;

Lo que hace este código es calcular qué porcentaje sobre 100 representa valor sobre total y redondear el resultado a 2 decimales. Es el ejemplo típico que encontraréis si buscáis cómo redondear.

Nos quedaría algo como esto una vez utilizada la nueva clase:

int total = 5642;
String valor = "878";
(new BigDecimal (valor).multiply (new BigDecimal (100)).divide (
	new BigDecimal (total), 2, BigDecimal.ROUND_HALF_EVEN)).doubleValue ();

Multiplicamos valor por 100 y dividimos por total, con 2 decimales (escala) con redondeo. Aunque aún podemos ser un pelín más exactos:

int total = 5642;
String valor = "878";
(new BigDecimal (valor).multiply (new BigDecimal ("100")).divide (
	new BigDecimal (String.valueOf (total)), 2,
		BigDecimal.ROUND_HALF_EVEN)).doubleValue ();

Ver explicación de porqué utilizar String en lugar de valores númericos al crear un BigDecimal

Tranquilos, sólo tendréis que revisar todos los programas que hayáis realizado desde el principio de los tiempos. No me odiéis a mí, sólo soy el mensajero.

6 comentarios

  1. Yo leí hace tiempo por algún sitio que el tema de los números de coma flotante se trató de una manera peculiar en Java.

    Ya que si seguían el estándar IEEE lo-que-sea para el formato y tratamiento de números reales, obtenían tiempos muy altos y no se podían permitir aquello.

    Así que decidieron saltarse dicho estándar y hacerlo a su modo, lo que hace que en diferentes sistemas operaciones con números reales den diferentes resultados.

    #  Fran 17 de October, 2007

  2. En diferentes sistemas no, lo hacen mal en todos (Chuchi tiene Ubuntu y fue el que levantó la liebre en la empresa). Eso es igualdad xDDD

    La verdad es que es una gran cagada y algo que se debería avisar en letras bien grandes: NO USES DOUBLE EN JAVA

    #  lek 17 de October, 2007

  3. lek lo que quise decir es que da resultados diferentes en cada sistema, es decir, que el resultado en un sistema no es válido en otro, que es lo mismo que decir que lo hace mal en todos.

    #  Fran 17 de October, 2007

  4. [...] 22:14 Gracias a Federico Varela por recordarnos que el ejemplo era más inexacto que Java multiplicando doubles No se modificaba el valor de d al estar ya creando la nueva instancia en la función. Los he [...]

    #  Mutabilidad en Java | 4 bits blog 25 de February, 2008

  5. Cagada no, pero usa BigDecimal, en Java si comparas resultados con Matlab (lenguaje matematico), los decimales te empiezan a bailar a partir del tercer decimal. Asi q si, pensandolo mejor, es una cagada de JAVA!

    #  yuyu 23 de June, 2008

  6. Ahora si que me enojé! porque no me entero de esto antes…!!!

    #  Raul 30 de October, 2008

Escribe un comentario