[英]Why does Java's RoundingMode HALF_DOWN round 1.245 to 1.25?
BigDecimal bd1 = new BigDecimal(1.245);
System.out.println(">> Half up: "
+ bd1.setScale(2, BigDecimal.ROUND_HALF_UP));
System.out.println(">> Half down: "
+ bd1.setScale(2, BigDecimal.ROUND_HALF_DOWN));
Results: 结果:
Half up: 1.25
上半场:1.25
Half down: 1.25
半场:1.25
It's the result of the initial double in the constructor. 它是构造函数中初始double的结果。 If you do
如果你这样做
BigDecimal bd1 = new BigDecimal("1.245");
(ie with quotes) it'll work as expected. (即带引号)它将按预期工作。
The double value 1.245
cannot accurately be represented, it is actually 1.24500000000000010658141036401502788066864013671875
, hence it is too large for actual rounding "down". 双值
1.245
无法准确表示,实际上是1.24500000000000010658141036401502788066864013671875
,因此对于实际舍入“向下”来说太大了。
if you print original value, you will see: 如果您打印原始值,您将看到:
1.24500000000000010658141036401502788066864013671875
this is because 1.245 cannot be represented as double number 这是因为1.245不能表示为双数
now read documentation about setScale ROUND_HALF_DOWN 现在阅读有关setScale ROUND_HALF_DOWN的文档
Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
舍入模式向“最近邻居”舍入,除非两个邻居等距,在这种情况下向下舍入。 Behaves as for ROUND_UP if the discarded fraction is > 0.5 ;
如果丢弃的分数> 0.5 , 则表现为ROUND_UP ; otherwise, behaves as for ROUND_DOWN.
否则,表现为ROUND_DOWN。
as you see discarded fraction is > 0.5, not equal as you expected 如您所见,丢弃的分数> 0.5,与您的预期不相等
if you declare your initial variable as BigDecimal bd1 = new BigDecimal("1.245");
如果你将你的初始变量声明为
BigDecimal bd1 = new BigDecimal("1.245");
you will get expected result 你会得到预期的结果
我认为这是因为你使用了一个带有float
的构造函数,它将你的值转换为1.2456345
,试试这个:
BigDecimal bd1 = new BigDecimal("1.245");
Problem comes from float. 问题来自浮动。 You shoud know that using float and double, you will never get precise value.
你应该知道使用float和double,你永远不会得到精确的值。 Like 0.1 is not equal to 1/10.
像0.1不等于1/10。
If you are interested in high precision you must use BigDecimal, but unitialize it with a string value, so that you won't loose presicion due to float casting. 如果您对高精度感兴趣,则必须使用BigDecimal,但是将其与字符串值一起使用,这样您就不会因浮动投射而失去预备。
Change your code to this: 将您的代码更改为:
BigDecimal bd1 = new BigDecimal("1.245");
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
You can see that "Note: For values other than float and double NaN and ±Infinity, this constructor is compatible with the values returned by Float.toString(float) and Double.toString(double). This is generally the preferred way to convert a float or double into a BigDecimal, as it doesn't suffer from the unpredictability of the BigDecimal(double) constructor." 你可以看到“注意:对于float和double NaN以及±Infinity以外的值,这个构造函数与Float.toString(float)和Double.toString(double)返回的值兼容。这通常是转换的首选方式一个浮点数或双重进入BigDecimal,因为它不会受到BigDecimal(double)构造函数的不可预测性的影响。“
So, if you want to set up a BigDecimal by a float number, you should 所以,如果你想用浮点数设置一个BigDecimal,你应该这样做
BigDecimal bd1 = new BigDecimal(Float.toString(1.245f));
You may also check the note of the constructor public BigDecimal(double val) 您还可以检查构造函数public BigDecimal(double val)的注释
The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which is exactly equal to 0.1, as one would expect. 另一方面,String构造函数是完全可预测的:写入新的BigDecimal(“0.1”)会创建一个BigDecimal,它正好等于0.1,正如人们所期望的那样。 Therefore, it is generally recommended that the String constructor be used in preference to this one.
因此,通常建议优先使用String构造函数。
When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; 当double必须用作BigDecimal的源时,请注意此构造函数提供了精确的转换; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor.
它不会产生与使用Double.toString(double)方法将double转换为String然后使用BigDecimal(String)构造函数相同的结果。 To get that result, use the static valueOf(double) method.
要获得该结果,请使用static valueOf(double)方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.