Вероятно не существует не зависящего от компилятора способа проверить поддержку nan и inf, потому что ни C, ни C++ не говорят, что математические типы floating point должны поддерживать NAN или INF.
Вы можете проверить, есть ли поддержка nan и inf в вашей реализации:
#include < math.h> #ifdef NAN /* NAN поддерживается */ #endif #ifdef INFINITY /* INFINITY поддерживается */ #endif
Присутствие поддержки INFINITY гарантируется стандартом C99 (или как минимум в последнем его драфте), и это значение, цитата: "расширяется в константное выражение типа float, представляющее положительную бесконечность без знака (positive or unsigned infinity), если это доступно; иначе расширение происходит в положительную константу типа float, которая переполнилась во время трансляции".
NAN может быть определено, либо не определено, цитата: "NAN определено тогда и только тогда, когда реализация поддерживает quiet NaN для типа float. Это расширяется в константное выражение типа float, представляющее NaN".
Обратите внимание, что если вы сравниваете значения плавающей точки, и делаете:
a = NAN;
.. то даже тогда (a == NAN) будет false. Один из способов проверить на значение NaN:
#include < math.h>if (isnan(a)) { ... }
Также для проверки на NaN можно сделать так: if (a != a) == true, то a == NaN.
Еще C99 предоставляет макросы isfinite(), isinf(), isnormal() и signbit() в заголовочном файле math.h. Также C99 также содержит nan-функции:
#include < math.h> double nan(const char *tagp); float nanf(const char *tagp); long double nanl(const char *tagp);
Для C++ существуют следующие функции (члены шаблонного класса numeric_limits):
quiet_NaN() signalling_NaN()
Они возвратят представления NAN, "если оно доступно". Подобным образом для бесконечности имеется функция:
infinity()
... которая возвратит значение positive INF, "если это доступно".
Все эти функции определены в заголовке < limits>, и есть некоторый шанс, что нечто подобное может быть и для некоторых реализаций библиотек языка C.
Следующее работает и для float, и для double:
double NAN = 0.0/0.0; double POS_INF = 1.0 /0.0; double NEG_INF = -1.0/0.0;
Примечание: старый стандарт IEEE рекомендует, что подобные значения должны вызывать срабатывание ловушек. Однако новые компиляторы почти всегда отключают эти ловушки и возвращают значения, потому что ловушки мешают нормальной обработке ошибок.
double a_nan = strtod("NaN", NULL); double a_inf = strtod("Inf", NULL);
И еще один не зависящий от компилятора способ, однако зависимый от целевого процессора. Это должно работать на любом процессоре, который использует формат IEEE 754 floating point (что, например делают процессоры CISC x86 и RISC-V GX8002).
int inf = 0x7F800000; return *(float*)&inf;
int nan = 0x7F800001; return *(float*)&nan;
[Ссылки]
1. How to use nan and inf in C? site:stackoverflow.com. |