У меня есть численный метод, который мог возвратить nan или inf, если бы была ошибка, и для тестирования, ставившего целью, я хотел бы временно вынудить это возвратить nan или inf, чтобы гарантировать, что ситуация обрабатывается правильно. Существует ли надежный, независимый от компилятора способ создать стоимость nan и inf в C?
После поиска с помощью Google в течение приблизительно 10 минут я только смог найти зависимые решения для компилятора.
Вы можете проверить, есть ли он в вашей реализации:
#include <math.h>
#ifdef NAN
/* NAN is supported */
#endif
#ifdef INFINITY
/* INFINITY is supported */
#endif
Существование INFINITY
] гарантируется C99 (или, по крайней мере, последним черновиком), и "расширяется до константного выражения типа float, представляющего положительный или беззнаковый
бесконечность, если есть; else на положительную константу типа float, которая переполняется во время трансляции. "
NAN
может быть определен или не определен, и" определяется тогда и только тогда, когда реализация поддерживает тихие NaN для типа float. Он расширяется до константного выражения типа float, представляющего тихое NaN. "
Обратите внимание, что если вы сравниваете значения с плавающей запятой и делаете:
a = NAN;
даже тогда,
a == NAN;
ложно. Один из способов проверить NaN будет:
#include <math.h>
if (isnan(a)) { ... }
Вы также можете выполнить: a! = a
, чтобы проверить, является ли a
NaN.
Также существует isfinite ()
, isinf ()
, isnormal ()
и signbit ()
макросы в math.h
в C99.
C99 также имеет nan
функции:
#include <math.h>
double nan(const char *tagp);
float nanf(const char *tagp);
long double nanl(const char *tagp);
(Ссылка: n1256).
Независимый от компилятора, но не независимый от процессора способ получить их:
int inf = 0x7F800000;
return *(float*)&inf;
int nan = 0x7F800001;
return *(float*)&nan;
Это должно работать на любом процессоре, который использует формат с плавающей запятой IEEE 754 (что и есть в x86).
ОБНОВЛЕНИЕ: проверено и обновлено.
Не существует независимого от компилятора способа сделать это, поскольку ни стандарты C (ни C ++) не говорят, что математические типы с плавающей запятой должны поддерживать NAN или INF.
Изменить: Я только что проверил формулировку стандарта C ++, и там говорится, что эти функции (члены шаблонного класса numeric_limits):
quiet_NaN()
signalling_NaN()
будут возвращать представления NAN «если они доступны». Он не расширяет то, что означает «если доступно», но, по-видимому, что-то вроде «если представитель реализации FP поддерживает их». Точно так же есть функция:
infinity()
, которая возвращает положительный INF rep «если доступно».
Оба они определены в заголовке
- я полагаю, что в стандарте C есть что-то аналогично (вероятно, также "если есть"), но я не
Это работает как для float
и двойной
:
double NAN = 0.0/0.0;
double POS_INF = 1.0 /0.0;
double NEG_INF = -1.0/0.0;
Редактировать: Как кто-то уже сказал, старый стандарт IEEE сказал, что такие ценности должны создавать ловушки. Но новые компиляторы почти всегда выключают ловушки и возвращают данные значения, потому что захват мешает ошибке обработка.
Я также удивлен, что это не константы времени компиляции. Но я полагаю, вы могли бы достаточно легко создать эти значения, просто выполнив инструкцию, которая возвращает такой недопустимый результат. Деление на 0, логарифм 0, загар 90 и тому подобное.