java.math.MathContext的使用
最近,我尝试了解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"。带有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);
其结果是一个BigDecimal,其值为1.24(由于四舍五入规则)