Skizzo
Skizzo

Reputation: 2983

Strange BigDecimal value using DecimalFormat

I'm trying to convert some string values in number using DecimalFormat. I try to explain you my problem in a better way:

I have the following method:

private BigDecimal loadBigDecimal(String value){

    BigDecimal bigDecimalToReturn = null;
    DecimalFormat df = new DecimalFormat("##.###");
    bigDecimalToReturn = new BigDecimal(df.parse(value).doubleValue());
    return bigDecimalToReturn;
}

Now if I try to run the method:

BigDeciaml dec = myObject.loadBigDecimal("120,11");

The value of dec is 120.1099999999999994315658113919198513031005859375. Why decimalFormat is changing the scale of my value?

Upvotes: 1

Views: 687

Answers (3)

Orace
Orace

Reputation: 8359

That is because of the df.parse(value).doubleValue() call. At this point, the value is converted to a double.

double represent plus or minus the sum of powers of 2 (with positive and negative exponents).

One can write 120 as 64+32+16+8.

But one can't write 0.11 as a finite sum of power of 2.

So there is an approximation.

0.1099999999999994315658113919198513031005859375

Which is a sum of power of 2.

It's look like BigDecimal as a constructor with a string for parameter. Maybe you can just use it.

BigDecimal dec = new BigDecimal("120,11");

Upvotes: 1

vbezhenar
vbezhenar

Reputation: 12316

You are doing conversion to double and backwards. That's unnecessary and introduces rounding errors. You should use the following code:

private BigDecimal loadBigDecimal(String value) throws ParseException {
    DecimalFormat df = new DecimalFormat("##.###");
    df.setParseBigDecimal(true);
    return (BigDecimal) df.parse(value);
}

Upvotes: 5

Necreaux
Necreaux

Reputation: 9776

Doubles are only approximations. That is correct for a double. If you want a specific scale, you need to tell it in the BigDecimal constructor.

Upvotes: 3

Related Questions