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

В моих программах бесконечность обычно возникает, когда значение делится на ноль. Я становлюсь неопределенным, когда делю ноль на ноль. Как вы проверяете наличие бесконечных и неопределенных значений в 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())
}

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

Лучше как? Один использует стандартную библиотеку, чтобы получить правильное представление для сравнения, а другой использует свойство, которое гарантируется языком (это сравнение с самим собой дает ложь). Обе функции просты и удобочитаемы. Нет ничего лучше, не так ли?

jalf 04.01.2009 16:14

Это правда. Эти две функции были моими предварительными мыслями, и мне было интересно, не упустил ли я что-нибудь. Но я думаю, они в порядке.

Samil 05.01.2009 00:59

Вот страница, который объясняет, как тестировать бесконечности и т. д. Посмотрите на функции isNumber и isFiniteNumber.

John D. Cook 04.01.2009 14:38

«Неопределенный» не означает то, что вы думаете, он используется для описания содержимого неинициализированных переменных и висячих указателей. Результатом 0.0 / 0.0 является NaN, а не «неопределенный».

Pascal Cuoq 30.07.2014 13:03
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
31
4
40 723
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

Ответ принят как подходящий

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

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

Хотя это, безусловно, одно из решений, его не следует отмечать как ответ. Это очень специфично для платформы, и его следует избегать почти во всех случаях. Особенно с появлением std :: isinf и его семейства в C++ 11. Но даже если бы у вас был старый компилятор, я бы не пошел с этим решением только от Microsoft.

Ela782 30.07.2014 01:01

Также std::isfinite.

jxh 13.01.2015 21:05

Вы также можете использовать их как строгое решение, предназначенное только для 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/… (но я не уверен в этом. если вы знаете больше, пожалуйста, прокомментируйте)

Johannes Schaub - litb 05.01.2009 01:24

Хороший вопрос. Не имею представления. Не стесняйтесь изменить свой ответ соответственно. В частности, я не знаю, какие альтернативные реализации могут быть выбраны и какие правила / гарантии для значений NaN они предоставляют.

Konrad Rudolph 05.01.2009 23:32

Хотя 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/…

Sebastian Redl 18.07.2013 16:56

Из опубликованной ссылки @ legends2k видно, что !std::isnormal() - лучший тест.

Warpspace 15.02.2016 10:04

Вы хотели написать std::isfinite? !isnormal вернет true даже для 0, чего не хочет OP - должен возвращать true только для значений inf и nan, поэтому !isfinite сделает это.

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

Другие вопросы по теме