50 votes

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 une méthode 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?

1 votes

Les plateformes arbitraires ne sont même pas tenues par la norme de supporter les NaN et les infinis. Je crois qu'une implémentation conforme à la norme IEEE 754 est requise pour les obtenir par division, comme dans votre exemple, cependant.

44voto

Mat Points 104488

Il y en a un dans C99, mais pas dans les normes précédentes AFAIK.

En C99, vous aurez NAN et INFINITY macros.

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

La macro INFINITY se développe en une expression constante de type float représentant l'innité positive ou non signée, si disponible ; ...

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

21 votes

Vous devriez dire "ANSI C89". L'actuelle "ANSI C" est la C99.

2 votes

En C89, la macro HUGE_VAL est disponible pour définir les valeurs de l'infini.

5voto

jcomeau_ictx Points 15736

Je ne sais pas si c'est standard ou portable, mais c'est un début :

jcomeau@intrepid:/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

Bizarrement, je ne peux pas obtenir de NaN positif en utilisant cette approche naïve.


Voir aussi ceci : http://www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html

3 votes

Drôle, qui produit inf -inf nan (pas -nan ) avec clang. Je ne sais pas vraiment ce que -nan est censé signifier, en fait :-)

0 votes

Résultat de VS2010 : 1.#INF00 -1.#INF00 -1.#IND00

1 votes

2voto

mlel Points 135

Si vous utilisez un ancien compilateur où INFINITY n'existe pas, vous pouvez également utiliser la macro HUGE_VAL à la place, également définie 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

2voto

Clayton L Points 428

Il existe un moyen réel de créer l'infini et l'infini négatif. Selon la norme IEEE 754, que C89 suit, l'infini est défini comme un nombre à virgule flottante contenant tous les zéros dans la mantisse (vingt-trois premiers bits) et tous les uns dans l'exposant (huit bits suivants). nan est défini comme tout nombre ayant tous les uns dans l'exposant, et tout sauf tous les zéros dans la mantisse (car c'est l'infini). La partie la plus difficile est de générer 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 lancer un unsigned à un float aurait pour conséquence la création par le compilateur d'un float de la même valeur. Donc, ce que nous devons faire est de forcer le compilateur à lire la mémoire comme un float, ce qui nous donne le résultat souhaité.

1 votes

Cela rompt le strict aliasing. Si possible, utilisez memcpy ou la méthode traditionnelle de division par zéro.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X