W większości języków programowania liczby zmiennoprzecinkowe są podobne do notacji naukowej : z wykładnikiem wykładniczym i mantysą (zwaną także znaczeniem). Powiedzmy 9.2
, że bardzo prosta liczba to właściwie ułamek:
5179139571476070 * 2 -49
Gdzie jest wykładnik -49
i mantysa 5179139571476070
. Nie można przedstawić w ten sposób niektórych liczb dziesiętnych, ponieważ wykładnik i mantysa muszą być liczbami całkowitymi. Innymi słowy, wszystkie zmiennoprzecinkowe muszą być liczbą całkowitą pomnożoną przez liczbę całkowitą równą 2 .
9.2
może być po prostu 92/10
, ale 10 nie może być wyrażone jako 2 n, jeżeli n jest ograniczone do wartości całkowitych.
Widząc dane
Najpierw kilka funkcji, aby zobaczyć komponenty, które tworzą wersje 32- i 64-bitowe float
. Przejrzyj je, jeśli zależy ci tylko na wynikach (przykład w Pythonie):
def float_to_bin_parts(number, bits=64):
if bits == 32: # single precision
int_pack = 'I'
float_pack = 'f'
exponent_bits = 8
mantissa_bits = 23
exponent_bias = 127
elif bits == 64: # double precision. all python floats are this
int_pack = 'Q'
float_pack = 'd'
exponent_bits = 11
mantissa_bits = 52
exponent_bias = 1023
else:
raise ValueError, 'bits argument must be 32 or 64'
bin_iter = iter(bin(struct.unpack(int_pack, struct.pack(float_pack, number))[0])[2:].rjust(bits, '0'))
return [''.join(islice(bin_iter, x)) for x in (1, exponent_bits, mantissa_bits)]
Za tą funkcją kryje się duża złożoność i wyjaśnienie byłoby dość styczne, ale jeśli jesteś zainteresowany, ważnym zasobem dla naszych celów jest moduł struct .
Python float
jest 64-bitową liczbą o podwójnej precyzji. W innych językach, takich jak C, C ++, Java i C #, podwójna precyzja ma osobny typ double
, który często jest implementowany jako 64 bity.
Kiedy wywołujemy tę funkcję w naszym przykładzie 9.2
, oto, co otrzymujemy:
>>> float_to_bin_parts(9.2)
['0', '10000000010', '0010011001100110011001100110011001100110011001100110']
Interpretacja danych
Zobaczysz, że podzieliłem wartość zwracaną na trzy składniki. Te elementy to:
- Znak
- Wykładnik potęgowy
- Mantissa (zwana także Znaczeniem lub Frakcją)
Znak
Znak jest przechowywany w pierwszym składniku jako pojedynczy bit. Łatwo to wytłumaczyć: 0
oznacza, że liczba zmiennoprzecinkowa jest liczbą dodatnią; 1
oznacza, że jest negatywny. Ponieważ 9.2
jest dodatnia, naszą wartością znaku jest 0
.
Wykładnik potęgowy
Wykładnik jest przechowywany w środkowym składniku jako 11 bitów. W naszym przypadku 0b10000000010
. W systemie dziesiętnym oznacza to wartość 1026
. Dziwactwo tego elementu polega na tym, że musisz odjąć liczbę równą 2 (liczba bitów) - 1 - 1, aby uzyskać prawdziwy wykładnik; w naszym przypadku oznacza to odejmowanie 0b1111111111
(liczba dziesiętna 1023
), aby uzyskać prawdziwy wykładnik 0b00000000011
(liczba dziesiętna 3).
Mantissa
Mantysa jest przechowywana w trzecim składniku jako 52 bity. Jednak ten element ma również dziwactwo. Aby zrozumieć to dziwactwo, weź pod uwagę liczbę w notacji naukowej, taką jak:
6.0221413x10 23
Mantissa byłaby 6.0221413
. Przypomnijmy, że mantysa w notacji naukowej zawsze zaczyna się od pojedynczej niezerowej cyfry. To samo dotyczy binarnych, z tym że binarne mają tylko dwie cyfry: 0
i 1
. Więc binarna mantysa zawsze zaczyna się od 1
! Gdy pływak jest przechowywany, 1
przednia część mantysy binarnej jest pomijana, aby zaoszczędzić miejsce; musimy umieścić go z tyłu naszego trzeciego elementu, aby uzyskać prawdziwą mantysę:
1.0010011001100110011001100110011001100110011001100110
Wymaga to czegoś więcej niż zwykłego dodania, ponieważ bity przechowywane w naszym trzecim składniku faktycznie reprezentują ułamkową część mantysy, po prawej stronie punktu podstawy .
Kiedy mamy do czynienia z liczbami dziesiętnymi, „przesuwamy przecinek dziesiętny” przez pomnożenie lub podzielenie przez potęgi 10. W trybie binarnym możemy zrobić to samo, mnożąc lub dzieląc przez potęgi 2. Ponieważ nasz trzeci element ma 52 bity, dzielimy przesuń go o 2 52, aby przesunąć o 52 miejsca w prawo:
0,0010011001100110011001100110011001100110011001100110
W notacji dziesiętnej, to tak samo jak dzielenie 675539944105574
przez 4503599627370496
dostać 0.1499999999999999
. (Jest to jeden z przykładów współczynnika, który można wyrazić dokładnie w postaci binarnej, ale tylko w przybliżeniu w postaci dziesiętnej; więcej szczegółów: 675539944105574/4503599627370496 .)
Teraz, gdy przekształciliśmy trzeci składnik w liczbę ułamkową, dodanie 1
daje prawdziwą mantysę.
Podsumowanie komponentów
- Znak (pierwszy składnik):
0
pozytywny, 1
negatywny
- Wykładnik (środkowy składnik): Odejmij 2 (liczba bitów) - 1 - 1, aby uzyskać prawdziwy wykładnik
- Mantissa (ostatni komponent): Podziel przez 2 (# bitów) i dodaj,
1
aby uzyskać prawdziwą mantysę
Obliczanie liczby
Łącząc wszystkie trzy części, otrzymujemy ten numer binarny:
1.0010011001100110011001100110011001100110011001100110 x 10 11
Które możemy następnie przekonwertować z binarnego na dziesiętny:
1,149999999999999999 x 2 3 (niedokładne!)
I pomnóż, aby odsłonić ostateczną reprezentację liczby, od której zaczęliśmy ( 9.2
) po zapisaniu jako wartość zmiennoprzecinkowa:
9.199999999999999993
Reprezentowanie jako ułamek
9.2
Teraz, kiedy zbudowaliśmy liczbę, można ją zrekonstruować w prosty ułamek:
1.0010011001100110011001100110011001100110011001100110 x 10 11
Przesuń mantysę na liczbę całkowitą:
10010011001100110011001100110011001100110011001100110 x 10 11-110100
Konwertuj na dziesiętne:
5179139571476070 x 2 3-52
Odejmij wykładnik potęgi:
5179139571476070 x 2 -49
Zamień wykładnik ujemny na podział:
5179139571476070/2 49
Pomnóż wykładnik:
5179139571476070/562949953421312
Co równa się:
9.199999999999999993
9.5
>>> float_to_bin_parts(9.5)
['0', '10000000010', '0011000000000000000000000000000000000000000000000000']
Widać już, że mantysa ma tylko 4 cyfry, po których następuje wiele zer. Ale przejdźmy kroki.
Zbierz binarny zapis naukowy:
1,0011 x 10 11
Przesuń kropkę dziesiętną:
10011 x 10 11–100
Odejmij wykładnik potęgi:
10011 x 10 -1
Binarny na dziesiętny:
19 x 2 -1
Wykładnik ujemny do podziału:
19/2 1
Pomnóż wykładnik:
19/2
Równa się:
9.5
Dalsza lektura