Arithmetic problems

Peter Januschke peter.januschke@sap.com
Thu Dec 30 02:26:00 GMT 1999


Some people were recently discussing about a problem
with program fragments like

   int ires = ( double ) i * ( double ) 0.0000001

where i is of type int and holding the value 40000000.
On most platforms, ires would be assigned a value of 40,
but using gcc on Linux (Intel), we obtain 39. It was
asked if this behaviour is a bug or correct.
The problem occurs only if gcc was started with one of the
options '-g' or '-O0'.

Well, the reason for the different result is, that gcc
obviously instructs Intel's FPU to compute the result in
extended precision, i.e. using 80 bits instead of 64 bits
(like requested by IEEE 754). Of course, there is no
restriction in the ANSI C standard, that forbids the use
of higher precision. But the different settings for the
FPU in debug mode and in optimized mode causes a lot
of programs to produce different results for evaluations
of even simple floating-point expressions. For example,
you can try out the following program (compile with
'gcc -O0'):

----------------------------------

#include <stdio.h>

int main()
{
  double a =  389514726;
  double b =  205117922;
  double c =  251217123;
  double d = -318037442;

  double p,q,s,x,y;

  x = a/(a*b + c*d);

  p = a*b;
  q = c*d;
  s = p+q;
  y = a/s;

  printf("x= %30.20e\n", x);
  printf("y= %30.20e\n", y);

  return;
}

------------------------------

In principle, the same expression is evaluated to
obtain x and y. The difference is, that x is computed
in "one step", using extended precision, while y is
computed by using intermediate results, that are rounded
to double precision. Thus we force y to be computed
according to IEEE 754.
Now compile the results a second time and let the
compiler optimise, e.g. 'gcc -O1'.

When you see the results, you should hopefully agree,
that this is an odd and inconsistent feature of gcc
on Linux (Intel) which should be corrected.

>From my point of view, gcc should provide a possibility
to enable the user to make sure that his computations
are carried out according to existing standards (like
IEEE 754). There are simple solutions and it should take
only very little effort to implement them:

1.) gcc could ALWAYS turn off extended precision like
    it does already when option -On (n>0) is present.

2.) An option could be provided, allowing the user
    to force gcc to let intermediate results be rounded to
    double precision. In the manual pages of gcc, there is
    already a description of such an option: -ffloat-store
    Unfortunately, this option currently is ineffective
    on Intel platforms.

--
Dr. Peter Januschke       SAP AG, Dep. ABAP Language
mailto:peter.januschke@sap.com  (occupational)
mailto:peter_januschke@t-online.de (private)



More information about the Gcc-bugs mailing list