Given the following doubles, does fmod
return the correct value?
double x = .090;
double y = .003;
double r = fmod(x, y);
// r = 0.0029999999999999949
Why doesn't r = 0?
Given the following doubles, does fmod
return the correct value?
double x = .090;
double y = .003;
double r = fmod(x, y);
// r = 0.0029999999999999949
Why doesn't r = 0?
Because, like most decimal fractions, these numbers can't be represented exactly by a binary floating point format. To see what values are actually being used:
#include <cstdio>
int main() {
printf("%.20f %.20f\n", .090, .003);
}
Output: 0.08999999999999999667 0.00300000000000000006
These small rounding errors mean that the first value is slightly less than an exact multiple of the second, hence the result you see.
You may want to allow a small tolerance for error:
if (r > y - some_small_value) {
r = 0;
}
This type of question can be resolved by reading a paper entitled What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Your machine uses a binary representation for floating-point numbers which cannot exactly represent the rational number 3/1000 = 0.003.
Of course, the machine can print its approximation of 0.003 as "0.003"
, but that's being done by the formatted printing code inside printf
, when it rounds off the value to a given number of decimal digits.
The difference between the printed, decimal versions of floating-point values and their actual internal values can create problems for the programmer or user who isn't aware of the issues.