Как проверить для 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
?
Ответы
Ответ 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)