java.math.MathContext的使用

时间:2020-03-05 18:38:54  来源:igfitidea点击:

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

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

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

解决方案

回答

如果我正确地理解了声音,那听起来就像我们期望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 = 2'和舍入模式= ROUND_HALF_EVEN

" BigDecimal Number = 0.5294",四舍五入为0.53

因此,我认为这是一种较新的技术,并将其用于取整目的。但是,由于它开始舍入部分数字的mentissa,因此变成了噩梦。

例如,

Number = 1.5294被四舍五入为1.5

数字= 10.5294被四舍五入为10

数字= 101.5294被四舍五入为100

.... 等等

因此,这不是我期望的四舍五入行为(精度为2)。

这似乎具有一定的逻辑,因为从模式上我可以说它采用数字的前两位(精度为2),然后将0添加到no。位数与未取整金额相同(请参见示例101.5294 ...)

回答

@贾坦

Thanks for you answer. It makes sense. Can you please explain me MathContext in the context of BigDecimal#round method.

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

精度再次指定有效位数。因此,如果我们将" 123"指定为数字,并要求输入2个有效数字,那么我们将获得" 120"。如果我们以科学计数法来考虑,可能会更加清楚。

按照科学计数法," 123"将是" 1.23e2"。如果我们仅保留2位有效数字,则将获得" 1.2e2"或者" 120"。通过减少有效数字的位数,我们降低了指定数字的精度。

" RoundingMode"部分指定了如何处理精度损失。要重用该示例,如果我们使用" 123"作为数字,并要求输入2个有效数字,则会降低精度。在" HALF_UP"(默认模式)的" RoundingMode"中," 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);

其结果是一个BigDecimal,其值为1.24(由于四舍五入规则)