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: /\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.
CodePudding user response:
Floating point numbers are not exact, when you add 1.8 0.3, the FPU might generate a slightly different result from the expected 2.1 (by margin smaller then float Epsilon) read more about floating-point numbers representation in wiki https://en.wikipedia.org/wiki/Machine_epsilon
what happens to you is:
1.8 0.3 = 209.09999999... then you truncate it to int resulting in 209
you might find this question also relevant to you Why float.Epsilon and not zero? might be
CodePudding user response:
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.
CodePudding user response:
// Online C compiler to run C program online
#include<stdio.h>
#include <stdint.h>
int main()
{
float x = 1.8;
x = x 0.3;
uint16_t coefficient = 100;
printf("x: /\n", x);
uint16_t y = round(x * coefficient);
printf("y: %u\n", y);
return 0;
}