Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dodging the inaccuracy of a floating point number

I totally understand the problems associated with floating points, but I have seen a very interesting behavior that I can't explain.

float x = 1028.25478;
long int y = 102825478;
float z = y/(float)100000.0;
printf("x = %f ", x);
printf("z = %f",z);

The output is:

x = 1028.254761 z = 1028.254780

Now if floating numbers failed to represent that specific random value (1028.25478) when I assigned that to variable x. Why isn't it the same in case of variable z?

P.S. I'm using pellesC IDE to test the code (C11 compiler).

like image 611
Ahmed Soliman Avatar asked Jan 03 '23 00:01

Ahmed Soliman


1 Answers

I am pretty sure that what happens here is that the latter floating point variable is elided and instead kept in a double-precision register; and then passed as is as an argument to printf. Then the compiler will believe that it is safe to pass this number at double precision after default argument promotions.

I managed to produce a similar result using GCC 7.2.0, with these switches:

-Wall -Werror -ffast-math -m32 -funsafe-math-optimizations -fexcess-precision=fast -O3

The output is

x = 1028.254761 z = 1028.254800

The number is slightly different there^.

The description for -fexcess-precision=fast says:

-fexcess-precision=style

This option allows further control over excess precision on machines where floating-point operations occur in a format with more precision or range than the IEEE standard and interchange floating-point types. By default, -fexcess-precision=fast is in effect; this means that operations may be carried out in a wider precision than the types specified in the source if that would result in faster code, and it is unpredictable when rounding to the types specified in the source code takes place. When compiling C, if -fexcess-precision=standard is specified then excess precision follows the rules specified in ISO C99; in particular, both casts and assignments cause values to be rounded to their semantic types (whereas -ffloat-store only affects assignments). This option [-fexcess-precision=standard] is enabled by default for C if a strict conformance option such as -std=c99 is used. -ffast-math enables -fexcess-precision=fast by default regardless of whether a strict conformance option is used.

This behaviour isn't C11-compliant

like image 190