web-dev-qa-db-fra.com

Comment générer NaN, -Infinity et + Infinity en ANSI C?

J'utilise ANSI C89 (pas C++), et je veux générer NaN, -Infinity et + Infinity.

Existe-t-il un moyen standard (par exemple, une macro standard)? Ou existe-t-il un moyen indépendant de la plate-forme et du compilateur pour générer ces chiffres?

float f = 0.0 / 0.0; // Is f ALWAYS in any platform is NaN?
45
Amir Saniyan

Il existe en C99, mais pas dans les normes précédentes AFAIK.

En C99, vous aurez des macros NAN et INFINITY.

De "Mathématiques <math.h> " (§7.12) section

La macro [~ # ~] infini [~ # ~] se développe en une expression constante de type float représentant une infinité positive ou non signée, si disponible; ...

Si vous êtes coincé avec ANSI C89, vous n'avez pas de chance. Voir C-FAQ 14.9 .

41
Mat

Si vous utilisez un ancien compilateur où INFINITY n'existe pas, vous pouvez également utiliser la macro HUGE_VAL à la place, également défini dans le <math.h> bibliothèque.

HUGE_VAL devrait être disponible dans la norme C89/C90 (ISO/IEC 9899: 1990).

Références: http://en.cppreference.com/w/c/numeric/math/HUGE_VAL

0
mlel

Il existe un moyen réel de créer l'infini et l'infini négatif. Sur la base de la norme IEEE 754, que suit C89, l'infini est défini comme un nombre à virgule flottante contenant tous les zéros de la mantisse (vingt-trois premiers bits) et tous ceux de l'exposant (huit bits suivants). nan est défini comme n'importe quel nombre avec tous ceux de l'exposant, et tout sauf des zéros dans la mantisse (parce que c'est l'infini). La partie difficile génère ce nombre, mais cela peut être accompli avec le code suivant:

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;

Cependant, le simple fait de convertir un unsigned en float entraînerait la création par le compilateur d'un float de la même valeur. Donc, ce que nous devons faire, c'est forcer le compilateur à lire la mémoire comme un flottant, ce qui nous donne le résultat souhaité.

0
Clayton L