2010-10-08 8 views
10

Sto scrivendo il codice Python 2.6 che si interfaccia con NI TestStand 4.2 tramite COM in Windows. Voglio fare un valore "NAN" per una variabile, ma se lo passo float('nan'), TestStand lo visualizza come IND.Come distinguere i diversi tipi di float NaN in Python

Apparentemente TestStand distingue tra valori in virgola mobile "IND" e "NAN". Secondo TestStand help:

  • IND corrisponde a Segnalazione NaN in Visual C++, mentre
  • NAN corrisponde a QuietNaN

Ciò implica che Python float('nan') è effettivamente un Signaling NaN quando passato attraverso COM. Tuttavia, da quello che ho letto su Segnalazione NaN, sembra che Segnalazione NaN è un po ' "esotico" e Tranquillo NaN è la vostra nan "regolare". Quindi ho i miei dubbi sul fatto che Python passerebbe un Segnalazione NaN tramite COM. Come potrei scoprire se un Python float('nan') viene fatta passare attraverso COM come Signaling NaN o Tranquillo NaN, o forse indeterminato?

C'è un modo per fare un Signaling NaN contro QuietNaN o indeterminato in Python, quando ci si interfaccia con altri linguaggi? (Utilizzando ctypes forse?) Suppongo che questa sarebbe una soluzione specifica per la piattaforma, e accetterei che in questo caso.

Aggiornamento: Nell'editor sequenza di TestStand, ho provato a fare due variabili, un set per NAN e l'altro insieme a IND. Quindi l'ho salvato su un file. Quindi ho aperto il file e letto ogni variabile usando Python. In entrambi i casi, Python li legge come float nan.

+0

Perché proprio vuoi fare questo? Potresti finire per complicare le cose. Potresti usare un NoneType, forse ... – JoshD

+0

Voglio impostare una variabile su 'NAN' (piuttosto che su' IND') in TestStand, tramite COM usando Python. Sarà più facile documentare per l'utente finale se possiamo usare costantemente 'NAN' nel nostro sistema. –

risposta

6

ho scavato un po 'per te, e penso che si potrebbe essere in grado di utilizzare il modulo struct in combinazione con le informazioni sul a Kevin's Summary Charts. Spiegano i pattern di bit esatti usati per i vari tipi di numeri in virgola mobile IEEE 754.

L'unica cosa che probabilmente dovrà fare attenzione perché, se ho letto gli argomenti su questo IND valore -eterminate, è che tale valore tende a innescare una sorta di punto di interruzione mobile quando assegnato direttamente nel codice C, provocando la essere trasformato in un semplice NaN.Il che a sua volta significava che a quelle persone veniva consigliato di fare questo genere di cose in ASM piuttosto che in C da quando C ha distrutto quella roba .. Dal momento che non è il mio campo, e che non sono sicuro di quale misura questo tipo di valore potrebbe confondere Python, ho pensato di menzionarlo così puoi almeno tenere d'occhio qualsiasi comportamento strano. (Vedere la risposta accettata per this question).

>>> import struct 

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

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

Facendo riferimento alla Kevin's Summary Charts, che dimostra che float('nan') è in realtà tecnicamente il valore indeterminato, mentre scipy.nan è un NaN silenzioso.

Proviamo a creare un NaN di segnalazione, quindi a verificarlo.

>>> 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, il NaN di segnalazione viene convertito in un NaN silenzioso.

Ora proviamo a creare direttamente un NaN silenzioso, quindi 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' 

Ecco come fare una corretta Tranquillo NaN usando struct.unpack() --at almeno, su una piattaforma Windows.

+0

Grazie per la tua risposta Stigma. Mi sono preso la libertà di modificarlo per aggiungere esempi di codice. Molto apprezzato. –

+0

Sono contento che tu ne sia uscito ciò di cui avevi bisogno, e grazie per aver aggiunto i campioni di codice per gli altri come me. :) – Stigma

+0

Nice - grazie. – ars

2

John Cook aveva un bel post su questo che potrebbe essere utile:

Aggiornamento: non sarà questo lavoro?

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

Probabilmente intendevi collegare [qui] (http://www.johndcook.com/blog/2009/07/21/ieee-arithmetic-python/). – Stigma

+0

@Stigma: D'oh! Link risolto, grazie. – ars

+0

Questo è un utile riferimento per l'apprendimento di NAN e INF in Python. Sfortunatamente, non arriva al punto di rispondere alla mia domanda. –

3

definizione CPython di nan

Quando Python segnala un nan, dove che viene?

  • risultato di un calcolo (valori specifici di piattaforma?)
  • Py_NAN nel codice sorgente CPython C
    • definito come (Py_HUGE_VAL * 0.)
      • valore è
      • Py_HUGE_VAL è probabilmente definito come specifico per la piattaforma HUGE_VAL - ha una nota per dire che dovrebbe essere HUGE_VAL tranne su piattaforme in cui è rotto.
  • float('nan') che è definito da Py_NAN nel codice sorgente C di CPython.

lettura Python e pywin32 codice sorgente

ho avuto uno sguardo al codice sorgente C per pywin32, in particolare win32com, che forma lo strato di traduzione Python↔COM. Tale codice:

  • prende l'oggetto di input
  • chiamate PyNumber_Float() per convertirlo in un Python float (se non è già)
  • chiamate PyFloat_AsDouble() per convertirlo in un double valore normale C.
    • Questo semplicemente restituisce il C double direttamente contenuto nel membro PyFloatObjectob_fval.

in modo che appaia come se ho tracciato un NaN dall'interfaccia COM torna a una pianura di tipo C double contenente Py_NAN, qualunque cosa che si rivela essere sulla piattaforma Windows.

TestStand NAN Valore

Ora Ho provato questo con NI TestStand. Per prima cosa ho provato:

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) 

ma che ancora apparso in TestStand come IND. Quindi ho creato un file TestStand con le variabili impostate su IND e NAN e leggendo i valori da Python. Si scopre che NAN di TestStand ha un valore di FFFF000000000001. In base al numero Kevin's Summary Charts ovvero a negativo NAN silenzioso. IND di TestStand ha il valore previsto per Indeterminato, FFF8000000000000.

Successo

Quindi, dopo tutto questo, sono riuscito a impostare un NAN in TestStand, da 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

i NaNs scipy non funzionano quando sono passati attraverso COM? – ars

+0

Non ho ancora provato 'scipy.nan' sul mio computer che esegue TestStand. –

+0

@ars, come ho mostrato nella mia risposta aggiornata, anche 'scipy.nan' non funzionerebbe. Un "NaN negativo tranquillo" ha fatto il trucco. –