I'm using the online compiler https://www.onlinegdb.com/ and in the following code when I multiply 2.1 with 100 the output becomes 209 instead of 210.
#include<stdio.h>
#include <stdint.h>
int main()
{
float x = 1.8;
x = x + 0.3;
int coefficient = 100;
printf("x: %2f\n", x);
uint16_t y = (uint16_t)(x * coefficient);
printf("y: %d\n", y);
return 0;
}
Where am I doing wrong? And what should I do to obtain 210?
I tried to all different type casts still doesn't work.
The following assumes the compiler uses IEEE-754 binary32 and binary64 for float
and double
, which is overwhelmingly common.
float x = 1.8;
Since 1.8
is a double
constant, the compiler converts 1.8 to the nearest double
value, 1.8000000000000000444089209850062616169452667236328125. Then, to assign it to the float
x
, it converts that to the nearest float
value, 1.7999999523162841796875.
x = x + 0.3;
The compiler converts 0.3 to the nearest double
value, 0.299999999999999988897769753748434595763683319091796875. Then it adds x
and that value using double
arithmetic, which produces 2.09999995231628400205181605997495353221893310546875.
Then, to assign that to x
, it converts it to the nearest float
value, 2.099999904632568359375.
uint16_t y = (uint16_t)(x * coefficient);
Since x
is float
and coefficient
is int
, the compiler converts the coefficient
to float
and performs the multiplication using float
arithmetic. This produces 209.9999847412109375.
Then the conversion to uint16_t
truncates the number, producing 209.
One way to get 210 instead is to use uint16_t y = lroundf(x * coefficient);
. (lroundf
is declared in <math.h>
.) However, to determine what the right way is, you should explain what these numbers are and why you are doing this arithmetic with them.