Reputation: 37
For the following code:
#include<stdio.h>
int main()
{
float a = 0.7;
printf("%.10f %.10f\n", 0.7f, a);
return 0;
}
The output I get is:
0.7000000000 0.6999999881
Please explain why a
is printed as 0.6999999881
while the literal constant is printed as 0.7000000000
?
Is the use of a floating point constant in this case compiler-dependent?
Upvotes: 1
Views: 712
Reputation: 12708
The reason you get different values is that, as you are passing to printf(3)
(which is a vararg function) as an unchecked parameter, the compiler does a cast to (double)
(and an optimization i'm guessing) converting the 0.7f
literal to a 0.7D
before passing it to printf
, so you are actually passing two different values to printf, the first is (double)0.7f
, and the second is the stored value of variable a
, converted to a (double)
.
Upvotes: 0
Reputation: 80335
Obtaining “0.7000000000” as the string printed for printf("%.10f",0.7f)
is normal behavior if the compiler defines FLT_EVAL_METHOD
as 1 or 2.
Indeed, in that mode, floating-point constants can be represented at a precision beyond that of their type (C11 5.2.4.2.2:9):
Except for assignment and cast (which remove all extra range and precision), the values yielded by operators with floating operands and values subject to the usual arithmetic conversions and of floating constants are evaluated to a format whose range and precision may be greater than required by the type.
In other words, printing 0.7000000000 0.6999999881 FLT_EVAL_METHOD=2
is one possible behavior for the modified program below.
#include<stdio.h>
#include <float.h>
int main()
{
float a=0.7;
printf("%.10f %.10f FLT_EVAL_METHOD=%d\n",0.7f, a, (int)FLT_EVAL_METHOD);
return 0;
}
Because the compiler defines FLT_EVAL_METHOD
to 2
, printf("%.10f %.10f", 0.7f, 0.7)
is treated as if it was printf("%.10f %.10f", (double)0.7L, (double)0.7L)
. Similarly, printf("%.60Lf %.60Lf\n", (long double)0.7f, (long double)0.7)
is equivalent to printf("%.60Lf %.60Lf\n", 0.7L, 0.7L)
.
Upvotes: 4