2010-10-08 21 views
10

Estoy escribiendo el código Python 2.6 que se conecta con NI TestStand 4.2 a través de COM en Windows. Quiero hacer un valor "NAN" para una variable, pero si lo paso float('nan'), TestStand lo muestra como IND.Cómo distinguir diferentes tipos de flotador NaN en Python

Aparentemente TestStand distingue entre los valores de coma flotante "IND" y "NAN". De acuerdo con TestStand help:

  • IND corresponde a señalización NaN en Visual C++, mientras que
  • NAN corresponde a QuietNaN

Eso implica que Python de float('nan') es efectivamente un señalización NaN cuando pasó a través de COM. Sin embargo, por lo que he leído sobre Signaling NaN, parece que Signaling NaN es un poco "exótico" y Quiet NaN es su NaN "normal". Así que tengo mis dudas de que Python estaría pasando un Signaling NaN a través de COM. ¿Cómo podría saber si un pitón float('nan') se pasa a través de COM como señalización NaN o Quiet NaN, o tal vez indeterminado?

¿Hay alguna manera de hacer una señalización NaN frente QuietNaN o indeterminado en Python, al interactuar con otras lenguas? (¿Usando ctypes quizás?) Supongo que esta sería una solución específica de la plataforma, y ​​lo aceptaría en este caso.

Actualización: En el editor de secuencias de TestStand, he intentado hacer dos variables, un conjunto a NAN y el otro conjunto de IND. Luego lo guardé en un archivo. Luego abrí el archivo y leí cada variable usando Python. En ambos casos, Python los lee como un flotador nan.

+0

Por qué es exactamente lo que quiere hacer esto? Puede estar complicando las cosas. Podría usar un NoneType quizás ... – JoshD

+0

Quiero establecer una variable para 'NAN' (en lugar de' IND') en TestStand, a través de COM usando Python. Será más fácil documentar para el usuario final si podemos usar consistentemente 'NAN' en todo nuestro sistema. –

Respuesta

6

cavé un poco para ti, y creo que podría ser capaz de utilizar el módulo struct en combinación con la información sobre al Kevin's Summary Charts. Explican los patrones de bits exactos utilizados para los diversos tipos de números de punto flotante IEEE 754.

Lo único que probablemente tenga que tener cuidado, si leo los temas en este IND -eterminate value, es que ese valor tiende a desencadenar algún tipo de interrupción de punto flotante cuando se asigna directamente en código C, causando ser convertido en un NaN simpleLo que a su vez significaba que a esas personas se les aconsejaba hacer este tipo de cosas en ASM en vez de en C, ya que C abstraía esas cosas. Ya que no es mi campo, y no estoy seguro en qué medida este tipo de valor interferiría Python, pensé que lo mencionaría para que al menos puedas mantener un ojo para cualquier comportamiento tan extraño. (Consulte la respuesta aceptada para this question).

>>> import struct 

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

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

Haciendo referencia a Kevin's Summary Charts, que muestra que float('nan') es en realidad técnicamente el valor indeterminado, mientras scipy.nan es un NaN Quiet.

Probemos haciendo un NaN de señalización y luego verifiquemos.

>>> 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' 

No, el NaN de señalización se convierte en un NaN silencioso.

Ahora intentemos hacer un NaN silencioso directamente, y luego verificarlo.

>>> 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' 

Así que eso es cómo hacer un Mudas NaN usando struct.unpack() -al menos, en una plataforma Windows.

+0

Gracias por su respuesta Estigma. Me he tomado la libertad de editarlo para agregar ejemplos de código. Muy apreciado. –

+0

Me alegra que hayas sacado lo que necesitabas, y gracias por agregar ejemplos de código para que otros como yo aprendan de él. :) – Stigma

+0

Niza - gracias. – ars

2

John Cook tenía un buen puesto en este que podría ser útil:

Actualización: no este trabajo?

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 
+0

Probablemente intentó vincular [aquí] (http://www.johndcook.com/blog/2009/07/21/ieee-arithmetic-python/). – Stigma

+0

@Stigma: D'oh! Enlace fijo, gracias. – ars

+0

Esa es una referencia útil para aprender sobre NAN e INF en Python. Lamentablemente, no llega a responder mi pregunta. –

3

definición de CPython nan

Cuando Python reporta un nan, donde viene eso?

  • resultado de un cálculo (valores específicos de la plataforma?)
  • Py_NAN en el código fuente CPython C
    • definido como (Py_HUGE_VAL * 0.)
      • El valor es específico de la plataforma
      • Py_HUGE_VAL es, probablemente, definido como HUGE_VAL --tiene una nota para decir que debe ser HUGE_VAL excepto en las plataformas donde eso está roto.
  • float('nan') que se define a partir de Py_NAN en el código fuente C de CPython.

lectura Python y Código Fuente pywin32

he tenido un vistazo al código fuente C para pywin32, en particular, win32com, que forma la capa de traducción Python↔COM. Ese código:

  • toma el objeto de entrada
  • llamadas PyNumber_Float() para convertirlo en un pitón float (si no lo está ya)
  • llamadas PyFloat_AsDouble() para convertirlo en un valor double C plano.
    • Esto simplemente devuelve el C double contenido directamente en el miembro PyFloatObjectob_fval.

por lo que parece como si hubiera trazado una NaN desde la interfaz COM de nuevo a una llanura de tipo C que contiene doublePy_NAN, lo que resulta ser en la plataforma Windows.

TestStand NAN Valor

Ahora he intentado esto con NI TestStand. Primero probé:

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) 

Pero que todavía apareció en TestStand como IND. Entonces creé un archivo TestStand con las variables establecidas en IND y NAN, y leí los valores de Python. Resulta que TestStand's NAN tiene un valor de FFFF000000000001. De acuerdo con Kevin's Summary Charts que es un negativo NAN silencioso. TestStand's IND tiene el valor esperado para Indeterminado, FFF8000000000000.

éxito

Así que, después de todo eso, he tenido éxito en el establecimiento de un NAN en TestStand, desde 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) 
+0

¿No funcionó el NaN scipy cuando pasó a través de COM? – ars

+0

Todavía no intenté 'scipy.nan' en mi computadora que ejecuta TestStand. –

+0

@ars, como he demostrado en mi respuesta actualizada, incluso 'scipy.nan' no funcionaría. Un "NaN negativo y silencioso" fue el truco. –

Cuestiones relacionadas