web-dev-qa-db-fra.com

Quels sont tous les calculs possibles qui pourraient provoquer un NaN en Python?

J'ai cherché autour, et il semble y avoir des discussions dispersées sur NaNs dans différents langages de programmation, y compris certains cas spécifiques, mais rien d'exhaustif ou clair.

Quelles sont les opérations les plus courantes qui provoqueraient un NaN, en Python, qui se produit en travaillant avec NumPy ou SciPy?

53
user961627

Si vous effectuez l'une des opérations suivantes sans tourner autour de l'environnement à virgule flottante, vous devriez obtenir un NaN là où vous n'en aviez pas auparavant:

  • 0/0 (Soit signe en haut et en bas)
  • inf/inf (Soit signe en haut et en bas)
  • inf - inf Ou (-inf) + inf Ou inf + (-inf) ou (-inf) - (-inf)
  • 0 * inf Et inf * 0 (L'un ou l'autre signe sur les deux facteurs)
  • sqrt(x) lorsque x < 0
  • fmod(x, y) lorsque y = 0 ou x est infini; ici fmod est un reste à virgule flottante.

La référence canonique pour ces aspects de l'arithmétique des machines est la spécification IEEE 754 . La section 7.1 décrit l'exception d'opération non valide, qui est celle qui est déclenchée lorsque vous êtes sur le point d'obtenir un NaN. "Exception" dans IEEE 754 signifie quelque chose de différent de ce qu'il fait dans un contexte de langage de programmation.

De nombreuses implémentations de fonctions spéciales documentent leur comportement aux singularités de la fonction qu'elles essaient d'implémenter. Voir la page de manuel pour atan2 Et log, par exemple.

Vous posez des questions spécifiques sur NumPy et SciPy. Je ne sais pas si c'est simplement pour dire "je pose des questions sur l'arithmétique de la machine qui se passe sous le capot dans NumPy" ou "je pose des questions sur eig() et tout ça". Je suppose que le premier, mais le reste de cette réponse essaie de faire un vague lien avec les fonctions de niveau supérieur dans NumPy. La règle de base est: Si l'implémentation d'une fonction commet l'un des péchés ci-dessus, vous obtenez un NaN.

Pour fft, par exemple, vous êtes susceptible d'obtenir NaNs si vos valeurs d'entrée sont autour de 1e1010 Ou plus et une perte de précision silencieuse si vos valeurs d'entrée sont autour de 1e-1010 Ou plus petit. Mis à part les entrées vraiment ridiculement mises à l'échelle, cependant, vous êtes assez en sécurité avec fft.

Pour les choses impliquant des mathématiques matricielles, les NaN peuvent apparaître (généralement via la route inf - inf) Si vos nombres sont énormes ou votre matrice est extrêmement mal conditionnée. Une discussion complète sur la façon de se faire défoncer par l'algèbre linéaire numérique est trop longue pour figurer dans une réponse. Je suggère de parcourir un livre d'algèbre linéaire numérique (Trefethen et Bau est populaire) au cours de quelques mois à la place.

Une chose que j'ai trouvée utile lors de l'écriture et du débogage de code qui "ne devrait pas" générer de NaN est de dire à la machine d'intercepter si un NaN se produit. Dans GNU C, je fais ceci:

#include <fenv.h>
feenableexcept(FE_INVALID);
55
tmyklebu