Как вы проверяете бесконечные и неопределенные значения в 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, чтобы вы могли избавиться от всего этого, когда придет время.