В моих программах бесконечность обычно возникает, когда значение делится на ноль. Я становлюсь неопределенным, когда делю ноль на ноль. Как вы проверяете наличие бесконечных и неопределенных значений в C++?
В C++ бесконечность обозначается 1. # INF. Неопределенный обозначается -1. # IND. Проблема в том, как проверить, является ли переменная бесконечной или неопределенной. Проверка бесконечности относительно проста: вы найдете определение бесконечности в вашем конкретном C++. В моем случае (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())
}
Есть ли лучшие способы для этих проверок, я что-нибудь упустил?
Это правда. Эти две функции были моими предварительными мыслями, и мне было интересно, не упустил ли я что-нибудь. Но я думаю, они в порядке.
Вот страница, который объясняет, как тестировать бесконечности и т. д. Посмотрите на функции isNumber и isFiniteNumber.
«Неопределенный» не означает то, что вы думаете, он используется для описания содержимого неинициализированных переменных и висячих указателей. Результатом 0.0 / 0.0 является NaN, а не «неопределенный».





Хотя это не является строго частью C++ 03, если ваш компилятор предоставляет некоторые из новых функций C99 стандартного файла заголовка <math.h>, тогда у вас может быть доступ к следующим «макросам, подобным функциям»: isfinite, isinf , isnan. В таком случае это будет самый простой и безопасный способ выполнить эти проверки.
Для Visual Studio я бы использовал _isnan и _finite или, возможно, _fpclass.
Но если у вас есть доступ к стандартной библиотеке и компилятору с поддержкой C++ 11, вы можете использовать std::isnan и std::isinf.
Хотя это, безусловно, одно из решений, его не следует отмечать как ответ. Это очень специфично для платформы, и его следует избегать почти во всех случаях. Особенно с появлением std :: isinf и его семейства в C++ 11. Но даже если бы у вас был старый компилятор, я бы не пошел с этим решением только от Microsoft.
Также std::isfinite.
Вы также можете использовать их как строгое решение, предназначенное только для 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)
Насколько я знаю, вы также должны поместить :: is_iec559 в свое статическое утверждение, поскольку x! = x будет работать только в том случае, если ваша реализация реализует стандарт ieee754 stackoverflow.com/questions/332705/… (но я не уверен в этом. если вы знаете больше, пожалуйста, прокомментируйте)
Хороший вопрос. Не имею представления. Не стесняйтесь изменить свой ответ соответственно. В частности, я не знаю, какие альтернативные реализации могут быть выбраны и какие правила / гарантии для значений NaN они предоставляют.
Хотя C++ 03 не предоставляет C99 Иснан и isinfмакросы, C++ 11 стандартизирует их, предоставляя их как функции. Если вы можете использовать C++ 11 вместо строгого C++ 03, тогда это будут более чистые варианты, избегая макросов, встроенные компоненты компилятора и платформо-зависимых функций.
C++ 11 std::isfinite возвращает true для всех значений, кроме inf и nan; поэтому !isfinite должен проверять бесконечные и неопределенные значения за один раз.
Если у вас нет C++ 11, у Boost.Math есть реализации. boost.org/doc/libs/1_54_0/libs/math/doc/html/math_toolkit/…
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
Думаю, есть isfinite от C99 или POSIX или что-то в этом роде.
Один из хакерских способов сделать это - протестировать x-x == 0; если x бесконечен или NaN, тогда x-x равен NaN, поэтому сравнение не выполняется, а если x конечно, то x-x - это 0, и сравнение завершается успешно. Я бы порекомендовал использовать isfinite или упаковать этот тест в функцию / макрос, называемый чем-то вроде isfinite, чтобы вы могли избавиться от всего этого, когда придет время.
Лучше как? Один использует стандартную библиотеку, чтобы получить правильное представление для сравнения, а другой использует свойство, которое гарантируется языком (это сравнение с самим собой дает ложь). Обе функции просты и удобочитаемы. Нет ничего лучше, не так ли?