BigDecimal/double Precision - 数字向上舍入

BigDecimal/double Precision - number rounds up higher

提问人:jerry.pepper 提问时间:7/17/2018 更新时间:7/17/2018 访问量:286

问:

以下方法调用的第二个 setYCoordinate() 获取不正确的值 -89.99999435599995 而不是 -89.99999435599994。

对 setXCoordinate() 的第一次调用获得正确的值 29.99993874900002。

setXCoordinate(BigDecimal.valueOf(29.99993874900002))
setYCoordinate(BigDecimal.valueOf(-89.99999435599994))

我在 BigDecimal.valueOf() 中放置了一个断点 - 此方法的代码如下所示 -

public static BigDecimal valueOf(double val) {
        // Reminder: a zero double returns '0.0', so we cannot fastpath
        // to use the constant ZERO.  This might be important enough to
        // justify a factory approach, a cache, or a few private
        // constants, later.
        return new BigDecimal(Double.toString(val));
    }

valueOf 接收到的参数,即“double val”本身在检查时为 -89.99999435599995。为什么?我在我的 Maven pom.xml 中设置了如下 Java 版本

<java.version>1.8</java.version>
java 精度 bigdecimal

评论

0赞 Ken Y-N 7/17/2018
Java 显然有 15 位十进制数字的精度,但您的坐标有 16 位数字。无论如何,您都不应该依赖这种程度的准确性。
2赞 user207421 7/17/2018
@KenY-N:这不是你的引文中所说的。它有 15.9 个整数十进制数字的精度。小数点后的含义取决于值。请参阅引文的最后一句话。我写的。
0赞 Hulk 7/17/2018
密切相关:stackoverflow.com/questions/16216248/...
0赞 Hulk 7/17/2018
...但是,在这个问题中引起混淆的转换发生在调用任何方法之前,当文字被解释为 .double

答:

9赞 Jacob G. 7/17/2018 #1

因为 a 无法保持那么高的精度;在初始化 :doubledoubleStringBigDecimal

new BigDecimal("29.99993874900002");
new BigDecimal("-89.99999435599994");

请参阅:浮点数学坏了吗?

评论

0赞 jerry.pepper 7/17/2018
更改为 setYCoordinate(new BigDecimal(-89.99999435599994)) 后,setYCoordinate 收到的值为 -89.99999435599994512813282199203968048095703125 - 我不需要也想要那么多数字,因为我在其他地方进行了精确的比较。
2赞 Jacob G. 7/17/2018
@jerry.pepper 你应该使用我的答案中所示的。String
0赞 Peter Lawrey 7/17/2018
@jerry.pepper,您可以对结果进行四舍五入,即使用 String 表示形式来获得比双支持更高的精度。
0赞 kshetline 7/17/2018 #2

对于指定了 16 位数字的双精度浮点值,您正处于精度的边缘,并且只有不到 16 位的十进制精度可用。如果您完全跳过 BigDecimal,只需将双精度设置为 -89.99999435599994 并将其打印出来,您将得到 -89.99999435599995。

1赞 Hulk 7/17/2018 #3

你的困惑与.BigDecimal

double d = -89.99999435599994;
System.out.println(d); //or inspecting it in a debugger

收益 率:

-89.99999435599995

这就是 java 中的工作方式,结合 Double.toString 定义 -representation 的方式。当文本被解释为 时,在调用任何方法之前发生此转换。JLS 第 3.10.2 章中指定了详细信息。浮点文字Double.valueOf(String) 的 JavaDocsdoublesStringdouble


如果您需要将值表示为 ,最简单的方法是使用构造函数接受 String,正如其他答案已经指出的那样:-89.99999435599994BigDecimal

BigDecimal bd = new BigDecimal(“-89.99999435599994”);

BigDecimal bd = new BigDecimal("-89.99999435599994");
System.out.println(bd);

收益 率:

-89.99999435599994