setscale - java bigdecimal add
Cómo redondear 0.745 a 0.75 usando BigDecimal.ROUND_HALF_UP? (5)
Esto tal vez le dará una pista sobre lo que salió mal.
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal bdTest = new BigDecimal(0.745);
BigDecimal bdTest1 = new BigDecimal("0.745");
bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP);
bdTest1 = bdTest1.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("bdTest:" + bdTest);
System.out.println("bdTest1:" + bdTest1);
}
}
El problema es que su entrada (un double x=0.745;
) no puede representar 0.745 exactamente. Realmente ahorra un valor ligeramente más bajo. Para BigDecimals
, esto ya está por debajo de 0.745, por lo que se redondea hacia abajo ...
Trate de no usar los BigDecimal(double/float)
.
Intenté lo siguiente,
double doubleVal = 1.745;
double doubleVal1 = 0.745;
BigDecimal bdTest = new BigDecimal( doubleVal);
BigDecimal bdTest1 = new BigDecimal( doubleVal1 );
bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP);
bdTest1 = bdTest1.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("bdTest:"+bdTest); //1.75
System.out.println("bdTest1:"+bdTest1);//0.74 problemmmm ????????????
pero obtuve resultados extraños. ¿Por qué?
Nunca construyas BigDecimales de carrozas o dobles. Constrúyelos a partir de enteros o cadenas. flota y dobla la precisión floja.
Este código funciona como se esperaba (acabo de cambiar el tipo de doble a Cadena):
public static void main(String[] args) {
String doubleVal = "1.745";
String doubleVal1 = "0.745";
BigDecimal bdTest = new BigDecimal( doubleVal);
BigDecimal bdTest1 = new BigDecimal( doubleVal1 );
bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP);
bdTest1 = bdTest1.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("bdTest:"+bdTest); //1.75
System.out.println("bdTest1:"+bdTest1);//0.75, no problem
}
Por su interés, haga lo mismo con el double
double doubleVal = 1.745;
double doubleVal2 = 0.745;
doubleVal = Math.round(doubleVal * 100 + 0.005) / 100.0;
doubleVal2 = Math.round(doubleVal2 * 100 + 0.005) / 100.0;
System.out.println("bdTest: " + doubleVal); //1.75
System.out.println("bdTest1: " + doubleVal2);//0.75
o solo
double doubleVal = 1.745;
double doubleVal2 = 0.745;
System.out.printf("bdTest: %.2f%n", doubleVal);
System.out.printf("bdTest1: %.2f%n", doubleVal2);
ambos imprimen
bdTest: 1.75
bdTest1: 0.75
Prefiero mantener el código lo más simple posible. ;)
Como señala @mshutov, debe agregar un poco más para asegurarse de que el valor medio siempre se redondee. Esto es porque los números como 265.335
son un poco menos de lo que parecen.
Use BigDecimal.valueOf(double d)
lugar del new BigDecimal(double d)
. El último tiene errores de precisión por flotante y doble.
double doubleVal = 1.745;
double doubleVal1 = 0.745;
System.out.println(new BigDecimal(doubleVal));
System.out.println(new BigDecimal(doubleVal1));
productos:
1.74500000000000010658141036401502788066864013671875
0.74499999999999999555910790149937383830547332763671875
Que muestra el valor real de los dos dobles y explica el resultado que obtienes. Como señalaron otros, no use el constructor doble (aparte del caso específico en el que desea ver el valor real de un doble).
Más sobre la doble precisión: