Reputation: 31
I am not an expert in programming, and I am facing the following issue.
I need to compute modulo between floats A and B. So I use fmod((double)A, (double)B). Theorically, if A is a multiple of B, then the result is 0.0. However, due to floating point precision purpose, A and B are not exactly the number I expected to have. Then, the result of the modulo computation is not 0.0, but something different. Which is problematic.
Example: A=99999.9, but the compiler interprets it as 99999.898. B=99.9, but the compiler interprets it as 99.900002. fmod(A,B) expected to be 0.0, but gives actually 99.9.
So the question is: how do you use to manage this kind of situation ?
Thank you
Upvotes: 2
Views: 80
Reputation: 153303
The trouble is that:
A
is not 99999.9
, but 99999.8984375 and
B
is not 99.9
, but 99.90000152587890625 and
A mod B
is 99.89691162109375
OP is getting the correct answer for the arguments given.
Need to use different augments.
A reasonable alternative is to convert the arguments by a scaled power-of-10, then round to an integer, %
, back to floating point and un-scale.
Overflow is a concern.
Since OP wants to treat numbers to the nearest 0.1, scale by 10.
#include <float.h>
#include <stdio.h>
int main(void) {
float A = 99999.9;
float B = 99.9;
printf("%.25f\n", A);
printf("%.25f\n", B);
printf("%.25f\n", fmod(A,B));
long long a = lround(A*10.0);
long long b = lround(B*10.0);
long long m = a%b;
double D = m/10.0;
printf("D = %.25f\n", D);
return 0;
}
Output
99999.8984375000000000000000000
99.9000015258789062500000000
99.8969116210937500000000000
D = 0.0000000000000000000000000
Alternative
long long a = lround(A*10.0);
long long b = lround(B*10.0);
long long m = a%b;
double D = m/10.0;
Scale, but skip the integer conversion part
double a = round(A*10.0);
double b = round(B*10.0);
double m = fmod(a,b);
double D = m/10.0;
Upvotes: 2