2017-07-01 15 views
9

Jako pojęcia matematyczne doskonale zdaję sobie sprawę z tego, czym są w rzeczywistości i nan. Ale naprawdę interesuje mnie to, w jaki sposób są one wdrażane w językach programowania.W jaki sposób są wdrażane systemy Inf i NaN?

W Pythonie mogę używać inf i nan w arytmetycznych i warunkowych wyrażeń, takich jak to:

>>> nan = float('nan') 
>>> inf = float('inf') 
>>> 1 + inf 
inf 
>>> inf + inf 
inf 
>>> inf - inf 
nan 

będzie to prowadzić mi uwierzyć, że Python posiada wewnętrznie specjalnego zarezerwowanego sekwencji bitów dla tych dwóch wielkości matematycznych, i żadna inna liczba nie może przyjąć tych pozycji. Czy moje założenie jest poprawne? Czy możesz mnie oświecić w tym względzie?

Jeśli moje założenie jest poprawne, to można wytłumaczyć w prosty sposób:

>>> inf == inf 
True 

to jednak nie jest:

>>> nan == nan 
False 

Oczywiście, w matematyce, to jest prawidłowa odpowiedź. Ale skąd Python wie, że powinien wypluć w tym przypadku False?

Co więcej, w jaki sposób implementacja Pythona różni się od implementacji java lub C++?

+1

Ponieważ instrukcje maszyny zmiennoprzecinkowej dla porównania zwracają wartość false, aby porównać nan z niczym, w tym z samym sobą – camelccc

+9

Jest to związane ze standardem [IEEE 754] (https://en.wikipedia.org/wiki/IEEE_754). –

+1

Prawie wszystkie języki programowania używają IEEE 754 dla wartości zmiennoprzecinkowych, które precyzyjnie określają, czym są te wartości specjalne, jak są reprezentowane i jak zachowują się w różnych operacjach. –

Odpowiedz

7

Zazwyczaj zmiennoprzecinkowych arytmetyka jest realizowana bezpośrednio przez sprzęt. Istnieją rzeczywiście specjalne wzorce bitowe dla nieskończoności i NaN, które są rozpoznawane przez sprzęt zmiennoprzecinkowy.

Liczba 64-bitowych liczb zmiennoprzecinkowych IEEE, w rodzaju używanych w CPython na typowych systemach, ma 1 bit do znaku, 11 bitów do wykładnika i 52 bity do mantysy. Patrz: https://en.wikipedia.org/wiki/Double-precision_floating-point_format

Jeśli wykładnik zawiera 0b11111111111 (wszystkie), to liczba jest albo inf lub nan, w zależności od tego, co jest przechowywane w mantysie. Python nie musi robić nic specjalnego, aby obsłużyć te przypadki. Otrzymasz te same wyniki, niezależnie od tego, czy porównywane są liczby w języku Python, C, Java lub w assemblerze.

+0

Myślę, że warto wspomnieć, że instrukcje sprzętowe do porównywania liczb zmiennoprzecinkowych mają na celu wskazanie, że dwa operandy nie są równe, jeśli jeden z nich jest NaN, nawet jeśli mają one identyczne wzorce bitowe. Pytanie autora sugeruje, że mogą one sądzić, że identyczne wzory bitów muszą koniecznie wskazywać na równość, a przynajmniej nie rozumieją, w jaki sposób identyczne wzorce bitowe można uznać za nie równe. –

+0

Dzięki za odpowiedź. To ma dla mnie sens. –

+0

@EricPostpischil: To nie brzmi w ogóle pożytecznie, aby wspomnieć, to tylko powielenie informacji w twoim komentarzu. Następnym razem, jeśli masz informacje przydatne dla osoby, która zadała pytanie, zaproponuj zmianę lub opublikuj komentarz skierowany do pytającego. –

4

Nie są to zachowania specyficzne dla Pythona, ale raczej standardowe użycie Pythona zmiennoprzecinkowego (i prawdopodobnie wszystkie popularne języki?).

nan i inf są specjalną wartością standardu zmiennoprzecinkowego IEEE_754. Posiadają wewnętrzne reprezentacje (sekwencja bitów, o której wspomniałeś), ale ich zachowanie nie jest typowe. Zachowanie nie jest typowe w przypadku innych wartości pływających, ale jest dobrze zdefiniowane przez IEEE_754. Implementacja odbywa się na poziomie instrukcji. (Procesor obsługuje to w zespole jednostek zmiennoprzecinkowych)

Jedno określone i nietrywialne zachowanie, NaN! = Wszystko, łącznie z samym sobą.

Wiedząc, że można napisać coś takiego:

def isNaN(f): return f != f 
Powiązane problemy