Lo que me gustaría es un método para convertir un doble en una cadena que se redondea utilizando el método de la mitad hacia arriba, es decir, si el decimal a redondear es 5, siempre se redondea 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 solo se muestren dígitos significativos, es decir, no debería haber ceros a la izquierda.
Sé que un método para hacer esto es usar el String.formatmétodo:
String.format("%.5g%n", 0.912385);
devoluciones:
0.91239
lo cual es genial, sin embargo, siempre muestra números con 5 decimales, incluso si no son significativos:
String.format("%.5g%n", 0.912300);
devoluciones:
0.91230
Otro método es usar el DecimalFormatter:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
devoluciones:
0.91238
Sin embargo, como puede ver, esto usa redondeo a medias. Es decir, se 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?

"#.##"redondeoHALF_UP.256.335f->"256.33"... (el ejemplo proviene de los comentarios a la respuesta de @ asterite).Suponiendo que
valuees undouble, puede hacer:Eso es para una precisión de 5 dígitos. El número de ceros indica el número de decimales.
fuente
Math.round(0.1 * Math.pow(10,20))/Math.pow(10,20) == 0.09223372036854775.265.335realmente significa265.335 += tolerance, donde la tolerancia depende de las operaciones anteriores y el rango de valores de entrada. No sabemos el verdadero valor exacto. En los valores límite, cualquier respuesta es posiblemente correcta. Si necesitamos ser exactos, no deberíamos trabajar en doble. Elfailaquí no está en volver a convertir al doble. Está en OP pensando que puede confiar en que la entrada265.335sea exactamente eso.te conseguirá a
BigDecimal. Para obtener la cadena fuera de él, simplemente llamar a esoBigDecimal'stoStringmétodo o latoPlainStringmétodo para Java 5+ para una cadena sin formato.Programa de muestra:
fuente
new BigDecimal(doubleVar)ya que puede encontrarse con problemas con el redondeo de puntos flotantesdouble val = 265.335;,BigDecimal.valueOf(val).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();=>265.34, pero(new BigDecimal(val)).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();=>265.33.También puedes usar el
para asegurarte de que tienes los 0 finales.
fuente
RoundingMode.Decimal modeutilizaRoundingMode.HALF_EVEN.Como otros han notado, la respuesta correcta es usar cualquiera
DecimalFormatoBigDecimal. El punto flotante no tiene lugares decimales, por lo que no puede redondear / truncar a un número específico de ellos en primer lugar. Tienes que trabajar en una raíz decimal, y eso es lo que hacen esas dos clases.Estoy publicando el siguiente código como contraejemplo de todas las respuestas en este hilo y, de hecho, en todo StackOverflow (y en otros lugares) que recomiendan la multiplicación seguida del truncamiento seguido de la división. Corresponde a los defensores de esta técnica explicar por qué el siguiente código produce un resultado incorrecto en más del 92% de los casos.
Salida de este programa:
EDITAR: Para abordar algunos comentarios a continuación, rehice la parte del módulo del bucle de prueba usando
BigDecimalynew MathContext(16)para la operación del módulo de la siguiente manera:Resultado:
fuente
100 trials 94 errorsDebería comenzar con una prueba que pase y demostrar que la introducción del redondeo interrumpe la prueba.doublesin errores ideone.com/BVCHh3Supongamos que tienes
puedes usar
BigDecimalo sin BigDecimal
con ambas soluciones
d == 9232.13fuente
RoundingMode.HALF_UPestá mal. Prueba con1.505. La forma correcta es usarBigDecimal.valueOf(d).Puede usar la clase DecimalFormat.
fuente
Double.valueOf()fue elegidoDouble.parseDouble()? ElvalueOf()método devuelve unDoubleobjeto, mientrasparseDouble()que devolverá undoubleprimitivo. Con la forma en que se escribe el código actual, también aplica el desempaquetado automático al retorno para convertirlo a la primitiva que sutwoDoublevariable espera, una operación adicional de código de bytes. Cambiaría la respuesta para usarparseDouble()en su lugar.Double.parseDouble()necesitaStringentradaReal How-to de Java publica esta solución, que también es compatible con versiones anteriores a Java 1.6.
fuente
fuente
Math.floor(x + 0.5)yMath.round(x)@Milhous: el formato decimal para redondear es excelente:
Agregaría que este método es muy bueno para proporcionar un mecanismo numérico real de redondeo, no solo visualmente, sino también durante el procesamiento.
Hipotético: debe implementar un mecanismo de redondeo en un programa GUI. Para alterar la precisión / precisión de un resultado, simplemente cambie el formato de intercalación (es decir, entre paréntesis). Así que eso:
volvería como salida:
0.912385volvería como salida:
0.91239volvería como salida:
0.9124[EDITAR: también si el formato de intercalación es así ("# 0. ############") e ingresa un decimal, por ejemplo, 3.1415926, por el argumento, DecimalFormat no produce basura ( p. ej. ceros finales) y devolverá:
3.1415926.. si está inclinado de esa manera. De acuerdo, es un poco detallado para el gusto de algunos desarrolladores, pero bueno, tiene poca huella de memoria durante el procesamiento y es muy fácil de implementar.]Entonces, esencialmente, la belleza de DecimalFormat es que maneja simultáneamente la apariencia de la cuerda, así como el nivel de precisión de redondeo establecido. Ergo: obtienes dos beneficios por el precio de la implementación de un código. ;)
fuente
double. Utilice BigDecimal o cualquier otro formato basado en decimales.Aquí hay un resumen de lo que puede usar si desea el resultado como Cadena:
DecimalFormat # setRoundingMode () :
BigDecimal # setScale ()
Aquí hay una sugerencia de qué bibliotecas puede usar si lo desea
doublecomo resultado. Sin embargo, no lo recomendaría para la conversión de cadenas, ya que double puede no ser capaz de representar exactamente lo que quieres (ver, por ejemplo, aquí )Precisión de Apache Commons Math
Funciones del potro
Utilidades de Weka
fuente
Puede usar el siguiente método de utilidad:
fuente
round(1.005,2);oround(0.50594724957626620092, 20);Una solución sucinta:
Ver también, https://stackoverflow.com/a/22186845/212950 Gracias a jpdymond por ofrecer esto.
fuente
Puedes usar BigDecimal
Consulte: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
fuente
Pruebe esto: org.apache.commons.math3.util.Precision.round (doble x, escala int)
Ver: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
La página de inicio de la Biblioteca de Matemáticas Apache Commons es: http://commons.apache.org/proper/commons-math/index.html
La implementación interna de este método es:
fuente
Como no encontré una respuesta completa sobre este tema, reuní una clase que debería manejar esto correctamente, con soporte para:
El uso es bastante simple :
(Por el bien de este ejemplo, estoy usando una configuración regional personalizada)
Aquí está la clase :
fuente
Si realmente desea números decimales para el cálculo (y no solo para la salida), no use un formato de punto flotante basado en binario como double.
Sí uso BigDecimal para los cálculos, pero tenga en cuenta que depende del tamaño de los números con los que está tratando. En la mayoría de mis implementaciones, encuentro que el análisis de doble o entero a Largo es suficiente para cálculos de números muy grandes.
De hecho, recientemente utilicé analizado a largo para obtener representaciones precisas (en lugar de resultados hexadecimales) en una GUI para números tan grandes como ################## ############### caracteres (como ejemplo).
fuente
Para lograr esto, podemos usar este formateador:
o:
Use este método para obtener siempre dos decimales:
Definiendo estos valores:
Usando el método podemos obtener estos resultados:
demostración en línea.
fuente
En caso de que alguien todavía necesite ayuda con esto. Esta solución funciona perfectamente para mí.
devuelve a
Stringcon la salida deseada.fuente
Estoy de acuerdo con la respuesta elegida para usar
DecimalFormat--- o alternativamenteBigDecimal.Por favor lea Actualización primero la continuación!
Sin embargo, si no desea redondear el valor doble y obtener undoubleresultado de valor, se puede utilizarorg.apache.commons.math3.util.Precision.round(..)como se mencionó anteriormente. La implementación usaBigDecimal, es lenta y crea basura.LaDoubleRounderutilidad proporciona un método similar pero rápido y libre de basura en la biblioteca decimal4j:Saldrá
Ver https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Descargo de responsabilidad: estoy involucrado en el proyecto decimal4j.
Actualización: como señaló @iaforek, DoubleRounder a veces devuelve resultados contraintuitivos. La razón es que realiza redondeos matemáticamente correctos. Por ejemplo
DoubleRounder.round(256.025d, 2), se redondeará hacia abajo a 256.02 porque el valor doble representado como 256.025d es algo más pequeño que el valor racional 256.025 y, por lo tanto, se redondeará hacia abajo.Notas:
BigDecimal(double)constructor (pero no alvalueOf(double)que usa el constructor de cadenas).Por esas razones y todo lo mencionado anteriormente en esta publicación, no puedo recomendar el uso de DoubleRounder .
fuente
El fragmento de código a continuación muestra cómo mostrar n dígitos. El truco es establecer la variable pp en 1 seguido de n ceros. En el siguiente ejemplo, el valor de pp variable tiene 5 ceros, por lo que se mostrarán 5 dígitos.
fuente
Si está usando
DecimalFormatpara convertirdoubleaString, es muy sencillo:Hay varios
RoundingModevalores de enumeración para seleccionar, dependiendo del comportamiento que requiera.fuente
Vine aquí solo queriendo una respuesta simple sobre cómo redondear un número. Esta es una respuesta complementaria para proporcionar eso.
Cómo redondear un número en Java
El caso más común es usar
Math.round().Los números se redondean al número entero más cercano. Un
.5valor se redondea. Si necesita un comportamiento de redondeo diferente al anterior, puede usar uno de los otros Math funciones . Vea la comparación a continuación.redondo
Como se indicó anteriormente, esto se redondea al número entero más cercano.
.5decimales redondeados. Este método devuelve unint.fortificar techo
Cualquier valor decimal se redondea al siguiente entero. Se va al techo . Este método devuelve a
double.suelo
Cualquier valor decimal se redondea al siguiente número entero. Este método devuelve a
double.rint
Esto es similar a redondear en que los valores decimales redondean al entero más cercano. Sin embargo, a diferencia de
round, los.5valores se redondean al entero par. Este método devuelve adouble.fuente
Si está utilizando una tecnología que tiene un JDK mínimo. Aquí hay una manera sin ninguna biblioteca de Java:
fuente
DecimalFormat es la mejor forma de salida, pero no lo prefiero. Siempre hago esto todo el tiempo, porque devuelve el doble valor. Entonces puedo usarlo más que solo la salida.
O
Si necesita un valor de lugares decimales grande, puede usar BigDecimal en su lugar. De todos modos
.0es importante. Sin ella, el redondeo de 0.33333d5 devuelve 0.33333 y solo se permiten 9 dígitos. La segunda función sin.0tiene problemas con 0.30000 return 0.30000000000000004.fuente
Aquí está mi respuesta:
fuente
Entonces, después de leer la mayoría de las respuestas, me di cuenta de que la mayoría de ellas no serán precisas, de hecho, usarlas
BigDecimalparece ser la mejor opción, pero si no comprende cómoRoundingModefunciona, inevitablemente perderá precisión. Me di cuenta de esto cuando trabajaba con grandes números en un proyecto y pensé que podría ayudar a otros a tener problemas para redondear números. Por ejemplo.Esperaría obtener
1363.28como salida, pero terminará con lo1363.27que no se espera si no sabe lo queRoundingModeestá haciendo. Entonces, mirando los documentos de Oracle , encontrará la siguiente descripciónRoundingMode.HALF_UP.Entonces, sabiendo esto, nos dimos cuenta de que no obtendremos un redondeo exacto, a menos que queramos redondear hacia el vecino más cercano . Entonces, para lograr una ronda adecuada, tendríamos que recorrer desde el
n-1decimal hacia los decimales deseados. Por ejemplo.Esto terminará dándonos el resultado esperado, que sería
1363.28.fuente
Donde dp = lugar decimal que desea, y el valor es un doble.
fuente
1.0paravalue = 1.005ydp = 2. Use esto en su lugar.Tenga en cuenta que String.format () y DecimalFormat producen cadenas usando la configuración regional predeterminada. Por lo tanto, pueden escribir números formateados con punto o coma como separador entre las partes enteras y decimales. Para asegurarse de que la cadena redondeada esté en el formato que desee, use java.text.NumberFormat de esta manera:
Se imprimirá en la configuración regional en inglés (no importa cuál sea su configuración regional): 0.99 123.57 123.00
El ejemplo está tomado de Farenda: cómo convertir el doble a la cadena correctamente .
fuente
En general, el redondeo se realiza escalando:
round(num / p) * pfuente