Strona główna » Algorytmy » Artykuły » IEEE 754
 

IEEE 754

Wstęp

Przechowywanie liczb rzeczywistych w komputerze jest obarczone błędem przybliżenia, ponieważ komputer nie jest zawsze w stanie pomieścić wszystkich cyfr po przecinku pewnej liczby. Standard IEEE 754 jest powszechnie używanym rozwiązaniem tego problemu. Został opisany przez Instytut Inżynierów Elektryków i Elektroników(ang. Institute of Electrical and Electronics Engineers (IEEE)) w 1985 r.

Kodowanie

Poniższy schemat przedstawia zapis liczby zmiennoprzecinkowej na 32 bitach:

ZnaczenieZnakWykładnikMantysa
Bity01..89..31

Pierwszy bit oznacza znak liczby. W tym przypadku 0 oznacza liczbę dodatnią, a 1 liczbę ujemną. Jest to bardzo podobne jak w kodowaniu liczb całkowitych U2. Kolejne 8 bitów jest to wykładnik. Wskazane 8 bitów oznacza pewną liczbę całkowitą q od której po odjęciu 127 otrzymuje się ceche. Ostatnie 23 bity to mantysa. Mantysa jest to część ułamkowa liczby, która powinna mieć zapis 1.x..x.

Zakodowaną liczę obliczamy ze wzoru: (-1)znakmantysa·2cecha

Zamiana liczby rzeczywistej na IEEE 754

Spróbujmy zamienić teraz liczbę 3.14 na zapis IEEE 754.

  1. Na początek określamy znak. Tutaj liczba jest dodatnia, więc wynosi on 0.
  2. Kolejny krok polega na zapisaniu liczby w notacji naukowej dla systemu binarnego. Oznacza to, że chcemy uzyskać liczbę w formacie 1.x..x·2w. W tym przypadku 3.14 = 1.57·21.
  3. Potęga dwójki wynosi 1, więc cecha do zakodowania wynosi 127 + 1 = 128 = 100000002.
  4. Ostatni etap polega na zapisaniu części ułamkowej 0.57 w postaci binarnej. Oznacza to, że używane będą jedynie potęgi 2 od -1 do -23

Potęga2-12-22-32-42-52-62-72-82-92-102-112-122-132-142-152-162-172-182-192-202-212-222-23
Bity10010001111010111000010

Powyższy zapis jest jedynie przybliżeniem, które oznacza, że 0.57 ~ 2-1 + 2-4 + 2-8 + 2-9 + 2-10 + 2-11 + 2-13 + 2-15 + 2-16 + 2-17 + 2-22.

Teraz przepisując wszystkie dane razem otrzymujemy zapis liczby 3.14 w kodowaniu IEEE 754:

ZnaczenieZnakWykładnikMantysa
Zapis01000000010010001111010111000010

Zamiana IEEE 754 na liczbę rzeczywistą

W poprzednim przykładzie została zakodowana liczba 3.14 jako 01000000010010001111010111000010IEEE 754. Teraz zostanie przedstawiony proces jej dekodowanie oraz porównanie wyniku z danymi wejściowymi.

  1. Na początek określamy znak. Pierwszy bit wynosi 0, więc znak = 0 czyli liczba dodatnia.
  2. Kolejny krok polega na odczytaniu wykładnika liczby. Wykładnik jest zakodowana jako 100000002 = 128, więc cecha wynosi 128 - 127 = 1.
  3. Następnie zapisaną wcześniej część ułamkową obliczamy sumując odpowiednie potęgi tam gdzie występuje bit 1. Z tego wynika, że mantysa wynosi 1 + 2-1 + 2-4 + 2-8 + 2-9 + 2-10 + 2-11 + 2-13 + 2-15 + 2-16 + 2-17 + 2-22 = 1.569999933242797. Tutaj należy zauważyć, że nie został otrzymany dokładnie wynik 1.57!
  4. Ostatni etap polega na podłożeniu wartości do wzoru (-1)znakmantysa·2cecha = (-1)01.569999933242797·21 = 3.139999866 co faktycznie w przybliżeniu można traktować jako 3.14.

Jak można zauważyć podczas przeliczania doszło do błędu przybliżenia, który wynosi |3.14 - 3.13999986| = 0.00000014. Ze względu na to, że każda liczba niebędąca możliwa do zapisania jako suma kolejnych potęg 2 zawsze będzie się różnić od oryginalnej to zgodnie ze specyfikacją stosuje się przybliżenia.

Wartości

Zakres

Zakres kodowanie IEEE 754 wynosi od około ± 1.18·10−38 do około ± 3.4·1038. Weźmy pod uwagę zapis informacji: najmniejszą wartość jaką można uzyskać to, gdy wykładnik jest 1, a mantysa wynosi 0 i jest to 2−127. Z kolei największa wartość jest dla wykładnika równego 254 oraz mantysy wypełnionej bitami 1 i ma wtedy wartość ok. 2, więc maksymalna wartość to 2127·2 = 2128.

Wartości specjalne

W powyższych rozważaniach została pominięta opcja, że wykładnik wynosi lub 255, ponieważ te wartości zostały zarezerwowane pod pewne specjalne wartości takie jak nieskończoność. Poniżej została przedstawiona pełna tabela specjalnych wartości jakie może przyjąć liczba zakodowana w IEEE 754:

WartośćZapisZnakWykładnikMantysa
zero000000000000000000000000000000000
zero ujemne-010000000000000000000000000000000
liczba zdenormalizowana*różne00000000różna od 0
nieskończoność+∞01111111100000000000000000000000
nieskończoność ujemna-∞11111111100000000000000000000000
nie liczba**NaNróżne11111111różna od 0

*liczby zdenormalizowane - liczby, które nie mogą zostać zapisane, ponieważ są zbyt małe do zakodowania
**NaN - nie liczba, Not a Number, wynik nie jest liczbą - może się pojawić jako wynik pierwiastkowania niektórych liczb ujemnych

Podwójna precyzja

Ze względu na rosnące zapotrzebowanie na dokładność obliczeń, ale również z powodu postępu technologicznego opracowana standard Podwójnej Precyzji, który jest kodowany na 64 bitach. Pozwala to zapisać znacznie większe liczby w dokładniejszy sposób niż w Pojedynczej Precyzji (zapisywanej na 32 bitach). Podział 64 bitów na odpowiednie części przedstawia się następująco:

ZnaczenieZnakWykładnikMantysa
Bity01..1112..63

Znak dalej jest zapisywany na pojedynczym bicie, a wykładnik zyskał 3 dodatkowe bity, a mantysa, aż 29! Oznacza to, że zakres obliczeń "niewiele" się zmienił, ale za to kodowane liczby są przetrzymywane ze znacznie większą dokładnością. W tym przypadku zakres przechowywanych liczb wynosi ±2.2·10−308 do około ±1.8·10308. Kroki w procesie kodowania są identyczne, ale należy pamiętać, że znacznie więcej danych jest zapisywanych: podczas wyliczania wykładnika dodaje się 1023 (a nie 127), a podczas wyliczania mantysy należy wyliczyć 52 bity, a nie tylko 23.

Podsumowanie

Wybór pomiędzy Pojedynczą, a Podwójną Precyzją pozostaje programiście, który na podstawie opisu programu, który pisze musi wywnioskować, który z tych typów będzie dla niego odpowiedni. Oczywiście nie należy zapominać, że w obydwu formatach dane mogą być obarczone błędem przybliżenia, ponieważ nie zawsze jest możliwe zapisanie dokładnie zadanej liczby na 32 lub 64 bitach!

Zadania
Zadanie 1
Kod źródłowy Zadanie 1Kod źródłowy Zadanie 1