У меня есть число, которое может быть нулями. Я делю на это число, поэтому я хочу проверить, равен ли он нулю, чтобы предотвратить NaN и бесконечности. Возможно ли, что я все еще создаю NaNs / бесконечность из-за ошибок округления внутри деления?
double x; // might be zero
double y;
if(x != 0) return y / x;
РЕДАКТИРОВАТЬ
Спасибо за ответы. Я добавлю несколько подвопросов тогда.
1) предполагая, что ни x, ни y не являются NaN / + inf или -inf, приведет ли деление, которое приводит к -inf / + inf, к увеличению числа циклов ЦП или к любому другому нежелательному поведению? (Может ли это потерпеть крах?)
2) есть ли способ предотвратить разделение на бесконечность? Использование смещений и так далее.
Может ли деление на ненулевое значение создать нан / бесконечность?
Да.
Если соблюдается IEEE-754, то:
Правила других представлений могут быть разными.
2) есть ли способ предотвратить отклонение, приводящее к бесконечности
Это должно иметь большое значение для предотвращения этого:
#include <cfenv>
#include <cassert>
#include <cmath>
#include <limits>
// ...
static_assert(std::numeric_limits<decltype(x)>::is_iec559, "Unknown floating point standard.");
#pragma STDC FENV_ACCESS ON
int failed = std::fesetround(FE_TOWARDZERO);
assert(!failed);
if(x != 0 && std::isfinite(x) && std::isfinite(y))
return y / x;
else
throw std::invalid_argument("informative message");
Некоторым компиляторам могут потребоваться параметры не по умолчанию, чтобы включить полное соответствие IEEE 754 (-frounding-math
на GCC).
Разделение очень маленького числа на очень большое число или умножение двух очень больших чисел может привести к «бесконечности». Разделив бесконечность на другую бесконечность, мы получим NaN. Например, (1E300/1E-300)/(1E300/1E-300)
или же (1E300*1E300)/(1E300*1E300)
оба принесут NaN.
Да, просто посмотрите на код ниже
#include <iostream>
int main ()
{
double x = 1, y = 2;
while (y != 0) {
std::cout << y << " " << x / y << std::endl;
y /= 2;
}
}
в какой-то момент вы получите:
8.9003e-308 1.12356e+307
4.45015e-308 2.24712e+307
2.22507e-308 4.49423e+307
1.11254e-308 8.98847e+307
5.56268e-309 inf
2.78134e-309 inf
1.39067e-309 inf
6.95336e-310 inf