It is well-known that 'double' computation results on x86 processors can
carry excess precision. Namely, if the value is stored in a floating-point
register (80 bits total, 64 bits mantissa) without passing through a
memory store, it can carry excess precision. The two ways to prevent
such excess precision (with GCC) are:
- option -ffloat-store,
- cast to 'volatile double'.
It is not so well-known that this phenomenon can also happen with 'float'
computations.
Here's a program:
======================================================================
#include <stdio.h>
#include <math.h>
int main ()
{
printf ("%.12g\n", (double) 0.9272951f);
printf ("%.12g\n", (double) 0.92729513f);
printf ("%.12g\n", (double) 0.92729514f);
printf ("%.12g\n", (double) 0.92729515f);
printf ("%.12g\n", (double) 0.92729516f);
printf ("%.12g\n", (double) 0.92729517f);
printf ("%.12g\n", (double) 0.92729518f);
printf ("%.12g\n", (double) 0.92729519f);
printf ("%.12g\n", (double) 0.9272952f);
printf ("%.12g\n", (double) 0.9272953f);
printf ("\n");
printf ("%.12g\n", (double) atan2f (0.8f, 0.6f));
printf ("%.12g\n", (double) (float) atan2f (0.8f, 0.6f));
printf ("%.12g\n", (double) (volatile float) atan2f (0.8f, 0.6f));
return 0;
}
======================================================================
Output on mingw:
0.927295088768
0.927295148373
0.927295148373
0.927295148373
0.927295148373
0.927295148373
0.927295207977
0.927295207977
0.927295207977
0.927295327187
0.927295206081
0.927295206081
0.927295206081
You can see that there are no 'float' values between
0.927295148373 and 0.927295207977, yet the atan2f() function
- which is declared to return 'float' - has returned a value
between them.
Does anyone know whether this can also happen with glibc functions?
Or are glibc functions that return 'float' really returning 'float'
values?
Bruno
--
In memoriam Engin Ceber <http://en.wikipedia.org/wiki/Engin_Ceber>