简体   繁体   English

BigDecimal / double精度 - 数字向上舍入

[英]BigDecimal/double Precision - number rounds up higher

The second of below method calls, to setYCoordinate(), gets incorrect value -89.99999435599995 instead of -89.99999435599994. 以下方法调用中的第二个调用setYCoordinate(),得到的值不正确-89.99999435599995而不是-89.99999435599994。

The first call to setXCoordinate() gets correct value 29.99993874900002. 第一次调用setXCoordinate()得到正确的值29.99993874900002。

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

I put a breakpoint inside BigDecimal.valueOf() - this method's code looks as below - 我在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));
    }

The argument received by valueOf ie "double val" itself is -89.99999435599995 when inspected. valueOf收到的参数即“双val”本身在检查时为-89.99999435599995。 Why? 为什么? I have Java version set as below in my Maven pom.xml 我在Maven pom.xml中设置了Java版本,如下所示

<java.version>1.8</java.version>

Because a double can't retain that much precision; 因为double不能保持那么高的精度; you shouldn't use a double , but rather a String when initializing your BigDecimal : 在初始化BigDecimal时,不应该使用double ,而是使用String

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

See: Is floating point math broken? 请参阅: 浮点数学是否已损坏?

Your confusion has nothing to do with BigDecimal . 你的困惑与BigDecimal无关。

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

yields: 收益率:

-89.99999435599995 -89.99999435599995

This is just the way doubles work in java, in combination with the way Double.toString defines the String -representation. 这就是在doubles的方式,结合Double.toString定义String Double.toString的方式。 This conversion happens before any method is invoked, when the literal is interpreted as double . 在将文字解释为double时,在调用任何方法之前进行此转换。 The details are specified in JLS Chapter 3.10.2. 详细信息在JLS第3.10.2章中指定 Floating-Point Literals and the JavaDocs of Double.valueOf(String) . 浮点字面值Double.valueOf(String)JavaDoc


If you need to express the value -89.99999435599994 as BigDecimal , the easiest way is to use the constructor taking a String , as other answers have already pointed out: 如果你需要将值-89.99999435599994表示为BigDecimal ,最简单的方法是使用构造函数获取String ,因为其他答案已经指出:

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

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

yields: 收益率:

-89.99999435599994 -89.99999435599994

You're right on the edge of precision for a double-precision floating point value, with 16 digits specified, and there's just shy of a full 16 digits of decimal accuracy available. 对于双精度浮点值而言,您处于精度的边缘,指定了16位数,并且只有十几位小数精度可用。 If you skip BigDecimal entirely, just set a double to -89.99999435599994 and print it back out, you'll get -89.99999435599995. 如果您完全跳过BigDecimal,只需将一个双精度设置为-89.99999435599994并将其打印出来,您将得到-89.99999435599995。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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