Is relational comparison between int and float dir

2019-01-12 06:32发布

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){
   do some crazy stuff
}

is this a valid comparison? is it possible at run time the allocation for the float is 3.0000001 and this would fail?

11条回答
淡お忘
2楼-- · 2019-01-12 06:45

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.

查看更多
贪生不怕死
3楼-- · 2019-01-12 06:47

The crux of the problem is that floating point numbers which have a finite representation in base 10, decimal don't always have a finite representation in base 2, binary.

查看更多
不美不萌又怎样
4楼-- · 2019-01-12 06:47

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
}
查看更多
做个烂人
5楼-- · 2019-01-12 06:51

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.

查看更多
老娘就宠你
6楼-- · 2019-01-12 06:55

I am going to buck the trend here a bit. As to the first question about whether the comparison is valid, the answer is yes. It is perfectly valid. If you want to know if a floating point value is exactly equal to 3, then the comparison to an integer is fine. The integer is implicitly converted to a floating point value for the comparison. In fact, the following code (at least with the compiler I used) produced identical assembly instructions.

if ( 3 == f )
    printf( "equal\n" );

and

if ( 3.0 == f )
    printf( "equal\n" );

So it depends on the logic and what the intended goal is. There is nothing inherently wrong with the syntax.

查看更多
贪生不怕死
7楼-- · 2019-01-12 07:02

No one else has cited it yet, and I haven't linked to it in a while, so here is the classic paper on the scary edges of floating point representation and arithmetic: What Every Computer Scientist Should Know About Floating Point.

The paper is a challenging read for a non-mathematician, but the key points are well stated in between the heavy swaths of math backing them up.

For this discussion, the points made by the other answers here are all valid. Floating point arithmetic is inexact, and hence comparisons for exact equality are generally a bad idea. Hence, epsilon is your friend.

One exception to the exact comparison rule is a test for exactly zero. It is perfectly legal and often sensible to test for exactly zero before a division or logarithm since the answer is well defined for any non-zero value. Of course, in the presence of IEEE rules and NaN, you can let that slide and test for NaN or Inf later on.

查看更多
登录 后发表回答