web-dev-qa-db-fra.com

Pourquoi NaN (pas un nombre) n'est-il disponible que pour les doubles?

J'ai une classe affaires qui contient deux propriétés décimales nullables. Une troisième propriété renvoie le résultat de la multiplication des deux autres propriétés. Si HasValue est vrai pour les deux types nullables, je multiplie et retourne le résultat. J'ai quelques options pour la valeur de retour si l'une des propriétés ou les deux sont nulles:

  • Retour 0
  • Jetez une exception
  • Renvoie un nombre magique (-1)
  • Retour décimal? (EDIT - voir commentaires)

Je pensais qu'une de mes options serait de retourner NaN, mais je vois que cela n'est possible que pour le type double. Pourquoi est-ce?

Pour mémoire, retourner 0 est le plus logique dans ce cas et c'est ce que je prévois de faire à moins que quelqu'un ait une meilleure suggestion.

45
Jamie Ide

Types intégraux dans .Net Utilisez le système du complément à deux pour la représentation. Bien qu'ils puissent réserver certains modèles de bits pour des valeurs spéciales, ils ont choisi de ne pas le faire. double et float utilisent un système de représentation complètement différent (IEEE 754) qui réserve des modèles de bits spéciaux pour NaN, + Infinity, -Infinity, ...

L'une des raisons pour lesquelles les valeurs NaN et Infinity ont plus de sens pour l'arithmétique à virgule flottante est que les opérations peuvent entraîner une division par zéro, non seulement parce que le diviseur est en fait zéro, mais parce qu'il est trop petit pour être représenté par le type. Par conséquent, si ce n'était pas le cas, vous pourriez avoir un calcul valide, mystérieusement jeter une exception de division par zéro. Cela ne se produira pas pour les types int car ils sont exacts et n'ont pas d'erreur de précision.

decimal est conçu pour être utilisé pour les nombres à virgule décimale "réels". Il est rarement soumis à des calculs que double et float sont conçus pour faire. Qu'est-ce que NaN exprimerait pour un nombre réel?

Laissant les raisons derrière lui, c'est ce que c'est et nous ne pouvons rien y faire, donc la meilleure voie à suivre est d'utiliser des types nullables (ils sont conçus pour aider exactement avec ce genre de situation). C'est la bonne façon de résoudre ce problème. Si vous ne voulez pas faire cela (et les exceptions n'ont pas de sens), vous devez recourir à la solution du nombre magique. Si vous avez choisi de le faire, assurez-vous simplement qu'il est en dehors du domaine des résultats valides.

EDIT (idée fausse très courante sur la décimale):

Comme également noté par MSDN , decimal n'est pas un point fixe. C'est un nombre à virgule flottante:

Un nombre décimal est une valeur à virgule flottante qui se compose d'un signe, d'une valeur numérique où chaque chiffre de la valeur varie de 0 à 9 et d'un facteur d'échelle qui indique la position d'une virgule décimale flottante qui sépare les parties intégrale et fractionnaire. de la valeur numérique.

41
Mehrdad Afshari