After upgrading to gcc 4.5.0 from 3.3.4, some of my floating point code fails. Searched for and could not find a matching bug. It boils down to this very simple example: #include <stdio.h> #define MY_PI 3.14159265358979323846 int main() { double z = MY_PI; puts(z == MY_PI ? "==" : "!="); return 0; } If this is compiled "gcc -o bug -Wall bug.c" it works: there is equality. Doesn't matter if optimization is used or not (-g, -O, -O2 all give same results). But if compiled with -ansi or -std=c99, then the equality fails, again regardless of optimization!! The preprocessed code looks as expected: int main() { double z = 3.14159265358979323846; puts(z == 3.14159265358979323846 ? "==" : "!="); return 0; } Cannot see how this is correct behavior since the exact same expression was used to initialize the variable and to test for equality. Do not see anything in my ANSI/ISO C reference that sheds any light. I can work around this by using actual double constants instead of preprocessor expressions ("double my_pi_2 = MY_PI_2" and setting/testing with my_pi_2, etc), but this should work as is!
pr323? As a general rule: never compare floating points for equality, use abs(a-b)<epsilon.
As an even more general rule, remember to always specify your target: in this case, for example, I can't reproduce at all the behavior on x86_64 -m64, only with -m32.
*** This bug has been marked as a duplicate of 323 *** *** This bug has been marked as a duplicate of 323 ***
i?86 is a FLT_EVAL_METHOD 2 target, so for strict C compliance all floating operations and constants are supposed to be evaluated in the precision of long double. The assignment of the constant to a double var or explicit cast to double cause rounding to happen, so your testcase is evaluated as: int main() { double z = 3.14159265358979323846L; puts((long double) z == 3.14159265358979323846L ? "==" : "!="); return 0; } and of course (double) 3.14159265358979323846L != 3.14159265358979323846L. You can use -fexcess-precision=fast (the default unless -std=c99/-std=c89 is requested) for the old behavior, or you can add explicit cast, z == (double) M_PI, or (as usually a good idea) avoid floating point equality/non-equality comparisons, instead check whether difference is smaller than some epsilon.
Thanks Jakub.
Subject: Re: Floating point comparison failure Thanks everyone. I usually do fuzzy floating-point comparison, except in certain special circumstances. I will switch to using double constants; I'm trying for a code that is maximally portable, so having to worry about what exact compiler switches to use is anathema. And might I add: you people are super-fast! I'm very impressed.