user1482015
user1482015

Reputation:

Float and BigDecimal precision difference

public static void main(String[] args) {
    // TODO Auto-generated method stub
    BigDecimal foo,foo1;
    foo=BigDecimal.valueOf(3.1);
    foo1=BigDecimal.valueOf(3.1f);

    System.out.println(foo);
    System.out.println(foo1);

}

RESULT:
3.1
3.0999999046325684

Why they are different result? I am using JDK1.7.0_03

Upvotes: 5

Views: 17202

Answers (4)

Jay Patel
Jay Patel

Reputation: 1

I had a similar issue due to a rookie mistake which I wanted to share:

BigDecimal bd = new BigDecimal(float); 

This was giving that extra precision I didn't want and setting it to String fixed it...

However, I was doing this:

BigDecimal bd = new BigDecimal(float);
bd.setScale(2, RoundingMode.HALF_UP);

Rookie Mistake. I should have done this.

bd = bd.setScale(2, RoundingMode.HALF_UP);

Upvotes: 0

Matt
Matt

Reputation: 11805

The problem is that for both float and double, you are using 32 and 64 bits respectively for representation of both the integer and decimal part of the number. The problem comes in when you try to represent a fractional value which doesn't really have an accurate decimal representation in binary bits.

Take .1 for example, there's no way to exactly represent this in base 2, any more than there is a way to accurately represent 1/3 in base 10.

So java uses some tricks so that when you say:

float f = 3.1;
System.out.println(f);

It prints out the right number. However, when you start doing arithmetic with these values, you end up with rounding errors.

BigDecimal is accurate because it uses a different representation. It internally stores a BigInteger (which uses an int[] to represent huge numbers). It then uses a precision value to tell it how many of those integer digits are are after the decimal point.

For instance, the value 3.1 would be represented in a BigDecimal as 31,precision=1 For this reason, BigDecimal doesn't suffer from the same rounding issues a float and double.

However, when you use a float/double value to initialize a BigDecimal, the same rounding error makes it's way into the BigDecimal instance. That's why it's recommended to use a String to construct the value.

Upvotes: 0

Peter Lawrey
Peter Lawrey

Reputation: 533500

float and double are different types with different precisions.

BigDecimal.valueOf(double) can correct for the representation error in double but not that in float

IMHO don't use float unless you have a very reason to do so.

Upvotes: 0

dacwe
dacwe

Reputation: 43504

3.1 defines a double while 3.1f defines a float. What you see is the problem the float has of representing that value (float uses "only" 32-bits and double 64-bits).

If you want to define a 3.1 exactly using BigDecimal use the String constructor:

BigDecimal foo = new BigDecimal("3.1");
System.out.println(foo);

Output:

3.1

Upvotes: 5

Related Questions