3

Consider the following code:

float x = 0.1;
if ( x> 0.1){
    printf("if");
}

Now when I check equality, it is explained that x is being converted to double by padding 0s at the end, but 0.1 on RHS is stored in double, hence the inequality. But if I go through this logic, the "if" in the above code should have given false, but istead it is true. Why?

Avijeet Ghosh
  • 167
  • 1
  • 8
  • 1
    floats are not perfectly precise. They cannot represent every number and so there will be rounding errors. In this case, it apparently rounded up to a value just a tiny bit greater than `0.1`. – Christian Gibbons Nov 23 '17 at 17:15
  • 1
    @ChristianGibbons -- note that the constant `0.1` is also a floating point value, represented inexactly as a `double`. – ad absurdum Nov 23 '17 at 17:17
  • @DavidBowling Indeed. That was an error of omission on my part. – Christian Gibbons Nov 23 '17 at 17:18
  • It's just an oversight that rounding (up) already happens with `float x = 0.1;`. –  Nov 23 '17 at 17:25

2 Answers2

7

(Restricting the answer to IEEE754 although all floating point schemes supported by C mandate that the double set is a superset of the float set.)

0.1 is 0.1000000000000000055511151231257827021181583404541015625

0.1f is 0.100000001490116119384765625.

0.100000001490116119384765625 is promoted to a double, but it's the same number as all floats can be represented as doubles exactly.

So (double)(0.1f) is bigger than 0.1, accounting for the result.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
2

The key issue is that 0.1 can't be represented exactly in binary. Converting this to base 2, you get a number with a repetend in the fraction part, 1001 is repeating forever (just like in decimal, 1/3 ends up with 3 repeating forever).

When storing 0.1 in a float, it ends up getting rounded up in the last digit *), therefore the float 0.1 is larger than the double 0.1

So, yes, converting the float to double just appends (binary) zeros, but the float was already a bit too large in the first place.


*) this actually depends on the representation of floating point numbers your implementation uses. With IEEE 754 floats, the representation would end with

... 10011001100

and because the next digit would be a 1, rounding is done upwards, so the final result ends with

... 10011001101
  • The phrasing “a period in the fraction part” made me think there was a “.” in the fraction part. I think it would be clearer to say that the binary digits in the fraction part continue forever, with a repeating pattern. – Eric Postpischil Nov 24 '17 at 01:09
  • @EricPostpischil mindless direct translation of the german word, the mathematical languages differ :( In german, it's indeed a "period" (in the sense of a uniformly repeating pattern); I just looked it up, in english it's called a "repetend" ... –  Nov 24 '17 at 08:56
  • Well, I just learned a new word. – Eric Postpischil Nov 24 '17 at 14:55