[JAVA] BigDecimal.valueOf (double) story

Decimal with Big Decimal

Big Decimal is the de facto standard for decimal calculations in java. If you try to calculate with double type or float type, an error will occur in a blink of an eye and it will be terrible.

What's more, this Big Decimal is likely to be used most by newcomers due to its bad nature. If you write the following code, an error will occur after all. Since there is an error when declaring it as double type, This is because even if you create a Big Decimal based on it, the error will be retained as it is. When I was a newcomer, my seniors slammed me into writing as below.


BigDecimal bad = new BigDecimal(1.3);
//Internally 1.3000000000000000444089209850062616169452667236328125

BigDecimal good = new BigDecimal("1.3");

BigDecimal.valueOf(double) So, when dealing with decimals in BigDecimal, the argument is a string and it completely permeates the body. A quick search recently revealed that there were quite a few commentary pages that said that BigDecimal.valueOf (double) could handle double types without any problems.

However, considering that new BigDecimal (double) cannot hold the exact decimal number at the time of double type, an error will occur. BigDecimal.valueOf (double) should also have an error.

But, surprisingly, in most cases BigDecimal.valueOf (double) works correctly.

BigDecimal fromValueOf = BigDecimal.valueOf(1.3);
//This is new Big Decimal("1.3")Will be the same value as

What does that mean.

Implementation of BigDecimal.valueOf

Looking at the implementation of BigDecimal.valueOf (double), it was as follows. (Quoted from OpenJdk)

    public static BigDecimal valueOf(double val) {
        //The comment part is omitted
        return new BigDecimal(Double.toString(val));
    }

The implementation is surprisingly simple, generating BigDecimal from a string using a stringized value of double type with Double.toString (double). So, as long as Double.toString (double) properly returns the literal value (or the corresponding numeric representation) from which the double value was based, it's likely to return the BigDecimal you intended.

Does Double.toString () restore the value properly?

It's okay in most cases, but it doesn't seem to return perfectly for numbers with a very large number of decimal places.

BigDecimal.valueOf(1.0000000003000003)
//1.0000000003000002

However, if you do not aim at it, it will not shift basically. It seems unlikely that you will use such a small number of digits.

Summary

Digression

By the way, this is the case when the double declared in the literal is used as it is. If you use the value after calculating with double type, it will not work.

BigDecimal.valueOf(1.3 + 1.5 + 1.4)
///4.199999999999999

After making the calculation Big Decimal.

Recommended Posts

BigDecimal.valueOf (double) story
JUnit story
Range story
MyBatis story