Comment produire un float NaN en c?

float f = (float)'a'; if(f  0){ } else{ printf("NaN\n"); } 

f ne sera pas supérieur / égal / inférieur à 0 s’il s’agit d’un NaN .

Mais comment produire un tel f en premier lieu?

J’ai essayé différentes façons de produire un NaN , mais aucun ne fonctionne.

En utilisant des nombres à virgule flottante, 0.0 / 0.0 n’est pas une erreur de “division par zéro”; il en résulte NaN .

Ce programme C imprime -nan :

 #include  int main() { float x = 0.0 / 0.0; printf("%f\n", x); return 0; } 

En termes d’apparence de NaN pour l’ordinateur, deux nombres “non valides” sont réservés à “signalisation” et à “silencieux” NaN (similaires aux deux nombres non valides réservés aux infinis positif et négatif). L’ entrée Wikipedia contient plus de détails sur la façon dont NaN est représenté sous forme de nombre à virgule flottante IEE.

Pour produire un nan, il y a plusieurs façons:

1) le générer manuellement (lisez ieee754 pour configurer correctement les bits)

2) utiliser une macro. GCC expose une macro NAN . C’est défini dans math.h

La manière générale de vérifier un nan est de vérifier if (f == f) (ce qui devrait échouer pour des valeurs nan)

Pour nan, les bits d’exposant dans la représentation float doivent tous être mis à 1 (float consiste en un bit signé, un ensemble de bits d’exposant et un ensemble de bits de mantisse).

Dans le manuel GNU GCC, math.h définit des macros permettant de définir explicitement une variable sur infini ou sur NaN. Comme il s’agit d’une partie de C99, vous pouvez utiliser les macros suivantes avec d’autres compilateurs compatibles C99.

– Macro: float INFINITY Une expression représentant l’infini positif. Il est égal à la valeur produite par des opérations mathématiques telles que 1.0 / 0.0. -INFINITY représente l’infini négatif.

Vous pouvez tester si une valeur à virgule flottante est infinie en la comparant à cette macro. Cependant, cela n’est pas recommandé. vous devriez plutôt utiliser la macro isfinite. Voir Classes en virgule flottante.

Cette macro a été introduite dans la norme ISO C99.

– Macro: float NAN Expression représentant une valeur qui n’est «pas un nombre». Cette macro est une extension GNU, disponible uniquement sur les machines prenant en charge la valeur «not a number», c’est-à-dire sur toutes les machines prenant en charge le point flottant IEEE.

Vous pouvez utiliser ‘#ifdef NAN’ pour vérifier si la machine prend en charge NaN. (Bien entendu, vous devez faire en sorte que les extensions GNU soient visibles, par exemple en définissant _GNU_SOURCE, puis vous devez inclure math.h.)

pour plus d’informations, vous pouvez voir ici: http://www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html

Vous pouvez utiliser la macro NAN ou simplement l’une des fonctions nan/nanf pour atsortingbuer une valeur nan à une variable.
Pour vérifier si vous avez affaire à une valeur nan, vous pouvez utiliser isnan() . Voici un exemple:

 #include  #include  int main(void) { float a = NAN;//using the macro in math.h float f = nanf("");//using the function version double d = nan("");//same as above but for doubles! printf("a = %f\nf = %f\nd = %f\n",a,f,d); if(isnan(a)) puts("a is a not a number!(NAN)\n"); return 0; } 

L’exécution de l’extrait de code ci-dessus vous donnera cette sortie:

 a = nan f = nan d = nan a is a not a number!(NAN) 

Exécutez le code vous-même: http://ideone.com/WWZBl8
Lire plus d’informations: http://www.cplusplus.com/reference/cmath/NAN/

Cela fonctionne aussi pour les constantes (0/0 donnera une erreur de compilation sur vs):

 const unsigned maxU = ~0; const float qNan = *((float*)&maxU); 

Pour les implémentations C hébergées, on peut faire un #include et utiliser la macro NAN si elle est définie. Par exemple, avec GCC, il est implémenté par un élément intégré: (__builtin_nanf ("")) .

Pour les implémentations C autonomes (sur lesquelles l’en-tête peut ne pas être disponible) ou lorsque la macro NAN n’est pas définie (ce qui peut arriver même si les NaN peuvent être pris en charge), il est possible de générer un NaN avec une opération à virgule flottante. tels que 0.0 / 0.0 . Cependant, il peut y avoir plusieurs problèmes avec cela.

Premièrement, une telle opération génère également une exception, avec une interruption possible sur certaines implémentations en C. On peut s’assurer qu’il est calculé au moment de la compilation avec:

 static double my_nan = 0.0 / 0.0; 

Un autre problème est que Microsoft Visual C ++ (au moins certaines versions) tente d’évaluer 0.0 / 0.0 au moment de la compilation (même lorsque cette expression se trouve à un endroit arbitraire du code) et se plaint de sa validité. Donc, la solution ici est l’inverse: assurez-vous que le compilateur ne l’évaluera pas au moment de la compilation, en faisant:

 static double zero = 0.0; 

puis utilisez zero / zero . Ces solutions étant en conflit, on peut tester le compilateur avec des directives de préprocesseur ( #if …) sur des macros spécifiques .

On peut également choisir une solution basée sur le codage NaN, mais il existe également des problèmes de portabilité. Premièrement, la norme IEEE 754 ne définit pas complètement le codage d’un NaN, en particulier la manière de distinguer les NaN silencieux et les signaux de signalisation (et le matériel diffère dans la pratique); les NaN de signalisation donneront un comportement indéfini. De plus, la norme IEEE 754 ne définit pas comment la chaîne de bits est représentée en mémoire, c’est-à-dire que l’endianité doit éventuellement être détectée. Si ces problèmes sont résolus, une union ou un tableau de caractères unsigned char avec une conversion de pointeur convient parfaitement pour obtenir le type à virgule flottante. N’utilisez pas un entier avec un pointeur sur son adresse pour faire un typage, car cela enfreindrait les règles d’aliasing C.

Le programme suivant produira un NaN. La deuxième déclaration se traduira par un NaN.

 #include  #include  #include "math.h" int _tmain(int argc, _TCHAR* argv[]) { double dSQRTValue = sqrt( -1.00 ); double dResult = -dSQRTValue; // This statement will result in a NaN. printf( "\n %lf", dResult ); return 0; } 

Ce qui suit sera le résultat du programme.

1. # QNAN0

nan est produit lorsque nous programmons une valeur telle que 0.0 / 0.0, selon @Dan Cecile OR sqrt (-1).