El uso de java.de matemáticas.MathContext
-
08-06-2019 - |
Pregunta
Recientemente traté de entender el uso de java.de matemáticas.MathContext pero no pudo entender correctamente.Se utiliza para el redondeo en java.math.BigDecimal
.Si sí ¿por qué no se la ronda de los dígitos decimales pero incluso mantisa parte.
A partir de la API de google docs, vine a saber que sigue el estándar especificado en ANSI X3.274-1996
y ANSI X3.274-1996/AM 1-2000
especificaciones pero no llegué a leer en línea.
Por favor, hágamelo saber si usted tiene alguna idea sobre esto.
Solución
@jatan
Gracias por la respuesta.Tiene sentido.¿Puede por favor explicar me MathContext en el contexto de BigDecimal#ronda método.
No hay nada especial acerca de BigDecimal.round()
vs cualquier otro BigDecimal
método.En todos los casos, la MathContext
especifica el número de dígitos significativos y el redondeo de la técnica.Básicamente, hay dos partes de cada MathContext
.Hay una precisión, y también hay un RoundingMode
.
La precisión de nuevo especifica el número de dígitos significativos.Así que si usted especifique 123
como un número, y pregunte por 2 dígitos significativos, vas a conseguir 120
.Podría ser más clara si pensamos en términos de la notación científica.
123
sería 1.23e2
en la notación científica.Si sólo mantener a 2 cifras significativas, entonces se obtiene 1.2e2
, o 120
.Al reducir el número de dígitos significativos, podemos reducir la precisión con la que podemos especificar un número.
El RoundingMode
parte especifica cómo debemos manejar la pérdida de precisión.Para reutilizar el ejemplo, si se utiliza 123
como el número, y pregunte por 2 dígitos significativos, ha reducido su precisión.Con un RoundingMode
de HALF_UP
(el modo por defecto), 123
se convertirá en 120
.Con un RoundingMode
de CEILING
, usted conseguirá el 130
.
Por ejemplo:
System.out.println(new BigDecimal("123.4",
new MathContext(4,RoundingMode.HALF_UP)));
System.out.println(new BigDecimal("123.4",
new MathContext(2,RoundingMode.HALF_UP)));
System.out.println(new BigDecimal("123.4",
new MathContext(2,RoundingMode.CEILING)));
System.out.println(new BigDecimal("123.4",
new MathContext(1,RoundingMode.CEILING)));
Salidas:
123.4
1.2E+2
1.3E+2
2E+2
Se puede ver que tanto la precisión y el modo de redondeo afecta a la salida.
Otros consejos
Para el redondeo sólo la parte fraccionaria de un BigDecimal, retirar el BigDecimal.setScale(int newScale, int roundingMode)
método.
E. g.para cambiar un número de tres dígitos después del punto decimal a uno con dos dígitos, y redondeo:
BigDecimal original = new BigDecimal("1.235");
BigDecimal scaled = original.setScale(2, BigDecimal.ROUND_HALF_UP);
El resultado de esto es un BigDecimal con el valor de 1,24 (debido al redondeo de la regla)
Me gustaría añadir aquí, un par de ejemplos.No he encontrado en las respuestas anteriores, pero me parece útil para aquellos que tal vez inducir a error dígitos significativos con el número de decimales.Supongamos, hemos dicho contexto:
MathContext MATH_CTX = new MathContext(3, RoundingMode.HALF_UP);
Para que este código:
BigDecimal d1 = new BigDecimal(1234.4, MATH_CTX);
System.out.println(d1);
es perfectamente claro, que su resultado es 1.23E+3
como los chicos se dijo anteriormente.Primeros dígitos significativos son 123...
Pero lo que en este caso:
BigDecimal d2 = new BigDecimal(0.000000454770054, MATH_CTX);
System.out.println(d2);
su número no será redondeado a 3 lugares después de la coma - para una persona puede no ser intuitivo y vale la pena destacar.En su lugar se redondeará a la primeros 3 dígitos significativos, que en este caso son los "4 5 4".Así, por encima de resultados del código en 4.55E-7
y no en 0.000
como alguien podía esperar.
Ejemplos similares:
BigDecimal d3 = new BigDecimal(0.001000045477, MATH_CTX);
System.out.println(d3); // 0.00100
BigDecimal d4 = new BigDecimal(0.200000477, MATH_CTX);
System.out.println(d4); // 0.200
BigDecimal d5 = new BigDecimal(0.000000004, MATH_CTX);
System.out.println(d5); //4.00E-9
Espero que este obvio, pero relevante ejemplo podría ser útil...
Si entiendo correctamente, suena como que usted está esperando el MathContext para controlar la cantidad de dígitos debe ser mantenido después del punto decimal.Eso no es lo que es.Se especifica el número de dígitos a mantener, total.Por lo que si especifica que desea 3 dígitos significativos, eso es todo lo que vas a obtener.
Por ejemplo, este:
System.out.println(new BigDecimal("1234567890.123456789",
new MathContext(20)));
System.out.println(new BigDecimal("1234567890.123456789",
new MathContext(10)));
System.out.println(new BigDecimal("1234567890.123456789",
new MathContext(5)));
de salida será:
1234567890.123456789
1234567890
1.2346E+9
No es por diversión.En realidad he encontrado algunos en línea ejemplo, que declaró que el uso de MathContext
para redondear las cantidades y números almacenados en BigDecimal.
Por ejemplo,
Si MathContext
está configurado para tener precision = 2
y rounding mode = ROUND_HALF_EVEN
BigDecimal Number = 0.5294
, es redondeado a 0.53
Así que pensé que es una técnica más reciente y que se usaba para el redondeo de propósito.Sin embargo, se convirtió en pesadilla, ya que comenzó a redondeo incluso mentissa parte de número.
Por ejemplo,
Number = 1.5294
se redondea a 1.5
Number = 10.5294
se redondea a 10
Number = 101.5294
se redondea a 100
....y así sucesivamente
Así que esto no es el comportamiento que se espera para el redondeo (como la precisión = 2).
Parece tener cierta lógica, porque a partir de la fraseología puedo decir que lleva dos primeros dígitos (como la precisión es de 2) de número y, a continuación, se anexa 0 hasta el no.de dígitos convertido mismo importe no redondeado (descargue el ejemplo de 101.5294 ...)