Как вы проверяете бесконечные и неопределенные значения в C++?
В моих программах бесконечность обычно возникает, когда значение делится на ноль. Я становлюсь неопределенным, когда делю ноль на ноль. Как вы проверяете бесконечные и неопределенные значения в C++?
В C++ бесконечность представлена 1.#БЕСКОНЕЧНОСТЬ. Неопределенное представлено значением -1.#IND. Проблема заключается в том, как проверить, является ли переменная бесконечной или неопределенной. Проверка бесконечности относительно проста: вы находите определение бесконечности в вашем конкретном C++. Для моего случая (VS2003), это std:: numeric_limits:: infinity(). Вы должны включить "ограничения", чтобы использовать его. Вы можете присвоить это бесконечное значение переменной и сравнить его с некоторым значением, чтобы проверить, является ли это значение бесконечным.
Неопределенное - это немного сложно, потому что вы не можете сравнить неопределенное значение с каким-то другим значением. Любое сравнение возвращает false. Это свойство можно использовать для определения неопределенного значения, сравнивая его с самим собой. Допустим, у вас есть двойная переменная под названием 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())
}
Есть ли лучшие способы для этих проверок, я что-нибудь упускаю?
6 ответов:
Для Visual Studio я бы использовал
_isnan
и еще_finite
, или, возможно,_fpclass
.Но если у вас есть доступ к стандартной библиотеке и компилятору C++11, вы можете использовать
std::isnan
и ещеstd::isinf
.
Хотя C++03 не предоставляет C99 isnan и isinf макросы , C++11 стандартизирует их, предоставляя их в виде функций . Если вы можете использовать C++11 вместо строгого C++03, то это будут более чистые варианты, избегая макросов, встроенных компиляторов и зависящих от платформы функций.
C++11's
std::isfinite
возвращаетtrue
для всех значений, кромеinf
иnan
; поэтому!isfinite
должен проверять бесконечные и неопределенные значения в одном выстрел.
Хотя и не является строго частью C++03, Если ваш компилятор предоставляет некоторые из новых функций C99 стандарта
заголовочный файл, то у вас может быть доступ к следующим "функциональным макросам": isfinite
,isinf
,isnan
. Если это так, то это будет самый простой и безопасный способ выполнить эти проверки.
Вы также можете использовать их как строгое решение только для C++. На самом деле они не предлагают больше, чем решение 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
, чтобы вы могли избавиться от всего этого, когда придет время.