`X! = X` est-il un moyen portable de tester NaN?

En C, vous pouvez tester si un double si NaN utilise isnan(x) . Cependant, de nombreux endroits en ligne, y compris par exemple cette réponse SO déclarent que vous pouvez simplement utiliser x!=x place.

Est-ce que x!=x dans une spécification C est une méthode qui permet de vérifier si x est NaN? Je ne le trouve pas moi-même et j’aimerais que mon code fonctionne avec différents compilateurs.

Veuillez vous reporter à la section normative Annexe F: Arithmétique en virgule flottante CEI 60559 de la norme C:

F.1 Introduction

Une implémentation qui définit __STDC_IEC_559__ doit être conforme aux spécifications de la présente annexe.

Les implémentations qui ne définissent pas __STDC_IEC_559__ ne sont pas tenues de se conformer à ces spécifications.

F.9.3 Opérateurs relationnels

L’expression x ≠ x est vraie si x est un NaN .

L’expression x = x est fausse si X est un Nan .

F.3 Opérateurs et fonctions

La macro isnan dans fournit la fonction isnan recommandée dans l’appendice à la CEI 60559.

NaN en tant que valeur unique x avec la propriété x!=x est une garantie IEEE 754. Savoir si NaN en C est un test fidèle revient à déterminer à quel point la représentation des variables et des opérations est mappée aux formats IEEE 754 et aux opérations du ou des compilateurs que vous souhaitez utiliser.

Vous devriez en particulier vous soucier de la «précision excessive» et de la façon dont les compilateurs s’en occupent. Une précision excessive correspond à ce qui se produit lorsque la FPU prend uniquement en charge les calculs dans un format plus large que celui que le compilateur souhaite utiliser pour les types float et double . Dans ce cas, les calculs peuvent être faits avec une précision plus grande et arrondis à la précision du type lorsque le compilateur en a envie d’une manière imprévisible.

La norme C99 définissait un moyen de gérer cet excès de précision en préservant la propriété que seul NaN était différent de lui-même, mais longtemps après 1999 (et même de nos jours, lorsque les auteurs du compilateur ne s’en soucient pas), en présence d’un excès de précision, x != x peut éventuellement être vrai pour toute variable x contenant le résultat fini d’un calcul, si le compilateur choisit d’arrondir le résultat de précision excessive du calcul entre l’évaluation du premier x et du second x .

Ce rapport décrit les périodes sombres des compilateurs qui n’ont fait aucun effort pour implémenter C99 (soit parce que ce n’était pas encore 1999, soit parce qu’ils ne s’y intéressaient pas assez).

Ce billet de 2008 décrit comment GCC a commencé à mettre en œuvre la norme C99 pour les excès de précision en 2008. Auparavant, GCC pouvait lui fournir toutes les sursockets décrites dans le rapport susmentionné.

Bien sûr, si la plate-forme cible n’implémente pas du tout IEEE 754, une valeur NaN peut même ne pas exister, ou exister et avoir des propriétés différentes de celles spécifiées par IEEE 754. Les cas courants sont un compilateur qui implémente IEEE 754 de manière assez fidèle avec FLT_EVAL_METHOD à 0, 1 ou 2 (qui garantissent tous que x != x xsi x est NaN), ou un compilateur avec une implémentation non standard d’excès de précision, où x != x n’est pas un test fiable pour NaN.