If a hardware FMA is available, then, in most cases (cases where n
is expected not to be small, per below), the fastest test may be:
#include <cmath>
…
double q = dn/dd;
if (std::fma(-q, dd, dn))
std::cout << "Quotient was not exact.\n";
This can fail if nd−q•dd is so small it is rounded to zero, which occurs in round-to-nearest-ties-to-even mode if its magnitude is smaller than half the smallest representable positive value (commonly 2−1074). That can happen only if dn
itself is small. I expect I could calculate some bound on dn
for that if desired, and, given that dn
= n
and n
is an integer, that should not occur.
Ignoring the exponent bounds, a way to test the significands for divisibility is:
#include <cfloat>
#include <cmath>
…
int sink; // Needed for frexp argument but will be ignored.
double fn = std::ldexp(std::frexp(n, &sink), DBL_MANT_DIG);
double fd = std::frexp(d, &sink);
if (std::fmod(fn, fd))
std::cout << "Quotient will not be exact.\n";
Given that n and d are integers that are exactly representable in the floating-point type, I think we could show their exponents cannot be such that the above test would fail. There are cases where n is a small integer and d is large (a value from 21023 to 21024−2972, inclusive) that I need to think about.