main()
{
int z;
float b=3.1;
z=b*5+1.5;
printf("%d",z);
}
I get value of z as 16.
When I use double I get 17. Why so?
main()
{
int z;
float b=3.1;
z=b*5+1.5;
printf("%d",z);
}
I get value of z as 16.
When I use double I get 17. Why so?
There are many numbers like 3.1 that float/double
cannot encode exactly given that floating point typical uses a binary floating point encoding. **1 In OP's case, rather than saving exactly 3.1 in b
, a nearby value is saved. As a float
and double
, different approximations were used leading to the 16 vs. 17.
The result of the FP math and the int
truncation accentuates this difference.
#include <float.h>
#include <stdio.h>
int main(void) {
printf("%d\n",FLT_EVAL_METHOD);
float b=3.1;
printf("%.20f %.20f %d\n",b, b*5+1.5, (int) (b*5+1.5));
volatile float v=3.1;
printf("%.20f %.20f %d\n",v, v*5+1.5, (int) (v*5+1.5));
double d=3.1;
printf("%.20f %.20f %d\n",d, d*5+1.5, (int) (d*5+1.5));
}
Output
2
3.09999990463256835938 16.99999952316284179688 16
3.09999990463256835938 16.99999952316284179688 16
3.10000000000000008882 17.00000000000000000000 17
Sometimes the effects of FLT_EVAL_METHOD
, which allow for some float
math to be done as double
math complicates the story. So the above uses a volatile float
to help should others try variations on this code.
Tip: With ample warnings, code may get a warning like the following. This hints that 3.1
and 3.1f
are not the same.
// warning: conversion to 'float' alters 'double' constant value [-Wfloat-conversion]
float b=3.1;
// no warning
float b=3.1f;
As an alternative to assigning a FP value to an int
directly, consider the various rounding functions like round(), roundf(), nearby(), rint(), lrint()
, etc.
#include <math.h>
// example: float to long
long int lrintf(float x);
long long_var = lrintf(float_var);
**1 There are infinite number of numbers. Yet only about 232 different float
.
3.1 cannot be represented precisely as a binary floating point number, just like 3⅓ cannot be represented precisely in decimal. So what will be stored in b
is the closest possible value as a float
(or double
) if you change the type of b
. That might be slightly less or slightly more, depending on where the fraction needs to be truncated.
If it turns out to be slightly more, 5*b+1.5
will be slightly more. than 17; otherwise it will be slightly less. But converting to an int
throws away the fraction, so this tiny difference suddenly becomrs important.
You should avoid the instability by rounding rather than truncating.