19

When using double or float data type in an iPhone app, I am running into problems with ">=" and "<=" comparisons because when a variable is assigned a number entered with one decimal place, such as 4.2, the float or double used in the comparison actually may have a value such as 4.1999998092651367. Because of this difference, a comparison such as ">= 4.2" is false instead of true. How can I avoid this problem?

blahdiblah
  • 33,069
  • 21
  • 98
  • 152
user183804
  • 531
  • 1
  • 8
  • 21
  • See http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison –  Feb 17 '11 at 04:02
  • Also, http://www.eecg.toronto.edu/~moshovos/ECE243-2008/00.practice/What%20Every%20Computer%20Scientist%20Should%20Know%20About%20Floating-Point%20Arithmetic.htm –  Feb 17 '11 at 04:03
  • Are you getting the problem with both `float` and `double` variables? Please post some sample code? – Vijay Mathew Feb 17 '11 at 04:04

1 Answers1

65

when a variable is assigned a number entered with one decimal place, such as 4.2, the float or double used in the comparison actually may have a value such as 4.1999998092651367

Not may. will. To be specific:

float f = 4.2;  // f is exactly 4.19999980926513671875
double d = 4.2; // d is exactly 4.20000000000000017763568394002504646778106689453125

The problem comes when you write something like:

float f = 4.2;
if (f >= 4.2) {
    // this block of code is not executed.
}

f is exactly 4.19999980926513671875, but you're comparing it to the double-precision literal "4.2", which has the value 4.20000000000000017763568394002504646778106689453125, so the comparison fails. If instead you compare against the single precision literal "4.2f":

float f = 4.2;
if (f >= 4.2f) {
    // this block of code is exectued.
}

the comparison succeeds, because the values are exactly equal. Floating-point is complicated, but it is entirely deterministic; one of the simplest things you can do to make it more intuitive is to not mix precisions. If you're working with float, make sure all of your literals are suffixed with f to make them single precision, too.

(This can also improve performance, but that's not the reason to do it; the reason to do it is because it will make your code more correct).

FreeAsInBeer
  • 12,937
  • 5
  • 50
  • 82
Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
  • Thanks for setting me straight. Now the code works as expected with comparisons using the "f" suffix on integers. As a follow-on, is this sort of issue with floating-point arithmetic a "feature" or an unavoidable problem? Seems like something that easily could introduce computational errors from code that seems logical and compiles without a problem. – user183804 Feb 18 '11 at 03:18
  • 3
    @user183804: I wouldn't call it a feature or an unavoidable problem. More of a "that's the nature of binary floating point, learn about it or be doomed to trip over this sort of thing". It's not unique to floating-point by any stretch of the imagination; people are thrown off by integer overflow and other aspects of integer arithmetic all the time. Arithmetic on the computer is not the same as the arithmetic we learn in school, and that basically just a fact that we as programmers need to learn to work with. – Stephen Canon Feb 18 '11 at 04:45
  • Thanks again. I'll be going over all my code with this new knowledge in mind. You've been extremely helpful, since my coming iPhone app deals with medical calculations, so accuracy is paramount. – user183804 Feb 18 '11 at 17:38
  • I found this to be a good reference: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm – nielsbot Oct 21 '13 at 23:04
  • based on article I linked, you can try comparing the numbers as integers.. If they are within 1 integer of each other, they lie within one float/double precision step of each other. If you know neither argument is zero you can compare floats/doubles within some minimum precision. – nielsbot Oct 21 '13 at 23:06
  • @uchuugaka: `double` literals have no suffix. `long double` literals are suffixed with `l` or `L`. – Stephen Canon Jan 02 '14 at 10:52
  • Doh. Format specifier I was thinking of. – uchuugaka Jan 03 '14 at 02:51
  • @StephenCanon So If I use 4.2, it is explicitly double-precision/of-type-double unless I add f as a suffix? – nr5 Sep 26 '17 at 08:01
  • @Nil: In C or Objective-C? Yes. – Stephen Canon Sep 28 '17 at 20:15