Если доступен аппаратный FMA, то в большинстве случаев (в случаях, когда n
ожидается не малым, как указано ниже), самый быстрый тест может быть:
#include <cmath>
…
double q = dn/dd;
if (std::fma(-q, dd, dn))
std::cout << "Quotient was not exact.\n";
Это может не сработать, если nd - q • dd настолько мало, что округляется до нуля, что происходит при округлении до ближайших связей. в режим четности, если его величина меньше половины наименьшего представимого положительного значения (обычно 2 -1074 ). Это может произойти, только если dn
само по себе мало. Я ожидаю, что мог бы рассчитать некоторую оценку для dn
для этого, если это необходимо, и, учитывая, что dn
= n
и n
- целое число, это не должно происходить.
Игнорирование границ экспонент, способ проверки значений и делимости:
#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";
Учитывая, что n и d являются целыми числами, которые точно представимы в типе с плавающей запятой, я думаю, мы могли бы показать, что их показатели не могут быть такими, чтобы вышеприведенный тест не удался. Есть случаи, когда n - это маленькое целое число, а d - большое (значение от 2 1023 до 2 1024 −2 972 включительно), о котором мне нужно подумать.