-1

In Java (Eclipse), 33.6f*100 gives 3359.9998. Even if 33.6*100 gives 3360. I don't succeed to reproduce this issue with other values (for example 32.6f*100 gives 3260).

Do you know what is it due to and how I can fix the issue? in my case 33.6f is given by the Math.abs function so I cannot just remove the "f".

johanvs
  • 4,273
  • 3
  • 24
  • 26
  • 2
    http://floating-point-gui.de/ – clcto Sep 08 '14 at 16:23
  • This is the way floating point works. It's not (usually) exact. Use `==` comparison with great care (if you use it at all). – Hot Licks Sep 08 '14 at 16:28
  • possible duplicate of [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Henry Keiter Sep 08 '14 at 16:28
  • Don't know what you mean by your last sentence: there are overloaded versions of `Math.abs` including one that takes a `double`, so why can't you remove the `f`? (Not that I recommend that as the solution. `double` has the same problem when your numbers get large enough.) – ajb Sep 08 '14 at 16:36
  • You should use `BigDecimal` instead. – Hannes Sep 08 '14 at 16:51
  • It's not the same. I already had the issue of unwanted decimals at the 15th position, and did the necessary. Here it's odd because if is at the 4th position, and because it is just for a particular value that it occurs. The epsilon method mentioned doesn't work because the delta is up than 1e-5. @ajb : you are right, it is not a correct justification. The point is just that I got a float variable (and then cannot remove the `f`) – johanvs Sep 08 '14 at 17:06
  • You don't say what you mean by `33.6f*100` **gives** `3359.9998`. What exactly do you mean by "gives"? I.e. how did you get that output? (No `float` or `double` will hold the number 3359.9998 _exactly_.) When I try `String.format("%10.4f",value)`, I did get the "issue" with `32.6f * 100` (it outputs `3259.9998`). So maybe you did something different? Anyway, never try to output more than 6 significant digits with a `float` (that's on _both_ sides of the decimal point), or 15 with a `double`. – ajb Sep 08 '14 at 19:15
  • Thanks for your precisions ajb. You are right I was expecting to have more decimal numbers that I can have with my float. The value was **given** by my debugger (certainly obtained the same way than your `format` result). And confirmed by the behaviour of the code after. – johanvs Sep 09 '14 at 08:50

1 Answers1

1

Floating point numbers can be difficult to implement correctly, and they (as you have noticied) do not have infinite precision. The easiest solution I can think of is to use Math.round(float) like

float f = 33.6f;
f *= 100;
if (Math.round(f) == 3360) {
    System.out.println("Like so");
}

See also Appendix D: What Every Computer Scientist Should Know About Floating-Point Arithmetic.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • Rounding might not always be ideal. For example, 3359.5 would be 'equal' to 3360 in this case. From what I've seen, using an epsilon works better. – Obicere Sep 08 '14 at 16:29
  • For the not infinite precision I agree, but here it seems to be a very bad precision. My purpose was to delete the decimals of a floating number up to the third. So I did : `(float) (Math.floor(Math.abs(value) * 100) / 100)`. If I add a round around `Math.abs(balance) * 100` it may be okay. But sorry I'm not a computer scientist and it seems to be a too hard document to read to solve my small issue. – johanvs Sep 08 '14 at 17:19
  • `float` gives you about 6 decimal digits of precision. So if you want a value with 4 digits to the left of the decimal point, you can only have 2 to the right and expect answers that show up correctly. If you want 4 to the left and 4 to the right, that's 8. So you can't use `float`. – ajb Sep 08 '14 at 19:18