Bug?

Andrew P. Mullhaupt amull at Morgan.COM
Sun Oct 1 02:16:28 AEST 1989


When comparing floating point numbers for equality, you are in grave
peril of several incredibly painful bugs, to wit:

1. Forget portability across machines. 

2. The 'storage history' fun: If your computer has a coprocessor or
FPA, you may find that IEEE arithmetic (80 bits wide) is done there,
but your number comes back to the CPU as a double. This means that

    z = functionreturningdouble();
    if ( y == z ) printf("Spew");

and

    if ( y == functionreturningdouble() ) printf("Spew");

need not have the same output. The classic example of this torture is
a bug where an expression needs to be debugged is computed in the
coprocessor (80 bit) registers, If the compiler has arrived at this
situation through optimization, and the program is not correct with
the extra bits of precision, then turning off optimization, (which
almost always happens if you compile for debugging), will make the bug
go away! If you observe this behavior, and decide to resort to the
insertion of diagnostic print statements, (because you realize that
you can't debug the program with the debugger), then the number which
gets printed out (i.e. has been coerced to double as it crossed the CPU
to be output), will appear to be correct, and the print statement may
actually fix the bug!

It is possible that in versions of C which have peculiar single and
double automatic conversions that this kind of bug occurs as well.

3. If I have a teeny tiny double called epsilon can I make this all
go away? Mostly yes, but strictly speaking, NO!!!!! If either you,
or your compiler (in a misguided imitation of APL's comparison tol-
erance) insert efficiency sapping +epsilon and -epsilon all over your
code, it displaces the problem to the comparisons

     y - epsilon < z

and
 
     y + epsilon > z

either of which can suffer from the storage history disease if the
difference involved is between two relevant precisions. In fact, you
may be inviting trouble by giving the compiler more to rearrange in
optimization.


The moral of the story is: Unless you are dead certain that nothing
else will do, comparing floating point numbers for equality is a
bad business, and your compiler ought not pretend to solve this problem
with some invisible epsilon, since it is not really solvable short of
interval arithmetic, and that's another story.

Later,
Andrew Mullhaupt



More information about the Comp.lang.c mailing list