Article View: gnu.gcc.help
Article #51714Re: Floating point differences
From: Hugh Fader
Date: Fri, 16 Apr 1993 16:02
Date: Fri, 16 Apr 1993 16:02
114 lines
5346 bytes
5346 bytes
I wrote:
: We have an application here that does a lot of floating point
: calculations. We have noticed differences in results between gcc and
: other compilers. i.e. cc on Sun, Borland C on PC, and MS C on PC give
: identical results. Only gcc on Sun differs. Does gcc do something
I think I know the problem. It has to do with differences in the
treatment of floats in traditional and ANSI C.
The definition of traditional C, `The C Programming Language' by
Kernighan and Ritchie (1978) p. 41, states:
More precisely, for each arithmetic operator, the following
sequence of conversion rules is applied.
char and short are converted to int, and float is converted to
double.
. . .
ANSI C may treat floats differently. In `The C Programming Language
Second Edition' by Kernighan and Ritchie (1988) p. 198 states:
. . . arithmetic on float may be done in single precision, rather
than double; the first edition specified that all floating
arithmetic was double precision.
I think that *may* is the operative word in the above quotation. I
know that cc is doing double arithmetic. You will see that both the
Borland and Microsoft compilers are promoting to double while the GNU
compiler is not.
A reply to my posting (included at the end of this message) included a
program for calculating the computer's epsilon, the smallest value
significantly different from zero. The program calculates epsilon two
ways, once with an intermediate variable and once without. The
intermediate variable forces truncation to float precision. The
calculation without the intermediate variable depends on compiler
implementation to determine whether float or double is used.
Here is the epsilon output run on Sun with three different
compiler/switch combinations:
slee06% cc -o epsilon epsilon.c
slee06% epsilon
Epsilon machine (avec variable intermediaire) : 1.19209e-07
Epsilon machine (sans variable intermediaire) : 2.22045e-16
slee06% gcc -o epsilon epsilon.c
slee06% epsilon
Epsilon machine (avec variable intermediaire) : 1.19209e-07
Epsilon machine (sans variable intermediaire) : 1.19209e-07
slee06% gcc -traditional -o epsilon epsilon.c
slee06% epsilon
Epsilon machine (avec variable intermediaire) : 1.19209e-07
Epsilon machine (sans variable intermediaire) : 2.22045e-16
The epsilon values from gcc's float.h are:
#define FLT_EPSILON ((float)1.19209290e-07)
#define DBL_EPSILON 2.2204460492503131e-16
As expected, cc appears to be doing double precision arithmetic. The
intermediate variable is truncating to float. The first run of gcc has
identical results with or without the intermediate variable. This
indicates it is not promoting float to double for arithmetic
operations. The second run of gcc, with the -traditional compiler
flag, gives the same result as for cc. Even though the gcc manual page
gives no indication of this, -traditional must be causing gcc to treat
float arithmetic the same way as cc does.
The Microsoft compiler gave the following results for epsilon:
Epsilon machine (avec variable intermediaire) : 1.0842e-019
Epsilon machine (sans variable intermediaire) : 1.0842e-019
The epsilon values from float.h are:
#define DBL_EPSILON 2.2204460492503131e-016
#define FLT_EPSILON 1.192092896e-07F
#define LDBL_EPSILON 5.4210108624275221706e-020
The epsilon program's output value is smaller than that given for
DBL_EPSILON in float.h! It appears that through optimization (maybe
by keeping floats in fpa registers) the Microsoft compiler avoids the
truncation by the intermediate variable.
The Borland compiler gave
Epsilon machine (avec variable intermediaire) : 1.19209e-07
Epsilon machine (sans variable intermediaire) : 1.0842e-19
Its epsilon values from float.h are:
#define DBL_EPSILON 2.2204460492503131E-16
#define FLT_EPSILON 1.19209290E-07F
#define LDBL_EPSILON 1.084202172485504E-19
The Borland compiler behaves similarly to cc execept that it gives
a value for the double epsilon is the LDBL value.
Summing things up, it looks like everybody but gcc is promoting floats
to double.
We tried compiling our application with gcc -traditional and the
results matched those of cc.
Does anyone have suggestions as to what the best approach is when you
want consistent floating point results from several compilers? One
way to do this would be to only use doubles. This is OK except when
you have large data sets.
----------- begin included file ------------------
Technical Details
Message-ID:
<1qmla6INNb25@fmsrl7.srl.ford.com>Path:
arc1-ca.pugleaf.net!gmd.de!newsserver.jvnc.net!louie!udel!gatech!emory!nigel.msen.com!fmsrl7!hughReferences:
<1qhbioINN55a@fmsrl7.srl.ford.com>Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 11318c,e3259ca760e1e814 X-Google-Attributes: gid11318c,public X-Google-ArrivalTime: 1993-04-16 09:24:31 PST Path: arc1-ca.pugleaf.net!gmd.de!newsserver.jvnc.net!louie!udel!gatech!emory!nigel.msen.com!fmsrl7!hugh From: hugh@slee01.srl.ford.com (Hugh Fader) Newsgroups: gnu.gcc.help Subject: Re: Floating point differences Date: 16 Apr 1993 16:02:08 GMT Organization: Ford Motor Company Research Laboratory Lines: 205 Message-ID: <1qmla6INNb25@fmsrl7.srl.ford.com> References: <1qhbioINN55a@fmsrl7.srl.ford.com> Reply-To: hugh@slee01.srl.ford.com NNTP-Posting-Host: slee06.srl.ford.com X-Newsreader: Tin 1.1 PL5