Подтвердить что ты не робот

Как вы проверяете бесконечные и неопределенные значения в С++?

В моих программах бесконечность обычно возникает, когда значение делится на ноль. Я становлюсь неопределенным, когда я делю нуль на ноль. Как вы проверяете бесконечные и неопределенные значения в С++?

В С++ бесконечность представлена ​​как 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())
}

Есть ли лучшие способы для этих проверок, я что-то пропустил?

4b9b3361

Ответ 1

Для Visual Studio я бы использовал _isnan и _finite, или, возможно, _fpclass.

Но если у вас есть доступ к стандартной библиотеке и компилятору, совместимому с С++ 11, вы можете использовать std::isnan и std::isinf.

Ответ 2

Хотя С++ 03 не предоставляет C99 isnan и isinf, С++ 11 их стандартизирует, предоставляя им функции . Если вы можете использовать С++ 11 вместо строгой С++ 03, то это были бы более чистые варианты, избегая макросов, встроенные компиляторы и функции, зависящие от платформы.

С++ 11 std::isfinite возвращает true для всех значений, кроме inf и nan; поэтому !isfinite должен проверять бесконечные и неопределенные значения за один снимок.

Ответ 3

Хотя это не является частью С++ 03, если ваш компилятор предоставляет некоторые из новых функций C99 стандарта < math.h > заголовочный файл, тогда у вас может быть доступ к следующим "функциональным макросам": isfinite, isinf, isnan. Если это так, это будет самый простой и безопасный способ выполнить эти проверки.

Ответ 4

Вы также можете использовать их как строгое решение на С++. Они действительно не предлагают больше, чем решение 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)

Ответ 5

Там isfinite от C99 или POSIX или что-то, что я думаю.

Один хакерский способ сделать это - проверить x-x == 0; если x бесконечно или NaN, то x-x есть NaN, поэтому сравнение терпит неудачу, а если x конечно, то x-x есть 0, и сравнение преуспевает. Я бы рекомендовал использовать isfinite, хотя, или упаковывая этот тест в функцию/макрос, называемый чем-то вроде isfinite, чтобы вы могли избавиться от всего этого, когда придет время.

Ответ 6

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