In what state can I compare two float variables directly using == in C ++?

I know that comparing two floating point variables is very difficult. Usually, when the difference between two floats is below the threshold, we consider the two variables equal. However, some cases by directly using == are possible, for example

int main()
{   

     float angle = 3.123f;
     if(angle == 3.123f)
     {
         std::cout<<"the same"<<std::endl;
     }
     else
     {
         std::cout<<"different"<<std::endl;
     }

     angle = 13;
     if(angle == 13 )
     {
         std::cout<<"the same"<<std::endl;
     }
     else
     {
         std::cout<<"different"<<std::endl;
     }

    return 0;
}

      

I am compiling codes in VC 2010 and it seems to be ==

valid in both cases. So my question is, what state can we safely use ==

to compare two variables?

The reason I was asking this question is because there is a function in my project that looks like this

void fun(int a, int b, float value=180); 

void fun(int a, int b, float value)
{
   if(value == 180)
   {
       // do something
   }
   else
   {
        // do something
   }
}

      

Basically, the function has fun

a default float variable as a function parameter. In the implementation of the function, we will check if we are using the default setting and if so, a special treatment will be performed.

+3


source to share


4 answers


All integers up to 2 ^ 24 are represented exactly as float

s, so there won't be any problem here.

The main reason not to use floating point equality - due to imprecise floating point operations - (180 / 7) * 7

may or may not be exactly 180. However, if it is simply passed as the default argument, you are completely safe.



If you're particularly concerned, instead of the default argument, just supply a two-argument overload that handles the default case.

+9


source


Use ==

if you like what he wanted to do: exact equality comparison. It is usually impractical to test exact equality against an imprecise calculation that might have a rounding error, but if you want to treat a certain (exact) value as a special case, with the expectation that callers will pass that (exact) value in to trigger a special case, that's OK ...



It also makes sense to check the exact values, which make the calculation much easier: for example, if you implement a cosine function, you can check if the argument is (exactly) 0 and return (exactly) 1, skipping the more complex math for calculating cosine in general. Note that in this case, you are returning the same value as the more complex computation, so callers will not see weird behavior depending on whether they pass exactly 0 or something very close to 0: they just get exactly 1 or something very close to 1.

+2


source


Obviously, equality means that the exact value you are comparing has been assigned to the variable before. What makes things tricky is not comparison, but the math behind the floats. If you assign 180t to the float and compare it to 180 it will always show true. The same is true for assigning 4.15 and comparing with 4.15, etc. Rounding errors only come into play if you are performing calculations and if the values โ€‹โ€‹involved are not exactly represented by the binary format used for floats.

However, in your case, this is not interesting, since you want to distinguish between default and non-default. You have to use two functions for this case and overload them:

void fun(int a, int b)
{
  // do the default-something
}

void fun(int a, int b, float value)
{
  // do the else-something
}

      

The behavior, however, will be different in the case that your entry without default is not possible by 180f

accident.

+2


source


For small enough integers, you should be safe.

But once the value you are comparing was a processing or conversion, all bids are disabled.

This is not a good idea.

Consider use NaN

, infinity, or something more "difficult".

0


source







All Articles