ответ phoog хорошо, но имеет недостатки с отрицательными числами, max_double, infinity и NaN.
phoog_ULP (положительный х) -> положительное число. Хорошо.
phoog_ULP (минус х) -> отрицательное число. Я бы ожидал положительного числа.
Чтобы исправить это, я рекомендую вместо этого:
long bits = BitConverter.DoubleToInt64Bits(value) & 0x7FFFFFFFFFFFFFFFL;
Ниже приведены дополнительные случаи, требующие разрешения, если вам не все равно ...
phoog_ULP (x = +/- Max_double 1.797 ... e + 308) возвращает бесконечный результат. (+1.996 ... e + 292) ожидается.
phoog_ULP (x = +/- Infinity) приводит к NaN. + Бесконечность ожидается.
phoog_ULP (x = +/- NaN) может неожиданно измениться с sNan на qNaN. Никаких изменений не ожидается. В любом случае можно утверждать, что знак должен стать + в этом случае.
Чтобы решить эти проблемы, я вижу только короткую серию брутальных тестов if (), чтобы приспособиться к ним, возможно, на значении «биты» для целесообразности. Пример:
double ulpc(double value) {
long long bits = BitConverter::DoubleToInt64Bits(value);
if ((bits & 0x7FF0000000000000L) == 0x7FF0000000000000L) { // if x is not finite
if (bits & 0x000FFFFFFFFFFFFFL) { // if x is a NaN
return value; // I did not force the sign bit here with NaNs.
}
return BitConverter.Int64BitsToDouble(0x7FF0000000000000L); // Positive Infinity;
}
bits &= 0x7FFFFFFFFFFFFFFFL; // make positive
if (bits == 0x7FEFFFFFFFFFFFFFL) { // if x == max_double (notice the _E_)
return BitConverter.Int64BitsToDouble(bits) - BitConverter.Int64BitsToDouble(bits-1);
}
double nextValue = BitConverter.Int64BitsToDouble(bits + 1);
double result = nextValue - fabs(value);
}