2

I am new to C language. Here is my question and code:

I have a constant and a variable with the same value and I try to compare them to check if they are equal. It seems to me that since they are assigned the same value, they should be equal but that is not the case.

#include <stdio.h>
#define mypi1 3.14

int main()
{
    int ans;
    float mypi2 = 3.14;
    if(mypi1==mypi2)
    {
        ans=1;
    }
    else
    {
        ans=0;
    }
    printf("%i",ans);

    return 0;
}

My output is 0. Which indicates they are not equal. What is the reasoning behind this? This is a really simple question but I could not find it anywhere. Please help and thanks in advance.

lollalolla
  • 454
  • 5
  • 10

1 Answers1

1
#define mypi1 3.14
float mypi2 = 3.14;

The first of those is a double type, the second is a double coerced into a float.

The expression mypi1==mypi2 will first convert the float back to a double before comparing (the idea is that, if one type is of lesser range/precision than the other, it's converted so that both types are identical).

Hence, if the if statement is failing, it's likely that you lose information in the double -> float -> double round-trip(a).

To be honest, unless you're using a great many floating point values (and storage space is a concern), you should probably just use double everywhere. If you do need float types, use that for both values:

#define mypi1 3.14f
float mypi2 = 3.14f;

Comparing two float variables will not involve any conversions.


(a) See, for example, the following complete program:

#include <stdio.h>
#define x 3.14
int main(void) {
    float y = 3.14;  // double -> float
    double z = y;    //        -> double
    printf("%.50f\n", x);
    printf("%.50f\n", z);
}

In this, x is a double and z is a double that's gone through the round-trip conversion discussed above. The output shows the difference that can happen:

3.14000000000000012434497875801753252744674682617188
3.14000010490417480468750000000000000000000000000000
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • This is very clear, thanks. However, I tried changing the value to 10.5 and the output return is 1 which indicates they are identical. Could you please explain this? – lollalolla Nov 22 '18 at 01:06
  • @lollalolla: See [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). Succinctly, there's an exact binary representation of 10.5 that both `float` and `double` can store; there isn't an exact binary representation of 3.14 (period), and `float` and `double` can only store different approximations to it (because they have different numbers of bits to store the value), and when the `float` is converted to `double`, what it stored isn't the same as what the `double` stored from the start. – Jonathan Leffler Nov 22 '18 at 02:44
  • @lollalolla, Jonathan is correct. Basically, numbers that can be built from constituents that are powers of two within the bit precision of the type (such as `2^3 + 2^1 + 2^-1 = 8 + 2 + 0.5 = 10.5`) can be represented exactly. For `3.14`, you can get `3` from `2 + 1` but the `0.14` bit is problematic. – paxdiablo Nov 22 '18 at 06:24
  • Thanks all. Now it makes perfect sense to me! – lollalolla Nov 22 '18 at 12:45