-1
    double test = 1029 / 9.8; // = 104.99999...
    int inttest1 = (int) test; // 104
    int inttest2 = (int)Math.floor(test); // 104
    double testtt = 9.8 * 105; // 1029.0

1029 / 9.8 equals 105

but Java returns 104.9999...

More serious problem is integer casing result is 104, not 105

Why this happens and how can I avoid this result?

heekyu
  • 93
  • 2
  • 9
  • 3
    Use [`java.math.BigDecimal`](http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html). – Tiny Mar 26 '14 at 06:18
  • see also http://stackoverflow.com/questions/2143476/how-to-cast-a-double-to-an-int-in-java – Scary Wombat Mar 26 '14 at 06:19
  • This is due to the inherent "imprecision" of `double`. If you need error free decimal calculations, you have no other choice but using `BigDecimal` or, if you can afford using an external library, apfloat. – fge Mar 26 '14 at 06:21
  • Casting *always* truncates - which is equivalent to floor on positive values, ceil on negative values - and, as such, casting is *not* a suitable replacement for the appropriate [rounding](http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#round(float)) or otherwise dealing with this situation. – user2864740 Mar 26 '14 at 06:23

3 Answers3

1

There are an infinite number of numbers, even in the limited range represented by Java. That's because mathematically, if you give me any two distinct numbers, I can average them to get a number between them. No matter how close they are.

And there are only a limited number of bits available to represent those numbers.

Hence, something has to give. What gives is the precision of the numbers. Not all numbers can be represented exactly, so some (the vast majority actually) are approximations.

For example, 0.1 cannot be represented exactly with IEEE754 encoding, even with a billion bits available to you.

See this answer for more information on the inherent imprecision of limited-storage floating point numbers.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
1

Casting to an int implicitly drops any decimal. No need to call Math.floor() (assuming positive numbers)

To avoid this behavior use BigDecimal;

http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html

Scary Wombat
  • 44,617
  • 6
  • 35
  • 64
0

Standard floating point variables are in binary floating point. Many decimal floating point values (which are the ones you type in your code) have no exact representation in binary floating point. So it isn't doing the calculation with the exact numbers you entered but with some values very close to it. You can use Math.round to round the result to the precision you need and most likely the small error will disappear.

If you really need exact decimal calculation use BigDecimal but note that it is much slower.

Eelke
  • 20,897
  • 4
  • 50
  • 76