6

I'd like to enable -Wfloat-equal in my build options (which is a GCC flag that issues a warning when two floating pointer numbers are compared via the == or != operators). However, in several header files of libraries I use, and a good portion of my own code, I often want to branch for non-zero values of a float or double, using if (x) or if (x != 0) or variations of that.

Since in these cases I am absolutely sure the value is exactly zero - the values checked are the result of an explicit zero-initialization, calloc, etc. - I cannot see a downside to using this comparison, rather than the considerably more expensive and less readable call to my near(x, 0) function.

Is there some way to get the effect of -Wfloat-equal for all other kinds of floating point equality comparisons, but allow these to pass unflagged? There are enough instances of them in library header files that they can significantly pollute my warning output.

Puppy
  • 144,682
  • 38
  • 256
  • 465

2 Answers2

2

It's pretty horrible, but this avoids the warning:

#include <functional>

template <class T>
inline bool is_zero(T v)
{
    return std::equal_to<T>()(v, 0);
}

GCC doesn't report warnings for system headers, and that causes the equality test to happen inside a system header.

Daniel James
  • 3,899
  • 22
  • 30
2

From the question you ask, it seems like the warning is entirely appropriate. If you're comparing against exact zero to test if data still has its initial zero value from calloc (which is actually incorrect from a standpoint of pure C, but works on any IEEE 754 conformant implementation), you could get false positives from non-zero values having been rounded to zero. In other words it sounds like your code is incorrect.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • I said exactly that in the question. There are a lot of things in C/C++ guaranteed to give a zero value in any implementation, and even more in any IEEE 754 implementation, which is practically everywhere. –  Feb 25 '11 at 23:52
  • @Joe: @R has a point: if you're testing against zero to see whether the value has ever been written since initialization, and any of your calculations could evaluate to zero, you'll incorrectly think a variable is newly initialized when it isn't. If you are looking for *newly initialized* union *calculation resulted in zero*, you need to use an inexact test because the calculation could be imprecise. – Ben Voigt Feb 26 '11 at 00:41
  • 1
    @Joe: Remind me why I should bother trying to help after the -1... but anyway, regarding `calloc`, C does not guarantee that floating point zero is all-zero-bits. Of course as I acknowledged it's a non-issue in the real world, especially if you're happy assuming IEEE 754. Aside from that, I don't see how you're confused by my answer. – R.. GitHub STOP HELPING ICE Feb 26 '11 at 00:50
  • 1
    Thanks guys, I know C. I'm interested in answers to the question, not another summary of how obscure x87 rounding rules are going to bite me (they're not going to). –  Feb 26 '11 at 00:55