java - quitar - Redondear un doble a 2 lugares decimales
redondear decimales en java netbeans (13)
Aquí hay una utilidad que redondea (en lugar de truncar ) un doble a un número específico de lugares decimales.
Por ejemplo:
round(200.3456, 2); // returns 200.35
Versión original; cuidado con esto
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
long factor = (long) Math.pow(10, places);
value = value * factor;
long tmp = Math.round(value);
return (double) tmp / factor;
}
Esto se descompone mal en los casos de esquina con un número muy alto de decimales (por ejemplo, round(1000.0d, 17)
) o parte entera de gran tamaño (por ejemplo, round(90080070060.1d, 9)
). Gracias a Sloin por señalar esto.
He estado usando lo anterior para redondear "no demasiado grandes" a 2 o 3 lugares decimales felizmente durante años (por ejemplo, para limpiar el tiempo en segundos para fines de registro: 27.987654321987 -> 27.99). Pero supongo que es mejor evitarlo, ya que hay formas más confiables disponibles, con código más limpio también.
Entonces, usa esto en su lugar
(Adaptado de esta respuesta por Louis Wasserman y esta por Sean Owen ).
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
Tenga en cuenta que HALF_UP
es el modo de redondeo "que se enseña comúnmente en la escuela". Lea detenidamente la documentación de RoundingMode , si sospecha que necesita algo más, como el redondeo de los banqueros .
Por supuesto, si lo prefiere, puede alinear lo anterior en una sola línea:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()
Y en cada caso
Siempre recuerde que las representaciones de punto flotante que usan float
y double
son inexactas . Por ejemplo, considera estas expresiones:
999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001
Para ser exactos, desea utilizar BigDecimal . Y mientras lo hace, use el constructor que toma una Cadena, nunca el que toma el doble. Por ejemplo, intente ejecutar esto:
System.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));
Algunas excelentes lecturas adicionales sobre el tema:
- Punto 48: "Evite
float
ydouble
si se requieren respuestas exactas" en Effective Java (2nd ed) por Joshua Bloch - Lo que todo programador debe saber sobre la aritmética de punto flotante
Si deseaba el formato de cadena en lugar de (o además de) redondear estrictamente los números, consulte las otras respuestas.
Específicamente, tenga en cuenta que la round(200, 0)
devuelve 200.0
. Si desea generar " 200.00 ", primero debe redondear y luego formatear el resultado para la salida (que se explica perfectamente en la respuesta de Jesper ).
Esta pregunta ya tiene una respuesta aquí:
- Cómo redondear un número a n lugares decimales en Java 29 respuestas
Si el valor es 200.3456
, debe formatearse a 200.34
. Si es 200
, entonces debería ser 200.00
.
Creo que esto es más fácil:
double time = 200.3456;
DecimalFormat df = new DecimalFormat("#.##");
time = Double.valueOf(df.format(time));
System.out.println(time); // 200.35
Tenga en cuenta que esto hará el redondeo por usted, no solo el formato.
En tu pregunta, ¿parece que también quieres evitar redondear los números? Creo que .format () redondeará los números usando half-up, afaik?
Entonces, si quieres redondear, 200.3456 debería ser 200.35 para una precisión de 2. Pero en tu caso, si solo quieres los primeros 2 y luego descartas el resto.
Puede multiplicarlo por 100 y luego convertir a un int (o tomar el piso del número), antes de dividir por 100 nuevamente.
200.3456 * 100 = 20034.56;
(int) 20034.56 = 20034;
20034/100.0 = 200.34;
Sin embargo, puede que tengas problemas con números realmente grandes cerca del límite. En cuyo caso, la conversión a una cadena y una subcadena funcionaría con la misma facilidad.
La forma más fácil, sería hacer un truco como este;
double val = ....;
val = val*100;
val = Math.round(val);
val = val /100;
si val comienza en 200.3456, luego pasa a 20034.56, luego se redondea a 20035 y luego lo dividimos para obtener 200.34.
Si quisieras redondear hacia abajo siempre podríamos truncarlo lanzando a un int:
double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;
Esta técnica funcionará en la mayoría de los casos, ya que para los dobles muy grandes (positivos o negativos) puede desbordarse. pero si sabe que sus valores estarán en un rango apropiado, entonces esto debería funcionar para usted.
Para dos dígitos de redondeo. Muy simple y básicamente está actualizando la variable en lugar de solo mostrar los propósitos que hace DecimalFormat.
x = Math.floor(x * 100) / 100;
Por favor use Apache commons math :
Precision.round(10.4567, 2)
Redondear un doble no suele ser lo que uno quiere. En su lugar, use String.format()
para representarlo en el formato deseado.
Si realmente desea el mismo doble, pero redondeado de la forma que desea, puede usar BigDecimal, por ejemplo
new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
Si solo desea imprimir un double
con dos dígitos después del punto decimal, use algo como esto:
double value = 200.3456;
System.out.printf("Value: %.2f", value);
Si desea tener el resultado en una String
lugar de imprimirse en la consola, use String.format()
con los mismos argumentos:
String result = String.format("%.2f", value);
O use la clase DecimalFormat
:
DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));
double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);
double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(value));
function Double round2(Double val) {
return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}
Tenga en cuenta la toString () !!!!
¡Esto se debe a que BigDecimal convierte la forma binaria exacta del doble!
Estos son los diversos métodos sugeridos y sus casos de falla.
// Always Good!
new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue()
Double val = 260.775d; //EXPECTED 260.78
260.77 - WRONG - new BigDecimal(val).setScale(2,RoundingMode.HALF_UP).doubleValue()
Double val = 260.775d; //EXPECTED 260.78
260.77 - TRY AGAIN - Math.round(val * 100.d) / 100.0d
Double val = 256.025d; //EXPECTED 256.03d
256.02 - OOPS - new DecimalFormat("0.00").format(val)
// By default use half even, works if you change mode to half_up
Double val = 256.025d; //EXPECTED 256.03d
256.02 - FAIL - (int)(val * 100 + 0.5) / 100.0;
value = (int)(value * 100 + 0.5) / 100.0;