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

Как генерировать NaN, -Infinity и + Infinity в ANSI C?

Я использую ANSI C89 (не С++), и я хочу сгенерировать NaN, -Infinity и + Infinity.

Есть ли стандартный способ (например, стандартный макрос)? Или существует какой-либо платформенный и независимый от компилятора способ генерации этих чисел?

float f = 0.0 / 0.0; // Is f ALWAYS in any platform is NaN?
4b9b3361

Ответ 1

Есть в C99, но не в предыдущих стандартах AFAIK.

В C99 у вас будут макросы NAN и INFINITY.

От "Математика <math.h>" (§7.12) раздел

Макрос INFINITY расширяется до постоянного выражения типа float, представляющего положительную или неподписанную бесконечность, если доступно;...

Если вы застряли с ANSI C89, вам не повезло. См. C-FAQ 14.9.

Ответ 2

Я не знаю, является ли это стандартным или портативным, но вот старт:

[email protected]:/tmp$ cat test.c; make test; ./test
#include <stdio.h>
int main() {
 printf("%f\n", 1.0 / 0);
 printf("%f\n", -1.0 / 0);
 printf("%f\n", 0.0 / 0);
 return 0;
}
cc     test.c   -o test
test.c: In function ‘main’:
test.c:3: warning: division by zero
test.c:4: warning: division by zero
test.c:5: warning: division by zero
inf
-inf
-nan

Как ни странно, я не могу получить положительный NaN, используя этот наивный подход.


Также см. Это: http://www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html

Ответ 3

Если вы используете старый компилятор, где INFINITY не существует, вы также можете использовать макрос HUGE_VAL, также определенный в библиотеке <math.h>.

HUGE_VAL должен быть доступен в стандарте C89/C90 (ISO/IEC 9899: 1990).

Ссылки: http://en.cppreference.com/w/c/numeric/math/HUGE_VAL

Ответ 4

Существует реальный способ создания бесконечности и отрицательной бесконечности. На основе стандарта IEEE 754, которому следует C89, бесконечность определяется как число с плавающей запятой, содержащее все нули в мантиссе (первые двадцать три бита) и все единицы в показателе степени (следующие восемь битов). nan определяется как любое число со всеми единицами в показателе степени и всем, кроме всех нулей в мантиссе (потому что эта бесконечность). Сложная часть - это генерация этого числа, но это можно сделать с помощью следующего кода:

unsigned int p = 0x7F800000; // 0xFF << 23
unsigned int n = 0xFF800000; // 0xFF8 << 20
unsigned int pnan = 0x7F800001; // or anything above this up to 0x7FFFFFFF
unsigned int nnan = 0xFF800001; // or anything above this up to 0xFFFFFFFF

float positiveInfinity = *(float *)&p;
float negativeInfinity = *(float *)&n;
float positiveNaN = *(float *)&pnan;
float negativeNaN = *(float *)&nnan;

Однако простое приведение unsigned к float приведет к тому, что компилятор создаст float с тем же значением. Итак, нам нужно заставить компилятор читать память как число с плавающей запятой, что дает нам желаемый результат.