2010-10-08 15 views
10

Piszę kod Python 2.6, który łączy się z NI TestStand 4.2 przez COM w Windows. Chcę utworzyć wartość "NAN" dla zmiennej, ale jeśli przekażę ją float('nan'), TestStand wyświetli ją jako IND.Jak rozróżnić różne typy pływaka NaN w Pythonie

Najwyraźniej w testowej stacji rozróżnia się wartości zmiennoprzecinkowe "IND" i "NAN". Według TestStand help:

  • IND odpowiada sygnalizacji NaN w Visual C++, a
  • NAN odpowiada QuietNaN

sugerujący, że Pythona float('nan') jest faktycznie Sygnalizacja NaN kiedy przeszedł przez COM. Jednak z tego, co przeczytałem na temat Signaling NaN, wydaje się, że Signaling NaN jest nieco "egzotyczny" i Quiet NaN jest twoim "zwykłym" NaN. Mam więc wątpliwości co do tego, że Python będzie przekazywać Signaling NaN do COM. Jak mogę się dowiedzieć, czy Python float('nan') jest przepuszczany przez COM jako sygnalizacji NaN lub Quiet NaN, czy może nieokreślony?

Czy istnieje jakiś sposób, aby Signaling NaN kontra QuietNaN lub nieokreślona w Pythonie, gdy relacje z innymi językami? (Może przy użyciu ctypes?) Zakładam, że byłoby to rozwiązanie specyficzne dla platformy i zaakceptowałbym to w tym przypadku.

Aktualizacja: W edytorze sekwencji TestStand, próbowałem co dwie zmienne, jeden zestaw do NAN a drugi zestaw do IND. Potem zapisałem go do pliku. Następnie otworzyłem plik i odczytałem każdą zmienną za pomocą Pythona. W obu przypadkach Python odczytuje je jako zmienną o wartości nan.

+0

Dlaczego dokładnie chcesz to zrobić? Być może komplikujesz rzeczy. Można użyć NoneType być może ... – JoshD

+0

Chcę ustawić zmienną na 'NAN' (zamiast" IND ") w TestStand, poprzez COM przy użyciu Python. Łatwiej będzie udokumentować użytkownikowi końcowemu, czy możemy konsekwentnie używać 'NAN' w naszym systemie. –

Odpowiedz

6

I wykopali kawałek dla ciebie, i myślę, że może być w stanie korzystać z modułu struct w połączeniu z informacjami na co Kevin's Summary Charts. Wyjaśniają one dokładne wzorce bitowe używane dla różnych rodzajów liczb zmiennoprzecinkowych IEEE 754.

Jedyną rzeczą, którą prawdopodobnie będziesz musiał zachować ostrożność, jeśli przeczytam tematy na tej IND -określonej wartości, jest to, że ta wartość ma tendencję do wywoływania pewnego rodzaju przerwań zmiennoprzecinkowych, gdy jest przypisana bezpośrednio w kodzie C, powodując ich zostać zmienionym na zwykły NaN.Co z kolei oznaczało, że ludziom radzono robić takie rzeczy w ASM, a nie w C, ponieważ C wyrzucił te rzeczy z dala .. Ponieważ nie jest to moja dziedzina i nie jestem pewien w jakim stopniu ten rodzaj wartości Python, pomyślałem, że wspomnę o tym, żebyś mógł przynajmniej zachować oko na takie dziwne zachowanie. (Zobacz akceptowaną odpowiedź na this question).

>>> import struct 

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

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

Nawiązując do Kevin's Summary Charts, który pokazuje, że float('nan') jest rzeczywiście technicznie wartość nieokreślona, ​​podczas scipy.nan jest cichy NaN.

Spróbujmy zrobić sygnalizację NaN, a następnie ją zweryfikować.

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

Nie, sygnalizacyjny NaN zamienia się na cichy NaN.

Teraz spróbujmy dokonać cichego NaN bezpośrednio, a następnie sprawdźmy.

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

Więc to, jak dokonać właściwego Quiet NaN użyciu struct.unpack() --at przynajmniej na platformie Windows.

+0

Dzięki za odpowiedź Stigma. Pozwoliłem sobie na edycję, aby dodać próbki kodu. Bardzo doceniane. –

+0

Cieszę się, że dostałeś to, czego potrzebujesz, i dziękuję za dodanie próbek kodu dla innych, takich jak ja, z których można się uczyć. :) – Stigma

+0

Nice - dzięki. – ars

2

Johna Cooka miał ładny post na to, co może być pomocne:

Aktualizacja: nie będzie tej pracy?

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

Prawdopodobnie zamierzałeś połączyć [tutaj] (http://www.johndcook.com/blog/2009/07/21/ieee-arithmetic-python/). – Stigma

+0

@Stigma: D'oh! Link naprawiony, dziękuję. – ars

+0

To pomocne źródło informacji o NAN i INF w Pythonie. Niestety, nie idzie tak daleko, jak odpowiedzieć na moje pytanie. –

3

definicja CPython od nan

Kiedy Python zgłasza nan, skąd to się wzięło?

  • Wynik obliczeń (wartości konkretnej platformy?)
  • Py_NAN w kodzie źródłowym CPython C
    • zdefiniowany jako (Py_HUGE_VAL * 0.)
      • wartość jest platforma specyficzne
      • Py_HUGE_VAL prawdopodobnie jest zdefiniowany jako HUGE_VAL - ma notatkę, która mówi, że powinna być HUGE_VAL, z wyjątkiem platform, na których jest zepsuta.
  • float('nan') który jest określony z Py_NAN w kodzie źródłowym C CPython'S.

Reading Python i pywin32 kod źródłowy

miałem spojrzeć na kod źródłowy C pywin32, w szczególności win32com, która stanowi warstwę translacji Python↔COM. Że kod:

  • trwa obiektu wejściowego
  • połączeń PyNumber_Float() aby przekształcić go w Pythonie float (jeśli nie jest już)
  • połączeń PyFloat_AsDouble() aby przekształcić go w czystym C wartości double.
    • Po prostu zwraca kod C double bezpośrednio zawarty w składniku PyFloatObjectob_fval.

Tak to wygląda jakbym prześledzić NaN z interfejsu COM z powrotem do zwykłego C double typu zawierającego Py_NAN, cokolwiek to okazuje się być na platformie Windows.

TestStand NAN Wartość

Teraz próbowałem to z NI TestStand. Najpierw próbowałem:

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) 

Ale to jeszcze pojawił się w TestStand jak IND. Tak więc utworzyłem plik TestStand ze zmiennymi ustawionymi na IND i NAN i odczytałem wartości z Pythona. Okazuje się, że TestStand's NAN ma wartość FFFF000000000001. Według Kevin's Summary Charts jest to negatywny cichy NAN. TestStand's IND ma oczekiwaną wartość dla Indeterminate, FFF8000000000000.

Sukces

Więc, mimo wszystko, że udało mi się ustawienie NAN w TestStand, od 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

czy scipy NaN nie działają po przejściu przez COM? – ars

+0

Nie próbowałem jeszcze wypróbować 'scipy.nan' na moim komputerze, na którym działa TestStand. –

+0

@ars, jak pokazałem w mojej zaktualizowanej odpowiedzi, nawet 'scipy.nan' nie działał. "Cichy negatywny NaN" zrobił lewę. –

Powiązane problemy