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

时间:2015-01-29 08:07:25

标签: java

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));

结果:

  
    

一半:1.25

         

半场:1.25

  

5 个答案:

答案 0 :(得分:4)

这是构造函数中初始double的结果。如果你这样做

BigDecimal bd1 = new BigDecimal("1.245");

(即带引号)它会按预期工作。

双值1.245无法准确表示,实际上是1.24500000000000010658141036401502788066864013671875,因此它太大而无法实际舍入“向下”。

答案 1 :(得分:3)

如果您打印原始值,您将看到:

1.24500000000000010658141036401502788066864013671875

这是因为1.245不能表示为双号

现在阅读有关setScale ROUND_HALF_DOWN

的文档
  

舍入模式向"最近邻居"除非两者   邻居是等距的,在这种情况下向下舍入。表现为    ROUND_UP,如果丢弃的分数> 0.5 ;否则,表现得像   ROUND_DOWN。

如您所见,丢弃的分数> 0.5,与预期不相等

如果您将初始变量声明为BigDecimal bd1 = new BigDecimal("1.245");,则会获得预期结果

答案 2 :(得分:2)

我认为这是因为您使用了float的构造函数,它会将您的值转换为1.2456345,请尝试:

BigDecimal bd1 = new BigDecimal("1.245");

答案 3 :(得分:1)

问题来自浮动。你应该知道使用float和double,你永远不会得到精确的值。像0.1不等于1/10。

如果您对高精度感兴趣,则必须使用BigDecimal,但要将其与字符串值一起使用,这样您就不会因浮动投射而失去预备。

将您的代码更改为:

BigDecimal bd1 = new BigDecimal("1.245");

答案 4 :(得分:1)

http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html

你可以看到“注意:对于float和double NaN以及±Infinity以外的值,这个构造函数与Float.toString(float)和Double.toString(double)返回的值兼容。这通常是首选将float或double转换为BigDecimal的方法,因为它不会受到BigDecimal(double)构造函数的不可预测性的影响。“

所以,如果你想用浮点数设置一个BigDecimal,你应该

BigDecimal bd1 = new BigDecimal(Float.toString(1.245f));

您还可以查看构造函数的注释 public BigDecimal(double val)

  1. 此构造函数的结果可能有些不可预测。有人可能会假设在Java中编写新的BigDecimal(0.1)会创建一个BigDecimal,它恰好等于0.1(未缩放值为1,标度为1),但它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能精确地表示为double(或者,就此而言,作为任何有限长度的二进制分数)。因此,传递给构造函数的值并不完全等于0.1,尽管有外观。
  2. 另一方面,String构造函数是完全可预测的:编写新的BigDecimal(“0.1”)会创建一个BigDecimal,它正好等于0.1,正如人们所期望的那样。因此,通常建议首先使用String构造函数。

  3. 当必须将double用作BigDecimal的源时,请注意此构造函数提供了精确的转换;它不会产生与使用Double.toString(double)方法将double转换为String然后使用BigDecimal(String)构造函数相同的结果。要获得该结果,请使用static valueOf(double)方法。