1

In C, 0.55 == 0.55f is false while 0.5 == 0.5f is true. Why is it different?

  1. Comparing 0.55:

    #include <stdio.h>
    int main() {
        if (0.55 == 0.55f)
            printf("Hi");
        else
            printf("Hello");
    }
    

    Outputs Hello.

  2. Comparing 0.5:

    #include <stdio.h>
    int main() {
        if (0.5 == 0.5f)
            printf("Hi");
        else
            printf("Hello");
    }
    

    Outputs Hi.

For both the code snippets, I expected Hello.
Why this difference?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Artho Cruz
  • 31
  • 3
  • 2
    Very related: [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Some programmer dude Jul 10 '19 at 09:56
  • And for floating point values, you should almost never do direct comparison for equality. Use an *epsilon* to compare for closeness instead. – Some programmer dude Jul 10 '19 at 09:57
  • @George: Some programmer dude said "an epsilon", not a particular epsilon. – Bathsheba Jul 10 '19 at 10:00
  • @Bathsheba Ah yep missed that. Though i'd argue it's confusing since C++ defines FLT_EPSILON and std::numeric_limits::epsilon. – George Jul 10 '19 at 10:02
  • @George: As I'm sure you know, neither have any bearing at all on a choice of multiplicative, additive, or other type of *epsilon* one could consider using when comparing numerical quantities, – Bathsheba Jul 10 '19 at 10:04
  • This question is very close (to the point I'd probably say duplicate) to [this](https://stackoverflow.com/questions/41691261/strange-output-when-comparing-same-float-values) and [this](https://stackoverflow.com/questions/1839422/strange-output-in-comparison-of-float-with-float-literal). – StoryTeller - Unslander Monica Jul 10 '19 at 10:05
  • Possible duplicate of [Explain this floating point behavior](https://stackoverflow.com/questions/9461744/explain-this-floating-point-behavior) – phuclv Jul 10 '19 at 10:47
  • [Can someone please explain me that in java why 0.6 is <0.6f but 0.7is >=0.7f](https://stackoverflow.com/q/16698198/995714), [Floating point comparison `a != 0.7`](https://stackoverflow.com/q/6883306/995714), [strange output in comparison of float with float literal](https://stackoverflow.com/q/1839422/995714) – phuclv Jul 10 '19 at 10:48
  • Possible duplicate of [strange output in comparison of float with float literal](https://stackoverflow.com/questions/1839422/strange-output-in-comparison-of-float-with-float-literal) – Mark Dickinson Jul 10 '19 at 17:28

2 Answers2

4

0.5 is a dyadic rational and of an appropriate magnitude so 0.5 is exactly one-half either as a float or a double.

The same cannot be said for 0.55. A double will store that number with no less precision than a float, and most likely more.

In both cases, the float is implicitly converted to a double prior to ==, but by then any truncation has taken place.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • SO only for 0.5 the if part will work and for all other comparisons the else part will work, isn't it??@Bathsheba – Artho Cruz Jul 10 '19 at 09:59
  • Other numbers will work too, e.g. small integers, rationals like 0.25, large integral powers of 2. – Bathsheba Jul 10 '19 at 10:00
  • @Downvoter if I've slipped something please let me know. – Bathsheba Jul 10 '19 at 10:13
  • 2
    I did not down vote, but being a dyadic rational is a necessary but not sufficient condition that a number is exactly representable both as a `float` and a `double` (even assuming the C implementation uses base two). So this answer does not contain a full explanation. – Eric Postpischil Jul 10 '19 at 10:27
  • I've addressed that by adding "of an appropriate magnitude". – Bathsheba Jul 10 '19 at 13:10
4

You are comparing two different types of values which are double and float. Think about the limitations of size with inexact numbers.

Exact values (decimal)

A -> 1/2 with 5 decimals is 0.5000

B -> 1/2 with 10 decimals is 0.5000000000

A == B will always return true

Inexact values (decimal)

A -> 1/3 with 5 decimals is 0.33333

B -> 1/3 with 10 decimals is 0.3333333333

A == B -> will always return false because they aren't the same.

Similarly, 0.55 cannot be represented exactly in binary but 0.5 can be.

The binary representation of 0.55d -> 0.10001100110011001101...

So they will not be equal

The binary representation of 0.5d -> 0.1

So they will be equal

Hope It clears your doubt

GOVIND DIXIT
  • 1,748
  • 10
  • 27