使用java.math.MathContext

最近我尝试了解java.math.MathContext的使用,但未能正确理解。 是否用于在java.math.BigDecimal进行舍入,如果是,为什么不是十进制数字,而是甚至是mentissa部分。

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

请让我知道,如果你有这个想法。

@jatan

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

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

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

科学记数法中的123将是1.23e2 。 如果你只保留2位有效数字,那么你得到1.2e2120 。 通过减less有效数字的数量,我们降低了我们可以指定数字的精度。

RoundingMode部分指定我们应该如何处理精度的损失。 要重用该示例,如果使用123作为数字,并要求input2位有效数字,则会降低精度。 使用HALF_UPRoundingMode (默认模式), 123将变为120 。 用CEILINGRoundingMode ,你会得到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(因为四舍五入规则)

我会在这里添加几个例子。 在以前的答案中,我没有find它们,但是我发现它们可能会误导有小数位数的 有效数字 。 我们假设,我们有这样的背景:

 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而不是有人可以预料的。

类似的例子:

 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 

我希望这个明显但相关的例子会有帮助

这不是为了好玩。 实际上,我find了一些在线的例子,其中指出了使用MathContext对存储在BigDecimal中的数量/数字进行舍入。

例如,

如果MathContextconfiguration为precision = 2rounding mode = ROUND_HALF_EVEN

BigDecimal Number = 0.5294四舍五入0.53

所以我认为这是一个更新的技术,并将其用于四舍五入的目的。 然而,因为甚至连mentissa的一部分开始四舍五入了所以变成恶梦。

例如,

Number = 1.5294四舍五入到1.5

Number = 10.5294被舍入到10

Number = 101.5294被舍入到100

…. 等等

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

这似乎是有一些逻辑,因为从pat我可以说,它需要前两位数字(精度为2)的数字,然后附加0的直到不。 的数字变成与未接地量相同(结算101.5294 …的例子)

如果我正确地理解了你,这听起来像是你期待MathContext控制在小数点后应该保留多less数字。 这不是它的目的。 它指定要保留多less个数字, 总数 。 所以,如果你指定你想要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