Java in double turn BigDecima cause loss of precision

1. wedges

Service in the following code appeared strange unequal problem? Finally found leading to loss of precision when double turn bigDecimal. Code and runs as follows:

        @Test
    public void doubleToDecimal() {
        double amountDouble = 16.67;
        BigDecimal amountDecimal = new BigDecimal("16.67");
        System.out.println(amountDecimal.compareTo(new BigDecimal(amountDouble)));

        System.out.println("amountDouble: " + amountDouble);
        System.out.println("amountDecimal: " + amountDecimal);
        System.out.println("new BigDecimal(amountDouble): " + new BigDecimal(amountDouble));
        System.out.println("BigDecimal.valueOf(amountDouble): " + BigDecimal.valueOf(amountDouble));
        System.out.println("new BigDecimal(Double.toString(amountDouble)): " + new BigDecimal(Double.toString(amountDouble)));
        System.out.println("new BigDecimal(String.valueOf(amountDouble)): " + new BigDecimal(String.valueOf(amountDouble)));
    }

Here Insert Picture Description
16.67 float into the top new BigDecimal()there was loss of precision, you can see 16.67changed 16.6700000000000017053025658242404460906982421875, which led compareTo not equal.

2. Analysis and proper use of gestures

float and double types of primary design goal is to 科学计算和工程计算. They perform a binary floating-point arithmetic, which is to put on a wide range of values 供较为精确的快速近似计算and well-designed. However, they do not provide fully accurate results, it should not be the case for applications requiring accurate results. Formal occasions should use BigDecimal.

Because 十进制的16.67本身就是无法用二进制精确表示, also said that no matter how many are your accuracy, can not be accurately represented in binary 16.67, so close to double figures only said that this is the disadvantage of binary computer, it can not be expressed as a decimal also 1/3, Like 1/6. If you use this to initialize bigDecimal double if the same problem occurs.

BigDecimal constructor public BigDecimal(double val)will lose double precision parameter. jdk has been clearly do not recommend using new BigDecimal(double value)this form of the constructor, but the use of new BigDecimal(Stringvalue)or BigDecimal.valueof( double value).

new BigDecimal(double value) javadoc as follows (have made it very clear, the situation will be unpredictable), do not use Recommend:
Here Insert Picture Description

BigDecimal.valueof( double value)Source as follows:
Here Insert Picture Description
This method is the recommended method BigDecimal converted from a double.
Here Insert Picture Description

3. Conclusion

We do not recommend the use of new BigDecimal(double value)this form of the constructor, but the use of new BigDecimal(Stringvalue)or BigDecimal.valueof( double value).

4. Further reading

Published 418 original articles · won praise 745 · Views 1.26 million +

Guess you like

Origin blog.csdn.net/u013467442/article/details/89450580
Recommended