java.math.MathContex的使用
最近,我尝试了解java.math.MathContext的用法,但未能正确理解。 是否将其用于ANSI X3.274-1996中的舍入。如果是,为什么不舍入小数点后甚至尾数部分。
从API文档中,我知道它遵循ANSI X3.274-1996和ANSI X3.274-1996/AM 1-2000规范中指定的标准,但是我没有让他们在线阅读。
如果您对此有任何想法,请告诉我。
5个解决方案
64 votes
要仅舍入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(由于四舍五入规则)
hacklife productions answered 2020-02-15T06:47:13Z
44 votes
@贾坦
感谢您的回答。 这说得通。 您能否在BigDecimal#round方法的上下文中向我解释MathContext。
RoundingMode与其他123方法没有什么特别的。 在所有情况下,RoundingMode指定有效数字的数量和舍入技术。 基本上,每个RoundingMode有两个部分。有一个精度,还有一个RoundingMode。
精度再次指定有效位数。 因此,如果您将RoundingMode指定为一个数字,并要求输入2个有效数字,您将获得123129。
RoundingMode用科学计数法将是123。 如果仅保留2个有效数字,则得到RoundingMode或27483002850419681968131。通过减少有效数字的位数,我们降低了指定数字的精度。
RoundingMode部分指定了如何处理精度损失。 要重用该示例,如果您使用123作为数字,并要求输入2个有效数字,则会降低精度。 在RoundingMode为HALF_UP(默认模式)的情况下,123将变为120。在RoundingMode为CEILING的情况下,您将获得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
您可以看到精度和舍入模式都会影响输出。
Derek Park answered 2020-02-15T06:46:44Z
13 votes
我将在此处添加一些示例。 我在以前的答案中没有找到它们,但是对于那些可能误导小数位数的有效数字的人,我发现它们很有用。 让我们假设,我们有这样的上下文:
MathContext MATH_CTX = new MathContext(3, RoundingMode.HALF_UP);
对于此代码:
BigDecimal d1 = new BigDecimal(1234.4, MATH_CTX);
System.out.println(d1);
十分清楚,正如您所说的,您的结果是4.55E-7。 第一位有效数字是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
我希望这个明显但相关的示例会有所帮助...
guitar_freak answered 2020-02-15T06:48:00Z
4 votes
如果我正确地理解了您的声音,那听起来就像您期望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
Derek Park answered 2020-02-15T06:48:29Z
4 votes
这不是为了好玩。 实际上,我在网上找到了一个示例,该示例说明使用Number = 101.5294来四舍五入BigDecimal中存储的金额/数字。
例如,
如果Number = 101.5294配置为具有100和rounding mode = ROUND_HALF_EVEN
Number = 101.5294,四舍五入为0.53
因此,我认为这是一种较新的技术,并将其用于取整目的。 但是它变成了噩梦,因为它开始对数字的mentissa部分进行四舍五入。
例如,
Number = 101.5294舍入为100
Number = 101.5294 is rounded to 100
Number = 101.5294 is rounded to 100
.... 等等
因此,这不是我期望的四舍五入行为(精度= 2)。
这似乎有些逻辑,因为从模式上我可以说,它采用数字的前两位(精度为2),然后将0附加到no。 位数与未取整金额相同(请参见示例101.5294 ...)
jatanp answered 2020-02-15T06:51:29Z