Search code examples
cfloating-pointbit-manipulation

is (0.1 + 0.2) == 0.3 true or false?


I have a basic understanding in float-point number and was reading this article which says:

0.1 + 0.2: This equals 0.3, but in floating-point: (0.1 + 0.2) == 0.3 is false. This is because 0.1, 0.2 and 0.3 cannot be precisely represented in base 2 floating-point.

Well, that's true according to the nature of floating point number, but I wrote a simple program to test:

float a = 0.1;
float b = 0.2;

if(a+b == 0.3)
{
  printf("true");
} else 
{
  printf("false");
}
// result is true

but the output is actually true. Here is my two questions:

  1. I think what happens is, because C uses the round-to-even rounding mode, so after rounding, it happens to be true, is my understanding correct?

  2. If my understanding is correct, then there must be some specified float-point number won't be true in this case, because there is still a small chance that rounding might fail. So that must be some combination as

    float a = ...;
    float b = ...;
    if(a+b == XXX)  // where XXX is the "intuitive" sum of a and b
    {
      printf("true");
    } else 
    {
      printf("false");   
    }
    
    //result is false now
    

Is my understanding correct?


Solution

  • I get false for your program, not true as you indicate in your question. (0.3 is a double literal, so my guess is that when you tested this locally, you used a float variable instead of a 0.3 literal.) If you actually use float (== 0.3f instead of == 0.3), you get true as the output because it just so happens that with float, 0.1 + 0.2 == 0.3 is true.

    But, the fundamental point remains that the IEEE-754 binary floating-point used by float (single-precision) and double (double-precision) is really fast to calculate and useful for lots of things, but inherently imprecise for some values, and so you get that kind of issue. With float, you get true for 0.1 + 0.2 == 0.3, but you get false for 0.1 + 0.6 == 0.7:

    #include <stdio.h>
    
    int main() {
        printf("%s\n", 0.1f + 0.6f == 0.7f ? "true" : "false"); // prints false
        //             ^^^^−−−^^^^−−−−^^^^−−− `float` literals
        return 0;
    }
    

    The famous 0.1 + 0.2 == 0.3 version of this issue happens to double:

    #include <stdio.h>
    
    int main() {
        printf("%s\n", 0.1 + 0.2 == 0.3 ? "true" : "false"); // prints false
        //             ^^^−−−^^^−−−−^^^−−− `double` literals
        return 0;
    }