I have a doubt concerning the output of the following C program. I tried to compile it using both Visual C++ 6.0 and MinGW32 (gcc 3.4.2).
#include <stdio.h>
int main() {
int x = 2147483647;
printf("%f\n", (float)2147483647);
printf("%f\n", (float)x);
return 0;
}
The output is:
2147483648.000000
2147483647.000000
My question is: why are both lines different? When you convert the integer value 2147483647 to the IEEE 754 floating-point format, it gets approximated to 2147483648.0. So, I expected that both lines would be equal to 2147483648.000000.
EDIT: The value "2147483647.000000" can't be a single-precision floating-point value, since the number 2147483647 can't be represented exactly in the IEEE 754 single-precision floating-point format without loss of precision.
In both cases, code seeks to convert from some integer type to
floatand then todouble.. Thedoubleconversion occurs as it is afloatvalue passed to a variadic function.Check your setting of
FLT_EVAL_METHOD, suspect it has a value of 1 or 2 (OP reports2with at least one compiler). This allows the compiler to evaluatefloat"... operations and constants to the range and precision" greater thanfloat.Your compiler optimized
(float)xgoing directlyinttodoublearithmetic. This is a performance improvement during run-time.(float)2147483647is a compile time cast and the compiler optimized forinttofloattodoubleaccuracy as performance is not an issue here.[Edit2] It is interesting that the C11 spec is more specific than the C99 spec with the addition of "Except for assignment and cast ...". This implies that C99 compilers were sometimes allowing the
inttodoubledirect conversion, without first going throughfloatand that C11 was amended to clearly not allow skipping a cast.With C11 formally excluding this behavior, modern compliers should not do this, but older ones, like OP's might - thus a bug by C11 standards. Unless some other C99 or C89 specification is found to say other-wise, this appears to be allowable compiler behavior.
[Edit] Taking comments together by @Keith Thompson, @tmyklebu, @Matt McNabb, the compiler, even with a non-zero
FLT_EVAL_METHOD, should be expected to produce2147483648.0.... Thus either a compiler optimization flag is explicitly over-riding correct behavior or the compiler has a corner bug.-1 indeterminable;
0 evaluate all operations and constants just to the range and precision of the type;
1 evaluate operations and constants of type
floatanddoubleto the range and precision of thedoubletype, evaluatelong doubleoperations and constants to the range and precision of thelong doubletype`;2 evaluate all operations and constants to the range and precision of the
long doubletype.-1 (Same as C99)
0 (Same as C99)
1 (Same as C99)
2 (Same as C99)