The following program, generates different answers depending on what level of optimization is used: #include <stdio.h> int main (int argc, char **argv) { double t1, t2, t3, t4; t1 = 0.040000000000000008; t2 = 0.20000000000000001; t3 = 0.20000000000000001; /* The comparison fails here */ if (t1 <= t3 * t2) { printf ("OK \n"); } else { printf ("Wrong!!! \n"); } t4 = t3 * t2; /* Comparison OK here */ if (t1 <= t4) { printf ("OK \n"); } else { printf ("Wrong!!! \n"); } printf ("t1=%E t2=%E t3=%E t3*t2=%E t4=%E \n", t1, t2, t3, t2 * t3, t4); } ------------------ Output: [richieb on chippewa] numbers > gcc -o doubles doubles.c [richieb on chippewa] numbers > ./doubles Wrong!!! OK t1=4.000000E-02 t2=2.000000E-01 t3=2.000000E-01 t3*t2=4.000000E-02 t4=4.000000E-02 [richieb on chippewa] numbers > gcc -O -o doubles doubles.c [richieb on chippewa] numbers > ./doubles OK Wrong!!! t1=4.000000E-02 t2=2.000000E-01 t3=2.000000E-01 t3*t2=4.000000E-02 t4=4.000000E-02 [richieb on chippewa] numbers > gcc -O2 -o doubles doubles.c [richieb on chippewa] numbers > ./doubles OK OK t1=4.000000E-02 t2=2.000000E-01 t3=2.000000E-01 t3*t2=4.000000E-02 t4=4.000000E-02 [richieb on chippewa] numbers > gcc -O3 -o doubles doubles.c [richieb on chippewa] numbers > ./doubles OK OK t1=4.000000E-02 t2=2.000000E-01 t3=2.000000E-01 t3*t2=4.000000E-02 t4=4.000000E-02 [richieb on chippewa] numbers > Versions of things: gcc --version egcs-2.91.66 [richieb on chippewa] numbers > uname -a Linux chippewa 2.2.9 #20 SMP Thu May 20 00:01:37 PDT 1999 i686 unknown [richieb on chippewa] numbers > ------- Additional Comments From 10/25/99 10:16 ------- I have tried the same program on a fresh install of RH 6.1 with the same result.
First of all, you need to use -ffloat-store in cases like this. If I do so, I always get "Wrong" for the first printf and "OK" for the second (regardless of optimization options, and with either the GCC we ship or the development GCC from egcs.cygnus.com). As for the case where it still prints "Wrong" - that seems to be the result of doing the arithmetic as extendeds rather than doubles. GCC requires you to use intermediate variables such as "t4" in this example - from the GCC manual (gcc.info): Use @samp{-ffloat-store} for such programs, after modifying them to store all pertinent intermediate computations into variables.
The problem I have is that on Solaris "gcc" compiles this program correctly and it always works right. My second problem is that the code that has the problem is produced by a compiler that emits C. Anyway, thanks for the suggestions.
If you read gcc.info (just before the sentence I quoted, under -ffloat-store), you'll see that the -ffloat-store issues only apply to architectures such as 68k and x86 in which floating point registers are extendeds. On the sparc, floating point registers are doubles. Feel free to take this up with the gcc maintainers at http://egcs.cygnus.com/ but GCC is behaving as documented - it just happens to differ between x86 and sparc.
Thanks!