Is relational comparison between int and float directly possible in C?

后端 未结 11 2095
Happy的楠姐
Happy的楠姐 2020-12-03 18:48

I am using Visual Studio 6 with some old time code written in c. I found an issue where the code looks like this..

int x = 3;
float y = 3.0;

if(x == y){
            


        
相关标签:
11条回答
  • 2020-12-03 19:03

    Well, I guess you won't be too surpised to hear that comparing floats for equality is a rookie mistake then.

    The problem is that many increments smaller than an integer values can't actually be represented exactly in IEEE floating point. So if you arrive at the float by trying to "index" it up to the value of 3.0 (say in increments of 0.1), it is quite possible your equality comparison can never be true.

    It is also a bad idea just from a type-strength standpoint. You should either convert the float into an int, check for your int being "close enough" (eg < 3.1 and > 2.9 or somesuch), or better yet if you are trying to make that float do double-duty for something like a counter, avoid the whole idea.

    0 讨论(0)
  • 2020-12-03 19:06

    That's scary. (I wonder what else you'll find.)

    x will be promoted to float, but that's not going to help you. Because of how floats are represented, using == to compare them is unreliable.

    I might suggest something like this (checking for absolute error/difference) instead:

    #define EPSILON 0.0001 
    if (fabs((float)x - y) < EPSILON) { /* Do stuff. */ }
    

    which is a common approach and may be sufficient for your purposes, if your values of x and y are "nice". If you really want to go in depth into the topic of comparing floats, this article probably has more information than you want. It does say about the epsilon method:

    If the range of the expectedResult is known then checking for absolute error is simple and effective. Just make sure that your absolute error value is larger than the minimum representable difference for the range and type of float you’re dealing with.

    0 讨论(0)
  • 2020-12-03 19:07

    You may be interested in the Game Developers Conference lecture Numerical Robustness for Geometric Calculations (aka EPSILON is NOT 0.00001!). It details choosing good threshold / epsilon values for a variety of tasks.

    (+1 on the mention of "What Every Computer Scientist Should Know About Floating Point" in another answer, too.)

    0 讨论(0)
  • 2020-12-03 19:08

    No, there is no problem in your use case, because the integers are mapped exactly to floats (there is no decimal truncation problem, as for example with 0.3; but 3 is 1.1E10 in binary scientific notation).

    In the worst case scenario I can think of, there can be integer numbers that cannot be represented in float because there are "gaps" larger than 1 between two consecutive float numbers, but even in that case, when the integer is cast to float to do the comparison, it will be truncated to the nearest float, in the same way as the float literal did.

    So as long your floats come from non decimal literals, the comparison with the equivalent integer will be the same, because the integer will be cast to the very same float before the comparison can be done.

    0 讨论(0)
  • 2020-12-03 19:11

    Edit:

    The right way is to use the epsilon method:

    #include <math.h>
    int x = 3;
    int y = 3.0;
    if (fabs((float) x - y) < 0.0001) { // Adjust the epsilon
      // Do stuff
    }
    
    0 讨论(0)
  • 2020-12-03 19:14

    This is generally (i.e., always) a bad idea. As you suspected, the comparison from 3 to 3.0000001 will indeed fail.

    What most people do, if an int-float comparison is really necessary, is pick some threshold of tolerance and go with that, like so:

    int x = 3;
    float y = 3.0;
    
    // some code here
    
    float difference = (float) x - y;
    float tolerableDifference = 0.001;
    
    if ((-tolerableDifference <= difference) && (difference <= tolerableDifference)) {
        // more code
    }
    
    0 讨论(0)
提交回复
热议问题