5
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

mskfisher
  • 3,291
  • 4
  • 35
  • 48
  • 3
    http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – Mysticial Jul 19 '12 at 09:32
  • I recommend reading [this](http://stackoverflow.com/q/1089018/1343161). – Keppil Jul 19 '12 at 09:32
  • possible duplicate of [Floating point arithmetic not producing exact results in Java](http://stackoverflow.com/questions/1661273/floating-point-arithmetic-not-producing-exact-results-in-java) – oers Jul 20 '12 at 08:32
  • Possible duplicate of [Floating point arithmetic not producing exact results](https://stackoverflow.com/questions/1661273/floating-point-arithmetic-not-producing-exact-results) – Louis Aug 14 '18 at 11:03
  • 2
    Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – james.garriss Aug 14 '18 at 14:54

4 Answers4

5

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
dacwe
  • 43,066
  • 12
  • 116
  • 140
  • So, is it the problems or Bug of float? Should I use double to avoid bug? –  Jul 19 '12 at 09:43
  • 3
    OP, these are not bugs. Please read what others have suggested below your question. Awareness of these issues is Programming 101. – Marko Topolnik Jul 19 '12 at 09:48
  • That said, the best way to do it is to use `String` instead of `double` _or_ `float`. – Louis Wasserman Jul 19 '12 at 09:51
  • Thanks all of you, all answers are very helpful to me, but I have to choose only 1 best answer only. I choose answer from dacwe, because I am just a simple programmer, know how to workaround is enough for me. –  Jul 20 '12 at 01:54
0

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.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

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.

Matt
  • 11,523
  • 2
  • 23
  • 33
0

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);
RyanS
  • 3,964
  • 3
  • 23
  • 37