使用java.math.MathContext
最近我尝试了解java.math.MathContext的使用,但未能正确理解。 是否用于在java.math.BigDecimal
进行舍入,如果是,为什么不是十进制数字,而是甚至是mentissa部分。
从API文档,我知道它遵循ANSI X3.274-1996
和ANSI 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.2e2
或120
。 通过减less有效数字的数量,我们降低了我们可以指定数字的精度。
RoundingMode
部分指定我们应该如何处理精度的损失。 要重用该示例,如果使用123
作为数字,并要求input2位有效数字,则会降低精度。 使用HALF_UP
的RoundingMode
(默认模式), 123
将变为120
。 用CEILING
的RoundingMode
,你会得到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中的数量/数字进行舍入。
例如,
如果MathContext
configuration为precision = 2
, rounding 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