Для краткости, допустим, я хочу вычислить выражение a / (b - c)
на float
с.
Чтобы убедиться, что результат имеет смысл, я могу проверить, равны ли b
и c
:
float EPS = std::numeric_limits<float>::epsilon();
if ((b - c) > EPS || (c - b) > EPS)
{
return a / (b - c);
}
но мои тесты показывают, что этого недостаточно для того, чтобы гарантировать либо значимые результаты, либо не дать результата, если это возможно.
Дело 1:
a = 1.0f;
b = 0.00000003f;
c = 0.00000002f;
Результат: Условие if НЕ выполнено, но выражение даст правильный результат 100000008 (что касается точности с плавающей точкой).
Дело 2:
a = 1e33f;
b = 0.000003;
c = 0.000002;
Результат: Условие if выполнено, но выражение не дает значимого результата +1.#INF00
.
Мне показалось, что проверять результат гораздо надежнее, чем аргументы:
const float INF = numeric_limits<float>::infinity();
float x = a / (b - c);
if (-INF < x && x < INF)
{
return x;
}
Но зачем тогда эпсилон и почему все говорят, что эпсилон хорошо использовать?