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

Как проверить для inf (и | или) NaN в двойной переменной

Рассмотрим следующий код:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

template<class T>
bool IsNaN(T t)
{
    return t != t;
}

int main(int argc, char**argv)
{
    double d1, d2;
    sscanf(argv[1], "%f", &d1);
    sscanf(argv[2], "%f", &d2);

    double dRes = d1/d2;

    cout << "dRes = " << dRes << "\n";

    if(IsNaN(dRes))
        cout << "Is NaN\n";
    else
        cout << "Not NaN\n";

}

Пара вопросов:

  • Когда я передаю 0 и 0 в качестве аргументов, он выводит dRes = inf. Но я ожидал dRes = NaN или что-то в этом роде.
  • Является ли NaN представимым в двойных переменных? В этом отношении любая переменная?
  • Когда я изменил тип данных d1, d2, dRes на int и прошел 0 и 0, я получил Floating exception. В чем разница?
  • Как проверить, равно ли значение переменной inf?
4b9b3361

Ответ 1

  • double следует читать с помощью %lf, а не %f. %f преобразует вход в 32-разрядный float, поэтому первые 32 бита ваших переменных будут заполнены некорректными данными, а последние 32 бита будут оставлены как мусор.

  • Да. #include <limits>, затем std::numeric_limits<double>::quiet_NaN(). Некоторые компиляторы (например, gcc) также предоставляют макрос NAN в <cmath>.

  • Нет никаких NaN или бесконечности для целых типов. Divide-by-zero для integer вызовет исключение (SIGFPE).

  • #include <cmath>, затем std::isinf(x). Используйте std::isfinite(x), чтобы гарантировать, что x не NaN или бесконечность.

Ответ 2

Функция fpclassify позволит вам проверять значение с плавающей запятой для всех особых случаев.

Он найден в <math.h> как макрос с C99 и в <cmath> как семейство функций для float, double и long double под перегруженным именем std::fpclassify, так как С++ 11.

cppreference имеет хороший пример

Ответ 3

Просто сделайте это так:

if (dRes  == +1.0/0.0 || dRes  == -1.0/0.0) ... //+INF, -INF
if (dRes  == +0.0/0.0 ) ... //+NaN; i.e. pow(2.0 ,16384.0)