java.math.MathContext 的使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7539/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use of java.math.MathContext
提问by jatanp
Recently I tried understanding the use of java.math.MathContextbut failed to understand properly. Is it used for rounding in java.math.BigDecimal
. If yes why does not it round the decimal digits but even mantissa part.
最近尝试理解java.math.MathContext的使用,但是没能正确理解。它是否用于四舍五入java.math.BigDecimal
。如果是,为什么它不舍入十进制数字,而是舍入尾数部分。
From API docs, I came to know that it follows the standard specified in ANSI X3.274-1996
and ANSI X3.274-1996/AM 1-2000
specifications but I did not get them to read online.
从 API 文档中,我了解到它遵循 和规范中指定的标准ANSI X3.274-1996
,ANSI X3.274-1996/AM 1-2000
但我没有让他们在线阅读。
Please let me know if you have any idea on this.
如果您对此有任何想法,请告诉我。
采纳答案by Derek Park
@jatan
@jatan
Thanks for you answer. It makes sense. Can you please explain me MathContext in the context of BigDecimal#round method.
谢谢你的回答。这说得通。您能否在 BigDecimal#round 方法的上下文中向我解释 MathContext。
There's nothing special about BigDecimal.round()
vs.any other BigDecimal
method. In all cases, the MathContext
specifies the number of significant digits and the rounding technique. Basically, there are two parts of every MathContext
. There's a precision, and there's also a RoundingMode
.
BigDecimal.round()
与任何其他BigDecimal
方法相比,没有什么特别之处。在所有情况下,MathContext
指定有效数字的数量和舍入技术。基本上,每个MathContext
. 有一个精度,还有一个RoundingMode
.
The precision again specifies the number of significant digits. So if you specify 123
as a number, and ask for 2 significant digits, you're going to get 120
. It might be clearer if you think in terms of scientific notation.
精度再次指定有效位数。因此,如果您指定123
为一个数字,并要求输入 2 个有效数字,您将得到120
. 如果您从科学记数法的角度考虑,可能会更清楚。
123
would be 1.23e2
in scientific notation. If you only keep 2 significant digits, then you get 1.2e2
, or 120
. By reducing the number of significant digits, we reduce the precision with which we can specify a number.
123
将采用1.23e2
科学记数法。如果您只保留 2 个有效数字,那么您将得到1.2e2
, 或120
。通过减少有效数字的数量,我们降低了指定数字的精度。
The RoundingMode
part specifies how we should handle the loss of precision. To reuse the example, if you use 123
as the number, and ask for 2 significant digits, you've reduced your precision. With a RoundingMode
of HALF_UP
(the default mode), 123
will become 120
. With a RoundingMode
of CEILING
, you'll get 130
.
该RoundingMode
部分指定了我们应该如何处理精度损失。要重用该示例,如果您使用123
作为数字,并要求 2 位有效数字,则您降低了精度。使用 a RoundingMode
of HALF_UP
(默认模式),123
将变为120
. 使用RoundingMode
of CEILING
,您将获得130
.
For example:
例如:
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)));
Outputs:
输出:
123.4
1.2E+2
1.3E+2
2E+2
You can see that both the precision and the rounding mode affect the output.
您可以看到精度和舍入模式都会影响输出。
回答by Derek Park
If I'm understanding you correctly, it sounds like you're expecting the MathContext to control how many digits should be kept after the decimal point. That's not what it's for. It specifies how many digits to keep, total. So if you specify that you want 3 significant digits, that's all you're going to get.
如果我对您的理解正确,听起来您希望 MathContext 控制小数点后应保留多少位数字。这不是它的目的。它指定要保留的位数,总计。因此,如果您指定需要 3 位有效数字,那么您将得到的仅此而已。
For example, this:
例如,这个:
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)));
will output:
将输出:
1234567890.123456789
1234567890
1.2346E+9
回答by jatanp
It's not for fun. Actually I found some online example, which stated the use of MathContext
to round the amounts/numbers stored in BigDecimal.
这不是为了好玩。实际上,我找到了一些在线示例,其中说明了对MathContext
BigDecimal 中存储的金额/数字进行四舍五入的用法。
For example,
例如,
If MathContext
is configured to have precision = 2
and rounding mode = ROUND_HALF_EVEN
如果MathContext
配置为具有precision = 2
和rounding mode = ROUND_HALF_EVEN
BigDecimal Number = 0.5294
, is roundedto 0.53
BigDecimal Number = 0.5294
,四舍五入为0.53
So I thought it is a newer technique and used it for rounding purpose. However it turned into nightmare because it started rounding even mentissa part of number.
所以我认为这是一种较新的技术并将其用于舍入目的。然而,它变成了噩梦,因为它甚至开始四舍五入数字的 mentissa 部分。
For example,
例如,
Number = 1.5294
is rounded to 1.5
Number = 1.5294
四舍五入为 1.5
Number = 10.5294
is rounded to 10
Number = 10.5294
四舍五入为 10
Number = 101.5294
is rounded to 100
Number = 101.5294
四舍五入为 100
.... and so on
.... 等等
So this is not the behavior I expected for rounding (as precision = 2).
所以这不是我期望的四舍五入行为(因为精度 = 2)。
It seems to be having some logic because from patter I can say that it takes first two digits (as precision is 2) of number and then appends 0's till the no. of digits become same as unrounded amount (checkout the example of 101.5294 ...)
它似乎有一些逻辑,因为从模式我可以说它需要数字的前两位数(因为精度是 2),然后附加 0 直到没有。数字变得与未四舍五入的数量相同(查看 101.5294 的示例...)
回答by hacklife productions
For rounding just the fractional part of a BigDecimal, check out the BigDecimal.setScale(int newScale, int roundingMode)
method.
要仅舍入 BigDecimal 的小数部分,请查看该BigDecimal.setScale(int newScale, int roundingMode)
方法。
E.g. to change a number with three digits after the decimal point to one with two digits, and rounding up:
例如,将一个小数点后三位数字改为一位两位数字,并四舍五入:
BigDecimal original = new BigDecimal("1.235");
BigDecimal scaled = original.setScale(2, BigDecimal.ROUND_HALF_UP);
The result of this is a BigDecimal with the value 1.24 (because of the rounding up rule)
结果是一个值为 1.24 的 BigDecimal(由于四舍五入规则)
回答by guitar_freak
I would add here, a few examples. I haven't found them in previous answers, but I find them useful for those who maybe mislead significant digitswith number of decimal places. Let's assume, we have such context:
我想在这里补充几个例子。我在以前的答案中没有找到它们,但我发现它们对于那些可能会误导小数位数的有效数字的人很有用。让我们假设,我们有这样的上下文:
MathContext MATH_CTX = new MathContext(3, RoundingMode.HALF_UP);
For this code:
对于此代码:
BigDecimal d1 = new BigDecimal(1234.4, MATH_CTX);
System.out.println(d1);
it's perfectly clear, that your result is 1.23E+3
as guys said above. First significant digits are 123...
很明显,你的结果1.23E+3
正如上面所说的那样。第一位有效数字是 123...
But what in this case:
但是在这种情况下:
BigDecimal d2 = new BigDecimal(0.000000454770054, MATH_CTX);
System.out.println(d2);
your number will not be rounded to 3 places after comma- for someone it can be not intuitive and worth to emphasize. Instead it will be rounded to the first 3 significant digits, which in this case are "4 5 4". So above code results in 4.55E-7
and not in 0.000
as someone could expect.
您的数字不会在逗号后四舍五入到 3 位- 对于某些人来说,这可能不直观且值得强调。相反,它将四舍五入到前 3 个有效数字,在这种情况下是“4 5 4”。所以上面的代码导致4.55E-7
而不是0.000
正如人们所期望的那样。
Similar examples:
类似的例子:
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
I hope this obvious, but relevant example would be helpful...
我希望这个显而易见但相关的例子会有所帮助......