Question

Est-il judicieux d’utiliser NaN à virgule flottante IEEE754 pour les valeurs non définies pour des raisons non mathématiques?

Dans notre cas, ils ne sont pas encore définis car les valeurs n’ont pas été reçues par un autre périphérique. Le contexte est un système intégré utilisant les valeurs IEC1131 REAL32. Modifier : le langage de programmation est le langage C; nous utiliserons donc probablement NAN et isnanf (x), qui sont issus de C99. Nous aurons peut-être besoin de contorsions supplémentaires pour les intégrer dans notre couche de compatibilité de système d’exploitation.

Dans les langages de programmation, le choix par défaut semble être d’initialiser les variables à virgule flottante avec un zéro positif, dont la représentation interne est constituée de zéros. Cela ne nous est pas utilisable, car 0 se situe dans la plage des valeurs valides.

Cela ressemble à une solution propre d’utiliser NaN, mais c’est peut-être plus compliqué que cela ne vaut la peine et nous devrions choisir une autre valeur?

Était-ce utile?

La solution

Je viens de remarquer cette question.

C’est l’une des utilisations de NaN que le comité IEEE 754 a à l’esprit (j’étais membre du comité). Les règles de propagation pour les NaN en arithmétique rendent cela très attrayant, car si vous avez le résultat d’une longue séquence de calculs qui implique des données initialisées, vous ne confondrez pas le résultat avec un résultat valide. Il peut également faciliter le suivi des calculs pour trouver où vous utilisez les données initialisées beaucoup plus simplement.

Cela dit, le comité de 754 n'a aucun contrôle sur quelques écueils: comme d'autres l'ont souligné, tout le matériel ne prend pas en charge les valeurs NaN à la vitesse, ce qui peut entraîner des problèmes de performances. Heureusement, on n’effectue souvent pas beaucoup d’opérations sur des données initialisées dans un contexte de performances critiques.

Autres conseils

Les NaN sont un choix raisonnable pour un signal de signalisation «aucune valeur» (le langage de programmation D les utilise pour les valeurs non initialisées, par exemple), mais comme toute comparaison les impliquant est fausse, vous pouvez vous attendre à quelques surprises:

  • if (result == DEFAULT_VALUE) , ne fonctionnera pas comme prévu si DEFAULT_VALUE est NaN, comme l'a mentionné Jon.

  • Ils peuvent également causer des problèmes de vérification de la plage si vous ne faites pas attention. Considérez la fonction:

bool isOutsideRange(double x, double minValue, double maxValue)
{
    return x < minValue || x > maxValue;
}

Si x est NaN, cette fonction signalera à tort que x est compris entre minValue et maxValue.

Si vous voulez juste une valeur magique à tester pour les utilisateurs, je recommanderais l'infini positif ou négatif au lieu de NaN, car il ne vient pas avec les mêmes pièges. Utilisez NaN lorsque vous le souhaitez, pour que ses opérations aboutissent à un NaN: utile lorsque vous ne souhaitez pas que les appelants vérifient la valeur, par exemple.

[Éditer: j'ai initialement réussi à taper "toutes les comparaisons les impliquant seront vraies" ci-dessus, ce qui n'est pas ce que je voulais dire et qui est faux, ils sont tous faux, à l'exception de NaN! = NaN, ce qui est vrai]

J’ai utilisé des NaN dans des situations similaires simplement à cause de cela: la valeur d’initialisation par défaut habituelle 0 est également une valeur valide. NaNs fonctionne bien jusqu'à présent.

En passant, c’est une bonne question de savoir pourquoi la valeur d’initialisation par défaut est généralement (par exemple, dans les types primitifs Java) 0 et non NaN. Ne pourrait-il pas aussi bien être 42 ou autre chose? Je me demande quelle est la raison d'être des zéros.

Je pense que c'est une mauvaise idée en général. Une chose à garder à l'esprit est que la plupart des processeurs traitent Nan beaucoup plus lentement que "d'habitude". flotte. Et il est difficile de garantir que vous n'aurez jamais Nan dans les paramètres habituels. D'après mon expérience en informatique numérique, cela crée souvent plus de problèmes que ce n'en vaut la peine.

La bonne solution consiste à éviter de coder "absence de valeur". dans le flotteur, mais pour le signaler d'une autre manière. Ce n'est pas toujours pratique, cependant, cela dépend de votre base de code.

Faites attention avec les NaN… ils peuvent se répandre comme une traînée de poudre si vous ne faites pas attention.

Elles constituent une valeur parfaitement valide pour les floats, mais toutes les assignations les impliquant seront également égales à NaN, elles se propagent donc dans votre code. C’est un très bon outil de débogage si vous l’attrapez, mais cela peut aussi être une véritable gêne si vous apportez quelque chose à libérer et qu’il existe un cas marginal quelque part.

D utilise cela comme justification pour donner les flottants NaN par défaut. (Avec lequel je ne suis pas sûr d'être d'accord)

Mes sentiments sont que c'est un peu hacky, mais au moins tous les autres nombres que vous faites avec cette valeur NaN donne NaN comme résultat - quand vous voyez un NaN dans un rapport de bogue, au moins vous savez quel type d'erreur vous êtes chasse.

Si votre besoin fondamental est d’avoir une valeur à virgule flottante qui ne représente aucun nombre qui aurait pu être reçu de l’appareil, et si l’appareil garantit qu’il ne retournera jamais NaN, cela me semble raisonnable.

N'oubliez pas que, selon votre environnement, vous avez probablement besoin d'un moyen spécial de détecter les NaN (n'utilisez pas si (x == float.NaN) ou quel que soit votre équivalent.)

Cela me semble une bonne utilisation des nans. J'aurais aimé y penser ...

Bien sûr, ils sont supposés se propager comme un virus, voilà le problème.

Je pense que j'utiliserais nan au lieu d'un des infinis. Il peut être intéressant d’utiliser un nanomètre de signalisation et de le laisser provoquer un événement lors de la première utilisation, mais il est trop tard pour qu’il devienne silencieux lors de la première utilisation.

Utiliser NaN comme valeur par défaut est raisonnable.

Notez que certaines expressions, telles que (0.0 / 0.0), renvoient NaN.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top