简体   繁体   English

为什么Java的RoundingMode HALF_DOWN在1.245到1.25之间?

[英]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)的注释

  1. The results of this constructor can be somewhat unpredictable. 这个构造函数的结果可能有点不可预测。 One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. 可以假设在Java中编写新的BigDecimal(0.1)会创建一个BigDecimal,它恰好等于0.1(未缩放的值为1,比例为1),但它实际上等于0.1000000000000000055511151231257827021181583404541015625。 This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). 这是因为0.1不能精确地表示为double(或者,就此而言,作为任何有限长度的二进制分数)。 Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding. 因此,传递给构造函数的值并不完全等于0.1,尽管有外观。
  2. 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构造函数。

  3. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM