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.format
mé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
value
es 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.335
realmente 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. Elfail
aquí no está en volver a convertir al doble. Está en OP pensando que puede confiar en que la entrada265.335
sea exactamente eso.te conseguirá a
BigDecimal
. Para obtener la cadena fuera de él, simplemente llamar a esoBigDecimal
'stoString
método o latoPlainString
mé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 mode
utilizaRoundingMode.HALF_EVEN.
Como otros han notado, la respuesta correcta es usar cualquiera
DecimalFormat
oBigDecimal
. 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
BigDecimal
ynew MathContext(16)
para la operación del módulo de la siguiente manera:Resultado:
fuente
100 trials 94 errors
Debería comenzar con una prueba que pase y demostrar que la introducción del redondeo interrumpe la prueba.double
sin errores ideone.com/BVCHh3Supongamos que tienes
puedes usar
BigDecimal
o sin BigDecimal
con ambas soluciones
d == 9232.13
fuente
RoundingMode.HALF_UP
está 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 unDouble
objeto, mientrasparseDouble()
que devolverá undouble
primitivo. 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 sutwoDouble
variable espera, una operación adicional de código de bytes. Cambiaría la respuesta para usarparseDouble()
en su lugar.Double.parseDouble()
necesitaString
entradaReal 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.912385
volvería como salida:
0.91239
volverí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
double
como 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
String
con 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 undouble
resultado de valor, se puede utilizarorg.apache.commons.math3.util.Precision.round(..)
como se mencionó anteriormente. La implementación usaBigDecimal
, es lenta y crea basura.LaDoubleRounder
utilidad 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
DecimalFormat
para convertirdouble
aString
, es muy sencillo:Hay varios
RoundingMode
valores 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
.5
valor 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.
.5
decimales 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.5
valores 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
.0
es importante. Sin ella, el redondeo de 0.33333d5 devuelve 0.33333 y solo se permiten 9 dígitos. La segunda función sin.0
tiene 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
BigDecimal
parece ser la mejor opción, pero si no comprende cómoRoundingMode
funciona, 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.28
como salida, pero terminará con lo1363.27
que no se espera si no sabe lo queRoundingMode
está 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-1
decimal 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.0
paravalue = 1.005
ydp = 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) * p
fuente