Lo que me gustaría es un método para convertir un doble en una cadena que redondee utilizando el método de la mitad hacia arriba - es decir, si el decimal a redondear es 5, siempre redondea hacia arriba al siguiente número. Este es el método estándar de redondeo que la mayoría de la gente espera en la mayoría de las situaciones.
También me gustaría que sólo se mostraran los dígitos significativos, es decir, que no hubiera ceros al final.
Sé que un método para hacer esto es utilizar el método String.format
:
String.format("%.5g%n", 0.912385);
devuelve:
0.91239
lo cual está muy bien, pero siempre muestra números con 5 decimales aunque no sean significativos:
String.format("%.5g%n", 0.912300);
devuelve:
0.91230
Otro método es utilizar el DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
devuelve:
0.91238
Sin embargo, como puede ver, esto utiliza el redondeo medio par. Es decir, redondeará hacia abajo si el dígito anterior es par. Lo que me gustaría es esto:
0.912385 -> 0.91239
0.912300 -> 0.9123
¿Cuál es la mejor manera de lograr esto en Java?
Utilice setRoundingMode
, establezca el RoundingMode
explícitamente para manejar su problema con la ronda media, luego utilice el patrón de formato para su salida requerida.
Ejemplo:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
da la salida:
12
123.1235
0.23
0.1
2341234.2125
EDIT: La respuesta original no aborda la precisión de los valores dobles. Eso está bien si no te importa mucho si se redondea hacia arriba o hacia abajo. Pero si quieres un redondeo preciso, entonces tienes que tener en cuenta la precisión esperada de los valores. Los valores de coma flotante tienen una representación binaria interna. Eso significa que un valor como 2,77395 no tiene realmente ese valor exacto internamente. Puede ser ligeramente mayor o ligeramente menor. Si el valor interno es ligeramente menor, entonces no se redondeará a 2,7740. Para remediar esta situación, debe ser consciente de la precisión de los valores con los que trabaja y sumar o restar ese valor antes de redondear. Por ejemplo, si sabe que sus valores son precisos hasta 6 dígitos, entonces para redondear los valores a la mitad, añada esa precisión al valor:
Double d = n.doubleValue() + 1e-6;
Para redondear hacia abajo, reste la precisión.
Asumiendo que valor
es un doble
, se puede hacer:
(double)Math.round(value * 100000d) / 100000d
Eso's para 5 dígitos de precisión. El número de ceros indica el número de decimales.