最近我尝试了解使用 java.math.MathContext 但未能正确理解。是否用于舍入 java.math.BigDecimal. 。如果是的话,为什么它不四舍五入小数位,甚至尾数部分。

从API文档中,我了解到它遵循中指定的标准 ANSI X3.274-1996ANSI X3.274-1996/AM 1-2000 规格,但我没有让它们在线阅读。

如果您对此有任何想法,请告诉我。

有帮助吗?

解决方案

@jatan

谢谢你的回答。这说得通。您能在 BigDecimal#round 方法的上下文中向我解释一下 MathContext 吗?

没什么特别的 BigDecimal.round() 任何其他 BigDecimal 方法。在所有情况下, MathContext 指定有效位数和舍入技术。基本上,每个都有两个部分 MathContext. 。有一个精度,还有一个 RoundingMode.

精度再次指定有效位数。所以如果你指定 123 作为一个数字,并要求 2 位有效数字,您将得到 120. 。如果你用科学记数法来思考,可能会更清楚。

123 将会 1.23e2 以科学记数法表示。如果只保留 2 位有效数字,则得到 1.2e2, , 或者 120. 。通过减少有效位数,我们可以降低指定数字的精度。

RoundingMode 部分指定我们应该如何处理精度损失。要重用该示例,如果您使用 123 作为数字,并要求 2 位有效数字,您就降低了精度。与一个 RoundingModeHALF_UP (默认模式), 123 会变成 120. 。与一个 RoundingModeCEILING, , 你会得到 130.

例如:

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

输出:

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

您可以看到精度和舍入模式都会影响输出。

其他提示

要仅舍入 BigDecimal 的小数部分,请查看 BigDecimal.setScale(int newScale, int roundingMode) 方法。

例如。将小数点后三位数字更改为两位数,并向上舍入:

BigDecimal original = new BigDecimal("1.235");
BigDecimal scaled = original.setScale(2, BigDecimal.ROUND_HALF_UP);

结果是一个值为 1.24 的 BigDecimal(由于向上舍入规则)

我想在这里添加几个例子。我在以前的答案中没有找到它们,但我发现它们对于那些可能误导的人很有用 有效数字 与数量 小数位. 。假设我们有这样的上下文:

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

对于这段代码:

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

很明显,你的结果是 1.23E+3 正如上面的人所说。第一个有效数字是 123...

但在这种情况下:

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

你的号码 逗号后不会四舍五入到 3 位 - 对于某些人来说,这可能不直观,值得强调。相反,它将四舍五入到 前 3 位有效数字, ,在本例中为“4 5 4”。所以上面的代码结果是 4.55E-7 并且不在 0.000 正如有人所预料的那样。

类似的例子:

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

我希望这个显而易见但相关的例子会有所帮助......

如果我理解正确的话,听起来您希望 MathContext 控制小数点后应保留多少位数字。那不是它的目的。它指定要保留多少位数字, 全部的. 。因此,如果您指定需要 3 位有效数字,这就是您将得到的全部内容。

例如,这个:

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

将输出:

1234567890.123456789
1234567890
1.2346E+9

这不是为了好玩。其实我在网上找到了一些例子,其中说明了使用 MathContext 对存储在 BigDecimal 中的金额/数字进行舍入。

例如,

如果 MathContext 配置为具有 precision = 2rounding mode = ROUND_HALF_EVEN

BigDecimal Number = 0.5294, , 是 圆形的0.53

所以我认为这是一种较新的技术并将其用于舍入目的。然而,它变成了噩梦,因为它甚至开始四舍五入数字的一部分。

例如,

Number = 1.5294 四舍五入为 1.5

Number = 10.5294 四舍五入为 10

Number = 101.5294 四舍五入为 100

....等等

所以这不是我期望的舍入行为(精度 = 2)。

它似乎有一些逻辑,因为从 Patter 来看,我可以说它需要数字的前两位数字(因为精度为 2),然后附加 0 直到数字。位数与未四舍五入的金额相同(查看 101.5294 ... 的示例)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top