12

¿Por qué si uso BigDecimal en este caso, no obtengo el resultado esperado?

double value1 = 5.68;
double value2 = 2.45;
System.out.println(BigDecimal.valueOf(value1 + value2));

SALIDA:

8.129999999999999

ESPERADO:

8.13
Jordi Castilla
  • 7,189
  • 10
  • 35
  • 60

3 Answers3

15

Lo que pasa es que estas haciendo la suma de los double no de los BigDecimal

Te recomiendo esto en su lugar

double value1 = 5.68;
double value2 = 2.45;
System.out.println(BigDecimal.valueOf(value1).add(BigDecimal.valueOf(value2)));

De esta forma cada número es convertido primero en un BigDecimal antes de realizar la suma.

Como el operador + no funciona con BigDecimal se debe usar el método .add() en su lugar

Carlos Muñoz
  • 12,864
  • 2
  • 42
  • 62
  • Aunque esto funcione, explicar exactamente por qué me parece bastante más difícil que usar `String`: `BigDecimal.valueOf("5.68").add(BigDecimal.valueOf("2.45"))`. – Peter Taylor Dec 16 '15 at 17:05
5

Cuando uses BigDecimal, conviene usar siempre los constructores y métodos que no usen el tipo double, ya que, como supongo ya sabes, el tipo double no tiene representaciones exactas para muchos números que tienen representación exacta en base 10.

Para tu ejemplo, podrías usar:

/* Usa valueOf(long valorSinEscalar, int escala) */
long value1 = 568;
long value2 = 245;
System.out.println(BigDecimal.valueOf(value1 + value2, 2));

o tal vez:

/* Usa el constructor BigDecimal(long valorSinEscalar, int escala) */
BigDecimal value1 = BigDecimal.valueOf(568, 2);
BigDecimal value2 = BigDecimal.valueOf(245, 2);
System.out.println(value1.add(value2));

o este otro:

/* Usa el constructor BigDecimal(String valor) */
BigDecimal value1 = new BigDecimal("5.68");
BigDecimal value2 = new BigDecimal("2.45");
System.out.println(value1.add(value2));

Nótese que hay una versión de estos constructores con un parámetro adicional MathContext, que permite seleccionar el modo de redondeo.

ninjalj
  • 1,087
  • 8
  • 14
1

Puesto que la pregunta es sobre redondeo utilizando BigDecimal, solo debes usar el método BigDecimal#setScale(int, RoundingMode):

System.out.println(BigDecimal.valueOf(value1 + value2).setScale(2, RoundingMode.HALF_EVEN));

El resultado será:

8.13

Puedes ver un ejemplo de esto corriendo en ideone.

Obviamente, no significa que esta es la forma de proceder con las operaciones decimales. Lo mejor sería seguir el ejemplo brindado en la respuesta de @ninjalj, donde si vas a utilizar números decimales, inicialices BigDecimal utilizando cadenas en lugar de double:

/* Usa el constructor BigDecimal(String valor) */
BigDecimal value1 = new BigDecimal("5.68");
BigDecimal value2 = new BigDecimal("2.45");
System.out.println(value1.add(value2));

De todas maneras, si las operaciones de arriba deben tener un número fijo de decimales, utiliza setScale.