fmod(1001.0, 0.0001) is giving 0.00009999999995, which seems like a very low precision (10-5), given the expected result of 0.
According to cppreference, fmod() is implementable using remainder(), but remainder(1001.0, 0.0001) gives -4.796965775988316e-14 (still far from double precision, but much better than 10-5).
Why does fmod precision depend on input arguments that much? Is it normal?
MCVE:
#include <cmath>
#include <iomanip>
#include <iostream>
using namespace std;
int main() {
double a = 1001.0, b = 0.0001;
cout << setprecision(16);
cout << "fmod: " << fmod(a, b) << endl;
cout << "remainder: " << remainder(a, b) << endl;
cout << "actual: " << a-floor(a/b)*b << endl;
cout << "a/b: " << a / b << endl;
}
Output:
fmod: 9.999999995203035e-05
remainder: -4.796965775988316e-14
actual: 0
a/b: 10010000
(same result with GCC, Clang, MSVC, with and without optimization)
If we modify your program to:
It outputs:
we can see that
0.0001is not representable as adoublesobis actually set to0.00010000000000000000479217360238593.This results in
a/bbeing10009999.9999999995203034224which therefore meansfmodshould return1001 - 10009999*0.00010000000000000000479217360238593which is9.99999999520303470323e-5.(numbers calculated in speedcrunch so may not match exactly IEEE double values)
The reason your "actual" value is different is that
floor(a/b)returns10010000not the exact value used byfmodwhich is10009999, this is itself due to10009999.99999999952not being representable as a double so it is rounded to10010000before being passed to floor.