Reputation:
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
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
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
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
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