В моем численном моделировании у меня есть код, подобный следующему фрагменту
double x;
do {
x = /* some computation */;
} while (x <= 0.0);
/* some algorithm that requires x to be (precisely) larger than 0 */
В некоторых компиляторах (например, gcc) на определенных платформах (например, linux, x87 math) возможно, что x
вычисляется с точностью, превышающей двойную («с избыточной точностью»). ( Обновление : когда я говорю здесь о точности, я имею в виду точность / и / диапазон.) При этих обстоятельствах вполне возможно, что сравнение (x <= 0
) возвращает false, даже если в следующий раз x округляется в меньшую сторону для удвоения точности он становится равным 0. (И нет никакой гарантии, что x не будет округлено в произвольный момент времени.)
Есть ли способ выполнить это сравнение, что
- портативный,
- работает в коде, который встроен,
- не влияет на производительность и
- не исключает некоторый произвольный диапазон (0, eps)?
Я пытался использовать (x < std::numeric_limits<double>::denorm_min()
), но это, казалось, значительно замедляло цикл при работе с математикой SSE2. (Я знаю, что денормали могут замедлить вычисления, но я не ожидал, что они будут медленнее просто перемещаться и сравнивать.)
Обновление:
Альтернативой является использование volatile
для принудительного ввода x
в память перед сравнением, например написав
} while (*((volatile double*)&x) <= 0.0);
Однако, в зависимости от приложения и оптимизаций, применяемых компилятором, это решение также может привести к значительным накладным расходам.
Обновление:
Проблема с любым допуском заключается в том, что он довольно произвольный, т. Е. Зависит от конкретного приложения или контекста. Я предпочел бы просто выполнить сравнение без лишней точности, чтобы мне не приходилось делать какие-либо дополнительные предположения или вводить произвольные эпсилоны в документацию моих библиотечных функций.