Question

Je vous écris du code Python 2.6 que les interfaces avec NI TestStand 4.2 via COM sous Windows. Je veux faire une valeur « NAN » pour une variable, mais si je le passe float('nan'), affiche TestStand en tant que IND.

Apparemment, TestStand établit une distinction entre virgule flottante « IND » et les valeurs « nan ». Selon TestStand aide :

  • IND correspond à NAN de signalisation dans Visual C ++, alors que
  • NAN correspond à QuietNaN

Cela implique que la float('nan') Python est effectivement un NAN de signalisation lorsqu'il est passé par COM. Cependant, de ce que j'ai lu NAN de signalisation , il semble que NAN de signalisation est un peu "exotique" et NaN silencieux est votre " « NaN régulière. J'ai donc mes doutes que Python serait passer un NAN de signalisation par COM. Comment pourrais-je savoir si un float('nan') Python est passé à travers COM comme Signaling NaN ou Quiet NaN , ou peut-être indéterminés ?

Est-il possible de faire une NAN de signalisation contre QuietNaN ou indéterminés en Python, lors de l'interfaçage avec d'autres langues? (L'utilisation ctypes peut-être?) Je suppose que ce serait une solution spécifique à la plateforme, et j'accepter que dans ce cas.

Mise à jour: Dans l'éditeur de séquence TestStand, j'ai essayé de faire deux variables, un ensemble à NAN et l'autre ensemble à IND. Ensuite, je l'ai enregistré dans un fichier. Ensuite, j'ai ouvert le fichier et lu chaque variable en utilisant Python. Dans les deux cas, Python les lit comme un flotteur nan.

Était-ce utile?

La solution

Je creusé un peu pour vous, et je pense que vous pourriez être en mesure d'utiliser le module de struct en combinaison avec les informations sur Classements Résumé de Kevin . Ils expliquent les motifs de bits exacts utilisés pour les différents types de nombres à virgule flottante IEEE 754.

La seule chose que vous aurez probablement être prudent car, si je lis les sujets de cette valeur IND-eterminate, est que cette valeur a tendance à déclencher une sorte d'interruption de virgule flottante lorsque affecté directement dans le code C, l'amenant à être transformé en une plaine NaN. Ce qui voulait dire ces gens ont été invités à faire ce genre de chose en ASM plutôt que C puisque C abstraire ce genre de choses loin .. Comme il n'est pas mon domaine, et que je ne suis pas sûr à quel point ce genre de valeur altérerait avec Python, je me suis dit que je vous signale que vous pouvez au moins garder un oeil pour un tel comportement bizarre. (Voir la réponse acceptée pour cette question ).

>>> import struct

>>> struct.pack(">d", float('nan')).encode("hex_codec")
'fff8000000000000'

>>> import scipy
>>> struct.pack(">d", scipy.nan).encode("hex_codec")
'7ff8000000000000'

Classements Résumé de Kevin , qui montre que float('nan') est en fait techniquement la valeur indéterminés, tandis que scipy.nan est un endroit calme NaN.

L'essai Let faire un NAN de signalisation, puis le vérifier.

>>> try_signaling_nan = struct.unpack(">d", "\x7f\xf0\x00\x00\x00\x00\x00\x01")[0]
>>> struct.pack(">d", try_signaling_nan).encode("hex_codec")
'7ff8000000000001'

Non, le NAN de signalisation est converti en un NaN silencieux.

Maintenant, nous allons essayer de faire un NaN calme directement, puis le vérifier.

>>> try_quiet_nan = struct.unpack(">d", "\x7f\xf8\x00\x00\x00\x00\x00\x00")[0]
>>> struct.pack(">d", try_quiet_nan).encode("hex_codec")
'7ff8000000000000'

Alors que comment faire un bon calme NaN en utilisant struct.unpack() -. Au moins, sur une plate-forme Windows

Autres conseils

définition CPython de nan

Lorsque Python fait état d'un nan, où cela vient?

  • résultat d'un calcul (valeurs de la plate-forme spécifiques?)
  • Py_NAN dans le code source CPython C
    • défini comme (Py_HUGE_VAL * 0.)
      • La valeur est spécifique à la plateforme
      • Py_HUGE_VAL est probablement définie comme HUGE_VAL -. Il a une note pour dire qu'il devrait être HUGE_VAL sauf sur les plates-formes où qui est cassé
  • float('nan') qui est définie à partir de Py_NAN dans le code source de CPython C.

Lecture Python et pywin32 code source

J'ai eu un coup d'oeil au code source C pour pywin32, en particulier win32com, qui forme la couche de traduction Python↔COM. Ce code:

  • prend l'objet d'entrée
  • appelle PyNumber_Float() pour le convertir en un float Python (si elle est pas déjà)
  • appels PyFloat_AsDouble() pour le convertir en une valeur de C double ordinaire.
    • Ceci retourne simplement le C double contenu directement dans l'élément de PyFloatObject ob_fval.

Il semble donc que j'ai tracé un NaN depuis l'interface COM retour à un type C double plaine contenant Py_NAN, quoi que se révèle être sur la plate-forme Windows.

TestStand NAN Valeur

Maintenant, je l'ai essayé avec NI TestStand. D'abord, j'ai essayé:

quiet_nan = struct.unpack(">d", "\x7f\xf8\x00\x00\x00\x00\x00\x01")[0]
# Set the variable's value in TestStand
locals_prop_object.SetValNumber(var_name, 0, quiet_nan)

Mais qui est apparu encore TestStand comme IND. Donc, je créé un fichier TestStand avec les variables définies IND et NAN, et lire les valeurs de Python. Il se trouve que le NAN de TestStand a une valeur de FFFF000000000001. Selon Classements Résumé de Kevin est négatif NaN silencieux. Le IND de TestStand n'ont la valeur attendue pour indéterminés , FFF8000000000000.

Succès

Alors, après tout cela, je l'ai réussi à mettre un NAN dans TestStand, de Python:

# Make a NAN suitable for TestStand
teststand_nan = struct.unpack(">d", "\xff\xff\x00\x00\x00\x00\x00\x01")[0]
# Set the variable's value in TestStand
locals_prop_object.SetValNumber(var_name, 0, teststand_nan)

John Cook avait un poste bien sur ce qui pourrait être utile:

Mise à jour : ne sera pas ce travail

In [144]: import scipy

In [145]: scipy.nan
Out[145]: 1.#QNAN

In [146]: scipy.inf
Out[146]: 1.#INF

In [147]: scipy.inf * 0
Out[147]: -1.#IND

D'après ce que je comprends, il semble qu'il y ait une certaine confusion à penser que le signe d'un NaN détermine si oui ou non il est calme. Au contraire, la convention est que le bit le plus significatif de la mantisse détermine cela. De Wikipédia (italique ajouté):

  

Dans IEEE 754 conformes au standard des formats de stockage à virgule flottante, NaN sont identifiés par spécifiques, des motifs de bits prédéfinis propres à NaN. Le bit de signe n'a pas d'importance . NaN au format binaire sont représentés avec le champ exponentielle rempli de ceux (comme les valeurs de l'infini), et un nombre non nul dans le champ significand (les distinguent des valeurs de l'infini). L'original norme IEEE 754 de 1985 (IEEE 754-1985) décrit seulement binaire des formats à virgule flottante, et ne précise pas comment l'état de signalisation / quiet devait être étiqueté. En pratique, le bit le plus significatif du champ de significand déterminer si un NaN est signalisation ou calme ... La révision de la norme IEEE 754 2008 (IEEE 754-2008) formule des recommandations formelles pour le codage de l'état de signalisation / quiet. Pour les formats binaires, le bit le plus significatif du champ significand devrait être un drapeau « is_quiet ». C'est à dire. ce bit est non nul si le NaN est calme, et zéro si le NaN signale .

Étant donné que la plupart des implémentations sont IEEE 754-2008 conforme, c'est la convention que vous devez suivre. En général, vous ne pouvez pas planifier sur le bit de signe étant cohérent pour NaN, même pour différentes NaN sur la même plate-forme. En vertu de cette convention, float('nan') et scipy.nan semblent tous deux être NaN calme, au moins dans les cas évoqués ci-dessus.

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