0

In c++ is there a compiler flag or an option somewhere that makes it so that if 2 floats are within the error of the floating point arithmetic that they evaluate as equal?

It's annoying having to track down floating point errors. For example a long time ago when testing something where I knew what the value was I even overwrote the value right before the line and it still failed. This is a very simplified version of what it looked like

double x = 3;
if(x == 3)
   printf("x is 3");
else
   printf("x is not 3");

And that went into the else case and printed "x is not 3"

There has to be a way to handle this that doesn't mean I have to add handling to each floating point comparison.

ks1322
  • 33,961
  • 14
  • 109
  • 164
Chris
  • 155
  • 6
  • 3
    Sorry no, there's no such flag. – Mark Ransom Dec 07 '22 at 20:38
  • 1
    So, you're looking for a flag that tells the compiler that two floats should compare equal even if they aren't equal? The difference between a result that's calculated with floating-point math and a result that's calculated with real numbers isn't something that can be determined accurately; if it was, there would be no notion of "floating point error". Keep in mind that floating-point math doesn't obey the rules that you've learned all your life about how numbers work. That doesn't make it wrong, any more than in `int x = 1/3; if (x * 3 != 1) /* something is wrong */`. – Pete Becker Dec 07 '22 at 20:49
  • 2
    Please be so kind as to post the name of the compiler and hardware you're using. While there are numbers for which we expect an imprecise conversion to floating point so such a comparison would fail, `3` is not such a number--if you're honestly getting the result you claim from the code you posted, either your compiler or hardware is badly broken. Typically expect to see this resolved statically (at compile time) so there's not even a comparison, just code to print "x is 3". https://godbolt.org/z/hvY8dPhMe – Jerry Coffin Dec 07 '22 at 20:53
  • 3
    There is no single "the error of floating point arithmetic". Error accumulates as you do different calculations, so the available precision will depend on exactly what operations you do and exactly what values you do them on. – Miles Budnek Dec 07 '22 at 21:01
  • 1
    You should read [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) and [What Every Computer Scientist Should Know About Floating-Point Arithmetic](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – Jesper Juhl Dec 08 '22 at 01:20
  • You can implement your own custom types which inherit most operations from `double` or `float` but overload the comparison operators differently. – chtz Dec 08 '22 at 08:03
  • @JerryCoffin Something like this could happen if you replace `3` by an (inexact) result of a float operation and the code was compiled with x87-math: https://stackoverflow.com/questions/59710531/if-i-copy-a-float-to-another-variable-will-they-be-equal (and yes, technically compilers with that behavior are broken). – chtz Dec 08 '22 at 08:07
  • 1
    Deciding whether two approximately (perhaps differently-rounded) numbers are "close enough to be equal" is one of the harder problems in floating-point work. The appropriate threshold to use (whether 1 ULP for some other) is often dependent on other details of the quantity being evaluated. So I wouldn't want the compiler trying to pick a one-size-fits-all approximately-equal threshold. – Steve Summit Dec 08 '22 at 14:55
  • @SteveSummit I know its complex which is why I figured someone has at somepoint worked out a way to get things working good enough for most applications. Otherwise it means you have to do this complex task every single time. Adding an optional compiler flag that replaces absolute comparisons with a close enough doesnt just have to mean its a simple close enough function. It could be complex and take into account how the error changes for different values. The reason I figured theres an option is so that it can be good enough for most cases not perfect for all. – Chris Dec 09 '22 at 17:14

1 Answers1

-1

If you use GCC and glibc you can include something like

#define _GNU_SOURCE 1
#include <fenv.h>
static void __attribute__((constructor)) trapfpe ()
{
    /* Enable some exceptions.  At startup all exceptions are masked.  */
    feenableexcept (FE_INEXACT);
}

in your project which will abort the program (with a core dump, if you have such enabled in your environment) when it hits one of the above FP exceptions.

That being said, I don't think FE_INEXACT is particularly useful in reality. A somewhat useful combination might be FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW (but that's beside the question being asked).

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
janneb
  • 36,249
  • 2
  • 81
  • 97