Witness the following short program: --------------------- #include <stdio.h> #include <stdlib.h> int main( int argc, char ** argv ) { double x = atof( argv[1] ); double d = x*x; printf( "%d\n", (x*x<d) ); return 0; } ----------------------- Ideally, this program should always print 0, since a number shouldn't be strictly less than itself. When compiled without optimization, the program will print 0 or 1 depending on the input (I get 0.3 --> 0, 0.4 --> 1, for instance). Now I understand that floating point numbers are far from ideal, and that this behaviour might not be a bug. Still, I would love to be able to characterize for which numbers the program will print 0 or 1. Any thoughts? Moreover, the program always prints a 0 when compiled with optimization. This inconsistency relative to the unoptimized version might indeed constitute a bug. Anyway, it's not totally clear to me that this is a bug. But either way, I'd love for someone in GCC land to explain to me what's going on. Thanks. p.s. The bug remains if you switch from doubles to floats. And I have a slightly larger program that exhibits the inconsistent behaviour when optimization is turned _on_. Release: 3.2.1, 2.95.4 Environment: Debian Woody, Pentium IV
From: Tim Prince <timothyprince@sbcglobal.net> To: csk@mud.cgl.uwaterloo.ca, gcc-gnats@gcc.gnu.org Cc: Subject: Re: other/10417: Inconsistent results in floating point comparison. Date: Tue, 15 Apr 2003 20:36:32 -0700 On Tuesday 15 April 2003 12:01, csk@mud.cgl.uwaterloo.ca wrote: > >Number: 10417 > >Category: other > >Synopsis: Inconsistent results in floating point comparison. > >Environment: > > Debian Woody, Pentium IV > > >Description: > > Witness the following short program: > > --------------------- > #include <stdio.h> > #include <stdlib.h> > > int main( int argc, char ** argv ) > { > double x = atof( argv[1] ); > double d = x*x; > > printf( "%d\n", (x*x<d) ); > return 0; > } > ----------------------- > > Ideally, this program should always print 0, since a number shouldn't be > strictly less than itself. When compiled without optimization, the program > will print 0 or 1 depending on the input (I get 0.3 --> 0, 0.4 --> 1, for > instance). > > Now I understand that floating point numbers are far from ideal, and that > this behaviour might not be a bug. Still, I would love to be able to > characterize for which numbers the program will print 0 or 1. Any > thoughts? If you ask the compiler to generate x87 code (the probable default for your configuration), it could interpret the expression as (long double)x*x < d; so the expression would be 1 every time d has been rounded up. If you use the command gcc -march=pentium4 -mfpmath=sse *.c as you might normally do for a P4, I doubt you could get the results you mention. > > Moreover, the program always prints a 0 when compiled with optimization. > This inconsistency relative to the unoptimized version might indeed > constitute a bug. I can't reproduce this, unless I tell the compiler to generate x87 code. As I don't "always" do that, I am not reproducing your claim. > > -- Tim Prince
State-Changed-From-To: open->closed State-Changed-Why: Not a bug. On x86, when optimizing, floating point values may be kept in FP registers when doing comparisons with others stored in memory. Now x86 FP registers have extra-precision over a 'double', which may invalid a comparison. Compile your code with '-ffloat-store' if it relies on exact IEEE floating-point semantics.
From: "Craig S. Kaplan" <csk@cgl.uwaterloo.ca> To: tprince@computer.org Cc: gcc-gnats@gcc.gnu.org Subject: Re: other/10417: Inconsistent results in floating point comparison. Date: Wed, 16 Apr 2003 10:40:02 -0400 (EDT) Tim, Thanks for the insights. If you've got the time, I have some additional comments below. > > --------------------- > > #include <stdio.h> > > #include <stdlib.h> > > > > int main( int argc, char ** argv ) > > { > > double x = atof( argv[1] ); > > double d = x*x; > > > > printf( "%d\n", (x*x<d) ); > > return 0; > > } > > ----------------------- > > > > Ideally, this program should always print 0, since a number shouldn't be > > strictly less than itself. When compiled without optimization, the program > > will print 0 or 1 depending on the input (I get 0.3 --> 0, 0.4 --> 1, for > > instance). > > > > Now I understand that floating point numbers are far from ideal, and that > > this behaviour might not be a bug. Still, I would love to be able to > > characterize for which numbers the program will print 0 or 1. Any > > thoughts? > If you ask the compiler to generate x87 code (the probable default for your > configuration), it could interpret the expression as > (long double)x*x < d; > so the expression would be 1 every time d has been rounded up. > If you use the command > gcc -march=pentium4 -mfpmath=sse *.c > as you might normally do for a P4, I doubt you could get the results you > mention. Surprisingly, I _do_ still get the strange behaviour with those switches. But I am beginning to understand where the behaviour may be coming from, based on your comments and the comments of another maintainer who emailed me (ebotcazou). When d is stored in a variable, some extra bits of precision that existed in the FPU are discarded. Now, you seem to suggest that the way the FPU does this is to _round_ d (rather than just truncating). My simple program seems to generate random output for different floats, but actually I'm just seeing the FPU's rounding semantics -- its decision whether to round up or down. Does that sound believable to you? Of course, if this is the case, we shouldn't expect -mfpmath=sse to solve the 'problem' -- we're still rounding x*x to store the answer in d. The other maintainer suggested that I needed '-ffloat-store' to guarantee strict IEEE semantics. I tried that switch, and it seemed to make the behaviour a little more consistent. It does remove the randomness from the large program I'm working on, but amazingly it doesn't fix my toy example. Using gcc 3.2.1, the only way I can make the short program above output 0 consistently is to compile it -O2. The -ffloat-store, -march=pentium4, and -mfpmath=sse switches don't seem to do anything. Any thoughts on why I'm not seeing a difference here? Thanks again. -- Craig S. Kaplan ``Evolution drives a steamroller, School of Computer Science disguised as a stationary bike.'' University of Waterloo http://www.cgl.uwaterloo.ca/~csk/
Reopening bug to mark bug as a dup of bug 323 so ...
that the number of dup goes up. *** This bug has been marked as a duplicate of 323 ***