Redondear un doble a 2 decimales [duplicado]

Resuelto Rajesh asked hace 14 años • 13 respuestas

Si el valor es 200.3456, se debe formatear en 200.34. Si lo es 200, entonces debería serlo 200.00.

Rajesh avatar May 11 '10 13:05 Rajesh
Aceptado

Aquí hay una utilidad que redondea (en lugar de truncar ) un doble a un número específico de 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 falla gravemente en los casos extremos con un número muy alto de decimales (por ejemplo round(1000.0d, 17), ) o una parte entera grande (por ejemplo, round(90080070060.1d, 9)). Gracias a Sloin por señalar esto.

He estado usando lo anterior para redondear felizmente dobles "no demasiado grandes" a 2 o 3 decimales durante años (por ejemplo, para limpiar el tiempo en segundos con fines de registro: 27.987654321987 -> 27.99). Pero supongo que es mejor evitarlo, ya que hay formas más confiables disponibles y también con un código más limpio.

Entonces, usa esto en su lugar

(Adaptado de esta respuesta de Louis Wasserman y ésta de Sean Owen ).

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    BigDecimal bd = BigDecimal.valueOf(value);
    bd = bd.setScale(places, RoundingMode.HALF_UP);
    return bd.doubleValue();
}

Tenga en cuenta que HALF_UPes 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 Bankers' Rounding .

Por supuesto, si lo prefiere, puede incluir lo anterior en una sola línea:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()

Y en todos los casos

Recuerde siempre que las representaciones de coma flotante que utilizan floaty doubleson inexactas . Por ejemplo, considere estas expresiones:

999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001

Para mayor exactitud, desea utilizar BigDecimal . Y mientras lo hace, use el constructor que toma un String, nunca el que toma double. Por ejemplo, intenta 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:

  • Ítem ​​48: "Evite floaty doublesi se requieren respuestas exactas" en Effective Java (2.ª ed.) de Joshua Bloch
  • Lo que todo programador debe saber sobre la aritmética de punto flotante

Si desea formatear cadenas en lugar de (o además de) números estrictamente redondeados, consulte las otras respuestas.

Específicamente, tenga en cuenta que round(200, 0)devuelve 200.0. Si desea generar " 200.00 ", primero debe redondear y luego formatear el resultado para la salida (lo cual se explica perfectamente en la respuesta de Jesper ).

Jonik avatar May 11 '2010 07:05 Jonik

Si solo desea imprimir un doublecon 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 Stringlugar de imprimirlo en la consola, utilícelo String.format()con los mismos argumentos:

String result = String.format("%.2f", value);

O usar clase DecimalFormat:

DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));
Jesper avatar May 11 '2010 06:05 Jesper