Ответ 1
Для Visual Studio я бы использовал _isnan
и _finite
, или, возможно, _fpclass
.
Но если у вас есть доступ к стандартной библиотеке и компилятору, совместимому с С++ 11, вы можете использовать std::isnan
и std::isinf
.
В моих программах бесконечность обычно возникает, когда значение делится на ноль. Я становлюсь неопределенным, когда я делю нуль на ноль. Как вы проверяете бесконечные и неопределенные значения в С++?
В С++ бесконечность представлена как 1. # INF. Неопределенный - -1. # IND. Проблема заключается в том, как проверить, является ли переменная бесконечной или неопределенной. Проверка бесконечности относительно проста: вы найдете определение бесконечности в вашем конкретном С++. Для моего случая (VS2003) это std:: numeric_limits:: infinity(). Вы должны включить "ограничения", чтобы использовать его. Вы можете назначить это бесконечное значение переменной, и вы можете сравнить ее с некоторым значением, чтобы проверить, является ли это значение бесконечным.
Неопределенный немного сложнее, потому что вы не можете сравнивать неопределенное значение с каким-либо другим значением. Любое сравнение возвращает false. Вы можете использовать это свойство для определения неопределенного значения, сравнивая его с самим собой. Скажем, у вас есть двойная переменная, называемая aVal. В нормальных условиях aVal!= AVal возвращает false. Но если значение неопределенно, aIndVal!= AIndVal возвращает true. Эта странная ситуация отсутствует для бесконечных значений, т.е. AInfVal!= AInfVal всегда возвращает false.
Вот две функции, которые можно использовать для проверки неопределенных и бесконечных значений:
#include "limits.h"
#include "math.h"
bool isIndeterminate(const double pV)
{
return (pV != pV);
}
bool isInfinite(const double pV)
{
return (fabs(pV) == std::numeric_limits::infinity())
}
Есть ли лучшие способы для этих проверок, я что-то пропустил?
Для Visual Studio я бы использовал _isnan
и _finite
, или, возможно, _fpclass
.
Но если у вас есть доступ к стандартной библиотеке и компилятору, совместимому с С++ 11, вы можете использовать std::isnan
и std::isinf
.
Хотя С++ 03 не предоставляет C99 isnan и isinf, С++ 11 их стандартизирует, предоставляя им функции . Если вы можете использовать С++ 11 вместо строгой С++ 03, то это были бы более чистые варианты, избегая макросов, встроенные компиляторы и функции, зависящие от платформы.
С++ 11 std::isfinite
возвращает true
для всех значений, кроме inf
и nan
; поэтому !isfinite
должен проверять бесконечные и неопределенные значения за один снимок.
Хотя это не является частью С++ 03, если ваш компилятор предоставляет некоторые из новых функций C99 стандарта < math.h > заголовочный файл, тогда у вас может быть доступ к следующим "функциональным макросам": isfinite
, isinf
, isnan
. Если это так, это будет самый простой и безопасный способ выполнить эти проверки.
Вы также можете использовать их как строгое решение на С++. Они действительно не предлагают больше, чем решение OP, за исключением дополнительной безопасности с использованием признаков типа и, возможно, самого маленького увеличения скорости в случае is_inf
.
template <bool> struct static_assert;
template <> struct static_assert<true> { };
template<typename T>
inline bool is_NaN(T const& x) {
static_cast<void>(sizeof(static_assert<std::numeric_limits<T>::has_quiet_NaN>));
return std::numeric_limits<T>::has_quiet_NaN and (x != x);
}
template <typename T>
inline bool is_inf(T const& x) {
static_cast<void>(sizeof(static_assert<std::numeric_limits<T>::has_infinity>));
return x == std::numeric_limits<T>::infinity() or x == -std::numeric_limits<T>::infinity();
}
(остерегайтесь самодельного static_assert
)
Там isfinite
от C99 или POSIX или что-то, что я думаю.
Один хакерский способ сделать это - проверить x-x == 0
; если x
бесконечно или NaN, то x-x
есть NaN, поэтому сравнение терпит неудачу, а если x
конечно, то x-x
есть 0
, и сравнение преуспевает. Я бы рекомендовал использовать isfinite
, хотя, или упаковывая этот тест в функцию/макрос, называемый чем-то вроде isfinite
, чтобы вы могли избавиться от всего этого, когда придет время.
if (x!=x) ... then x is nan
if (x>0 && x/x != x/x) ... then x is +inf
if (x<0 && x/x != x/x) ... then x is -inf
это также может работать (но включает вызов функции exp() и проверку равенства удвоений):
if (exp(-x)==0.) ... then x is inf
if (exp(x)==0.) ... then x is -inf