setscale java math bigdecimal mathcontext

setscale - Uso de java.math.MathContext



bigdecimal java (5)

@jatan

Gracias por tu respuesta. Que tiene sentido. ¿Puedes explicarme MathContext en el contexto del método BigDecimal # round?

No hay nada especial acerca de BigDecimal.round() frente a cualquier otro método BigDecimal . En todos los casos, MathContext especifica el número de dígitos significativos y la técnica de redondeo. Básicamente, hay dos partes de cada MathContext . Hay una precisión, y también hay un RoundingMode .

La precisión nuevamente especifica el número de dígitos significativos. Entonces, si especifica 123 como un número y pide 2 dígitos significativos, obtendrá 120 . Podría ser más claro si piensas en términos de notación científica.

123 sería 1.23e2 en notación científica. Si solo conserva dos dígitos significativos, obtiene 1.2e2 o 120 . Al reducir el número de dígitos significativos, reducimos la precisión con la que podemos especificar un número.

La parte RoundingMode especifica cómo debemos manejar la pérdida de precisión. Para reutilizar el ejemplo, si usa 123 como número y solicita 2 dígitos significativos, ha reducido su precisión. Con un RoundingMode de HALF_UP (el modo predeterminado), 123 se convertirá en 120 . Con un RoundingMode de CEILING , obtendrá 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)));

Productos:

123.4 1.2E+2 1.3E+2 2E+2

Puede ver que tanto la precisión como el modo de redondeo afectan la salida.

Recientemente intenté entender el uso de java.math.MathContext pero no entendí bien. ¿Se utiliza para redondear en java.math.BigDecimal , si es así, por qué no redondea los dígitos decimales, sino incluso la parte mentissa.

De los documentos de la API, llegué a saber que sigue el estándar especificado en las especificaciones ANSI X3.274-1996 y ANSI X3.274-1996/AM 1-2000 pero no conseguí que se leyeran en línea.

Por favor, avíseme si tiene alguna idea al respecto.


No es por diversión De hecho, encontré algunos ejemplos en línea, que indicaban el uso de MathContext para redondear las cantidades / 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 , se redondea a 0.53

Entonces pensé que era una técnica más nueva y la usé para redondear el propósito. Sin embargo, se convirtió en una pesadilla porque comenzó a redondear incluso a mentissa como parte del 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í

Entonces este no es el comportamiento que esperaba para redondear (como precisión = 2).

Parece tener algo de lógica porque de golpeteo puedo decir que toma los primeros dos dígitos (como la precisión es 2) de número y luego agrega 0 hasta el no. de dígitos se vuelven iguales a la cantidad no redondeada (consulte el ejemplo de 101.5294 ...)


Para redondear solo la parte fraccional de un BigDecimal, consulte el BigDecimal.setScale(int newScale, int roundingMode) .

Por ejemplo, para cambiar un número con tres dígitos después del punto decimal a uno con dos dígitos, y redondeando hacia arriba:

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 1.24 (debido a la regla de redondeo)


Si te entiendo correctamente, parece que esperas que MathContext controle cuántos dígitos se deben guardar después del punto decimal. Para eso no es para eso. Especifica cuántos dígitos conservar, total . Entonces, si especifica que desea 3 dígitos significativos, eso es todo lo que obtendrá.

Por ejemplo, esto:

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)));

dará salida:

1234567890.123456789 1234567890 1.2346E+9


Yo agregaría aquí, algunos ejemplos. No los he encontrado en respuestas anteriores, pero los considero útiles para aquellos que pueden confundir dígitos significativos con el número de decimales . Supongamos, tenemos ese contexto:

MathContext MATH_CTX = new MathContext(3, RoundingMode.HALF_UP);

Para este código:

BigDecimal d1 = new BigDecimal(1234.4, MATH_CTX); System.out.println(d1);

está perfectamente claro, que tu resultado es 1.23E+3 como dicen los chicos arriba. Los primeros dígitos significativos son 123 ...

Pero que en este caso:

BigDecimal d2 = new BigDecimal(0.000000454770054, MATH_CTX); System.out.println(d2);

su número no se redondeará a 3 lugares después de la coma ; para alguien, puede no ser intuitivo y vale la pena destacarlo. En cambio, se redondeará a los primeros 3 dígitos significativos , que en este caso son "4 5 4". Por lo tanto, el código anterior da como resultado 4.55E-7 y no en 0.000 como podría esperarse.

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 ejemplo obvio pero relevante sea útil ...