BigDecimal/double Precision - number rounds up higher

不想你离开。 提交于 2021-02-10 06:19:36

问题


The second of below method calls, to setYCoordinate(), gets incorrect value -89.99999435599995 instead of -89.99999435599994.

The first call to setXCoordinate() gets correct value 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 -

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 i.e. "double val" itself is -89.99999435599995 when inspected. Why? I have Java version set as below in my Maven pom.xml

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

回答1:


Because a double can't retain that much precision; you shouldn't use a double, but rather a String when initializing your BigDecimal:

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

See: Is floating point math broken?




回答2:


Your confusion has nothing to do with BigDecimal.

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

yields:

-89.99999435599995

This is just the way doubles work in java, in combination with the way Double.toString defines the String-representation. This conversion happens before any method is invoked, when the literal is interpreted as double. The details are specified in JLS Chapter 3.10.2. Floating-Point Literals and the JavaDocs of Double.valueOf(String).


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:

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

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

yields:

-89.99999435599994




回答3:


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. If you skip BigDecimal entirely, just set a double to -89.99999435599994 and print it back out, you'll get -89.99999435599995.



来源:https://stackoverflow.com/questions/51371109/bigdecimal-double-precision-number-rounds-up-higher

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!