JustPaste.it

Standard IEEE 754

Aby ujednolicić wyniki obliczeń numerycznych wykonywanych na różnych platformach sprzętowych, wprowadzono ściśle określony standard zapisu zmiennoprzecinkowego IEEE 754. W następnym rozdziale przedstawiamy wywiad z profesorem Williamem Kahanem - jednym z twórców tego standardu. Jak na warunki szkoły średniej standard IEEE 754 jest dosyć skomplikowany, ponieważ nie został on opracowany do nauki lecz do praktycznych zastosowań inżynierskich i naukowych. Jednakże nie widzę powodów, aby zdolny uczeń liceum nie mógł sobie go przyswoić - wiedza ta zaowocuje na studiach wyższych oraz wpłynie na zrozumienie zalet i ograniczeń obliczeń komputerowych.

bb6cfc60edb09a3c80c475e9e338635c.gif

Standard IEEE 754 definiuje dwa rodzaje liczb zmiennoprzecinkowych: 32-bitowe (pojedynczej precyzji - ang. single precision) oraz 64-bitowe (podwójnej precyzji - ang. double precision). Kod binarny liczby zmiennoprzecinkowej podzielony jest na trzy pola zawierające komponenty zapisu zmiennoprzecinkowego:

Format zapisu zmiennoprzecinkowego IEEE 754
32 bity - pojedyncza precyzja (1 bit)   b31 (8 bitów)   b30 ... b23 (BIAS=127) (23 bity)   ,b22 ... b0 (U1)
64 bity - podwójna precyzja (1 bit)   b63 (11 bitów)   b62 ... b52 (BIAS=1023) (52 bity)   ,b51 ... b0 (U1)
Opis pół bitowych bit znaku bity kodu cechy bity ułamkowe mantysy

Bit znaku

Pierwszy bit w zapisie liczby zwany jest bitem znaku. Stan 0 oznacza liczbę dodatnią, stan 1 liczbę ujemną. Aby zatem zmienić znak liczby zmiennoprzecinkowej na przeciwny, wystarczy dokonać negacji tego bitu.

Bity kodu cechy

Liczby zmiennoprzecinkowe IEEE 754 zapisują cechę w kodzie z nadmiarem.

W pojedynczej precyzji cecha posiada 8 bitów, a nadmiar wynosi 127. Zatem w polu cechy można zapisać wartości od -127 (wszystkie bity b30...b23 wyzerowane) do 128 (wszystkie bity b30...b23 ustawione na 1).

W podwójnej precyzji cecha zbudowana jest z 11 bitów, nadmiar wynosi 1023. Najmniejszą wartością będzie -1023 (bity b62...b52 ustawione na 0) , a największą 1024 (bity b62...b52 ustawione na 1). Wzrost ilości bitów cech liczb zmiennoprzecinkowych wpływa a ich zakres.

UWAGA! Cechy zbudowane z samych zer i z samych jedynek pełnią w standardzie IEEE 754 specjalne funkcje nie związane z ich normalnym znaczeniem. Opisujemy to szczegółowo w dalszej części artykułu.

Bity ułamkowe mantysy

W pojedynczej precyzji mantysa posiada 23 bity, a w podwójnej precyzji 52 bity. Wzrost liczby bitów mantys liczb zmiennoprzecinkowych wpływa na ich precyzję, czyli dokładność odwzorowywania liczb rzeczywistych.

Mantysy są zapisywane w stałoprzecinkowym kodzie U1. Ponieważ mantysa jest prawie zawsze znormalizowana (z wyjątkiem wartości zdenormalizowanej, która jest przypadkiem szczególnym liczby zmiennoprzecinkowej IEEE 754), to jej wartość liczbowa zawiera się pomiędzy 1 a 2. Wynika stąd, iż pierwszy bit całkowity mantysy zawsze wynosi 1. Skoro tak, to nie musi on być zapamiętywany - będzie automatycznie odtwarzany w czasie wykonywania obliczeń na liczbie zmiennoprzecinkowej. W polu mantysy zapamiętujemy tylko bity ułamkowe. Dzięki tej prostej sztuczce zyskujemy jeden dodatkowy bit mantysy - zwiększamy jej rozdzielczość do 24 bitów dla formatu pojedynczej precyzji i do 53 bitów dla formatu podwójnej precyzji. Sposób ten nie jest wcale nowy - zastosował go już w 1936 roku niemiecki konstruktor Konrad Zuse w swoich komputerach.

7b4d16fdffec9a79a50d491726349f85.gif

Wartość liczby IEEE 754 obliczamy wg poznanych dotychczas zasad. Z kodu wydzielamy poszczególne pola znaku z, cechy c i mantysy m. Odczytana mantysa zawiera tylko bity ułamkowe. Dodajemy zatem na początku 01 i przecinek. W wyniku otrzymujemy dodatnią liczbę stałoprzecinkową w kodzie U1. Teraz obliczamy wartość cechy i mantysy, a następnie wyliczamy wartość liczby wg wzoru:

L(IEEE 754) = (-1)zm2c

Dla przykładu policzymy wartości kilku liczb w pojedynczej precyzji (dla podwójnej precyzji rachunki są identyczne, lecz bardziej uciążliwe do przeprowadzenia z uwagi na większą liczbę bitów).

e0d38665a4fc0db64de858ca958ccb5f.gif

 

Obliczyć wartość dziesiętną liczby zmiennoprzecinkowej:  01000010110010000000000000000000(IEEE 754).

Kod binarny dzielimy na poszczególne pola zawierające kolejno znak, cechę oraz bity ułamkowe mantysy:

0 10000101 10010000000000000000000
z cecha bity ułamkowe mantysy

z = 0 - liczba jest dodatnia
c = 10000101(BIAS=127) = 133 - 127 = 6
m = 01,10010000000000000000000(U1) = 19/16

Mamy wszystkie niezbędne składniki, wyliczamy wartość liczby:

L(IEEE 754) = (-1)zm2c = (-1)0 x 19/16 x 26 = 25/16 x 26= 25 x 22 = 25 x 4 = 100(10)

01000010110010000000000000000000(IEEE 754) = 100(10).

e0d38665a4fc0db64de858ca958ccb5f.gif

 

Obliczyć wartość dziesiętną liczby zmiennoprzecinkowej 11000001110110000000000000000000(IEEE 754).

Postępujemy identycznie jak w poprzednim przykładzie:

1 10000011 10110000000000000000000
z cecha bity ułamkowe mantysy

z = 1 - liczba jest ujemna
c = 10000011(BIAS=127) = 131 - 127 = 4
m = 01,10110000000000000000000(U1) = 111/16

L(IEEE 754) = (-1)zm2c = (-1)1 x 111/16 x 24 = - 27/16 x 24= -27(10)

11000001110110000000000000000000(IEEE 754) = -27(10).

e0d38665a4fc0db64de858ca958ccb5f.gif

 

Obliczyć wartość dziesiętną liczby zmiennoprzecinkowej 10111110000000000000000000000000(IEEE 754).

1 01111100 00000000000000000000000
z cecha bity ułamkowe mantysy

z = 1 - liczba jest ujemna
c = 01111100(BIAS=127) = 124 - 127 = -3
m = 01,00000000000000000000000(U1) = 1

L(IEEE 754) = (-1)zm2c = (-1)1 x 1 x 2-3 = - 1/8 = -0,125(10)

11000001110110000000000000000000(IEEE 754) = -0,125(10).

Jak widać, liczby zmiennoprzecinkowe wcale nie są takie straszne - pod warunkiem, że pilnie studiowałeś nasz artykuł. W przeciwnym razie na zawsze pozostaną dla ciebie tajemnicą...

Poniżej przedstawiam prosty program w języku Pascal, który pozwala zobaczyć wewnętrzną postać wprowadzonej liczby zmiennoprzecinkowej w standardzie IEEE 754 (program nie uwzględnia wartości specjalnych - ale może ty potrafisz go ulepszyć?). W programie wykorzystujemy fakt, iż komputer IBM PC przechowuje liczby zmiennoprzecinkowe w tym właśnie standardzie, zatem nic nie musimy przeliczać, wszystko robi za nas system.

Efekt uruchomienia programu
Demonstracja standardu zmiennoprzecinkowego IEEE 754
----------------------------------------------------
(C)2005 mgr Jerzy Walaszek I LO w Tarnowie

Wpisz liczbe : -13257.25

11000110010011110010010100000000

1 10001100 10011110010010100000000
z cecha mantysa

z = 1
c = 10001100 = 13
m = 01,10011110010010100000000 = 1.6183166504

Klawisz ENTER = KONIEC

 

program IEEE754;

{$APPTYPE CONSOLE}

type
sp_ieee754 = record
case
value: integer of
0 : (b : array[0..3] of byte);
1 : (f : single);
end;

var
l_ieee754 : sp_ieee754;
i,j,v,c,z : integer;
s : string;
begin
writeln('Demonstracja standardu zmiennoprzecinkowego IEEE 754');
writeln('----------------------------------------------------');
writeln('(C)2005 mgr Jerzy Walaszek I LO w Tarnowie');
writeln;
write('Wpisz liczbe : '); readln(l_ieee754.f);
writeln;
//---------------------------------------
// Odczytujemy kolejne bity zapisu liczby
//---------------------------------------
s := '';
for i := 0 to 3 do
begin

v := l_ieee754.b[i];
for j := 1 to 8 do
begin

s := char(48 + (v mod 2)) + s;
v := v div 2;
end;
end;
writeln(s);
writeln;
for i := 1 to 32 do
begin

write(s[i]);
if (i = 1) or (i = 9) then write(' ');
end;
writeln;
writeln('z cecha mantysa');
writeln;
//----------------------------------------------------
// Teraz wyznaczamy wartości poszczególnych składników
// Program nie uwzględnia wartości specjalnych !
//----------------------------------------------------
z := (l_ieee754.b[3] and $80) shr 7;
writeln('z = ',z);
c := ((l_ieee754.b[3] and $7f) shl 1) or
((l_ieee754.b[2] and $80) shr 7) - 127;
writeln('c = ',copy(s,2,8),' = ',c);
v := $800000 or ((l_ieee754.b[2] and $7f) shl 16) or
(l_ieee754.b[1] shl 8) or l_ieee754.b[0];
writeln('m = 01,',copy(s,10,23),' = ',v / $800000:0:10);
writeln;
write('Klawisz ENTER = KONIEC'); readln;
end.

 

aac58d6fe62d574254debc69f7472393.gif

Gdy znamy budowę liczby zmiennoprzecinkowej w standardzie IEEE 754, z obliczeniem zakresu możliwych do zapisania w nim liczb nie będzie żadnego problemu. Po prostu musimy znaleźć największą cechę i największą mantysę i podstawić je do podanego wcześniej wzoru.

Liczby pojedynczej precyzji

Największa cecha posiada kod:

c = 11111110(BIAS=127)
c = 254 - 127
c = 127

Kod 11111111(BIAS=127) = 255 - 127 = 128 jest zarezerwowany dla specjalnych sytuacji, zatem nie możemy go wykorzystać na cechę liczby zmiennoprzecinkowej.

Największa mantysa osiada kod:

m = 01,11111111111111111111111(U1)
m = (224 - 1) / 223

Obliczamy wartość największej liczby:

max(IEEE 754) = m x 2c
max(IEEE 754) = (224 - 1) / 223
x 2127
max(IEEE 754) = (224 - 1)
x 2104
max(IEEE 754) = 3,4028234663852885981170418348452
x 1038

a po zaokrągleniu:

max(IEEE 754) = 3,4 x 1038

Ponieważ zmianą znaku możemy uzyskać tę samą wartość po stronie ujemnej, zakres liczb zmiennoprzecinkowych IEEE 754 w pojedynczej precyzji wynosi:

5dceea3c70ed7cc0ccdd44cbae0d591e.gif    
   
    77a78d35ce44df0129186e14fbf5290d.gifZakres liczb zmiennoprzecinkowych IEEE 754 w pojedynczej precyzji

Z(IEEE 754) = - 3,4 x 1038 ... 3,4 x 1038

 
       

 

Liczby podwójnej precyzji

Dla liczby IEEE 754 podwójnej precyzji przeprowadzamy identyczne obliczenia:

c = 11111111110(BIAS=1023)
c = 2046 - 1023
c = 1023

m = 01,1111111111111111111111111111111111111111111111111111(U1)
m = (253 - 1) / 252

max(IEEE 754) = m x 2c
max(IEEE 754) = (253 - 1) / 252
x 21023
max(IEEE 754) = (253 - 1)
x 2971
max(IEEE 754) = 1,797693134862315708145274237317
x 10308

a po zaokrągleniu:

max(IEEE 754) = 1,8 x 10308

5dceea3c70ed7cc0ccdd44cbae0d591e.gif    
   
    77a78d35ce44df0129186e14fbf5290d.gifZakres liczb zmiennoprzecinkowych IEEE 754 w podwójnej precyzji

Z(IEEE 754) = - 1,8 x 10308 ... 1,8 x 10308

 
       

 

 

 

27168a874f0227c3b06f4dec95954536.gif

Oprócz zakresu, na który wpływa głównie długość formatu bitowego cechy, dla liczb zmiennoprzecinkowych nie mniej ważnym parametrem jest precyzja zapisu, czyli z jaką dokładnością dana liczba może być reprezentowana. Precyzję podaje się najczęściej jako przybliżoną ilość dziesiętnych cyfr znaczących. Na przykład jeśli precyzja zapisu wynosi trzy cyfry dziesiętne, to liczby 856  92,4  1,53 zostaną zapamiętane dokładnie, natomiast liczby o większej ilości cyfr już nie: 85613 zostanie zapamiętane jako 856??, gdzie znaki ? reprezentują dowolne cyfry.

Precyzję zapisu liczby zawsze wyznacza ilość dostępnych bitów mantysy. Jedną cyfrę dziesiętną koduje (statystycznie) log2(10) bitów mantysy. Ułóżmy zatem proste proporcje:

Dla pojedynczej precyzji mantysa ma długość 24 bity:

1 cyfra dziesiętna --- log2(10) bitów
x cyfr dziesiętnych --- 24 bity

Stąd

x cyfr dziesiętnych = 24 / log2(10) = 24 / 3,32 = 7,2 cyfry

Zaokrąglamy wynik do liczby całkowitej i dla liczb w pojedynczej precyzji otrzymujemy 7 dziesiętnych cyfr znaczących.

Dla podwójnej precyzji mantysa ma długość 53 bity:

1 cyfra dziesiętna --- log2(10) bitów
x cyfr dziesiętnych --- 53 bity

Stąd

x cyfr dziesiętnych = 53 / log2(10) = 53 / 3,32 = 15,96 cyfry

Zaokrąglamy wynik do liczby całkowitej i dla liczb w podwójnej precyzji otrzymujemy 15-16 cyfr znaczących.

5dceea3c70ed7cc0ccdd44cbae0d591e.gif    
   
   

77a78d35ce44df0129186e14fbf5290d.gif

Liczby pojedynczej precyzji IEEE 754 oferują precyzję 7 cyfr dziesiętnych. Zatem nadają się one do bardzo prostych rachunków, gdzie nie wymagana jest zbyt duża dokładność.

Liczby podwójnej precyzji IEEE 754 oferują precyzję 15...16 cyfr dziesiętnych. Zatem nadają się do dokładnych obliczeń naukowych i inżynierskich. Stosuj je zawsze tam, gdzie wymagana jest duża dokładność końcowych wyników.

 
       

 

e14149084943b512deea3788191a7a3b.gif

 

Wartość zero

Zauważ, iż w normalny sposób nie można zapisać w formacie IEEE 754 wartości 0, ponieważ mantysa ma domyślną część całkowitą równą 1 - w polu mantysy zapamiętywane są jedynie bity ułamkowe. Dlatego zero jest specjalnym przypadkiem liczby zmiennoprzecinkowej, gdzie zarówno pole wykładnika jak i mantysy zawiera same 0. Bit znaku może przyjmować dowolną wartość (stąd możemy dostać dodatnie lub ujemne 0, jednakże przy porównaniu są one traktowane jak równe sobie).

Wartość ZERO pole
znaku
pole
cechy
pole
mantysy
0/1 0...0 0...0

Wartość zdenormalizowana

Jeśli wszystkie bity cechy mają wartość 0, lecz mantysa zawiera bity o wartościach 1 (w przeciwnym razie liczba zostanie potraktowana jak opisane wcześniej zero), to jest to tzw. zdenormalizowana liczba zmiennoprzecinkowa. W takim przypadku mantysa nie posiada domyślnej części całkowitej 1, lecz jest liczbą ułamkową, której bity zawarte są w polu formatu IEEE 754.

Wartość

zdenormalizowana

pole
znaku
pole
cechy
pole
mantysy
0/1 0...0 bity ułamkowe mantysy

 

Wartość zdenormalizowaną liczby zmiennoprzecinkowej liczymy według wzoru:

Pojedyncza precyzja

m = 00,(pole mantysy)(U1)

L = (-1)zm2-126

Stąd najmniejszą wartością zmiennoprzecinkową różną od zera jest:

00000000000000000000000000000001(IEEE 754)

m = 00,00000000000000000000001(U1)
m = 2-23

min(IEEE 754) = 2-23 x 2-126 = 2-149
min(IEEE 754) = 1,4012984643248170709237295832899
x 10-45
min(IEEE 754) = ±1,4
x 10-45

Podwójna precyzja

m = 00,(pole mantysy)(U1)

L = (-1)zm2-1022

Stąd najmniejszą wartością zmiennoprzecinkową różną od zera jest:

000000000000000000000000000000000000000000000000000000000000001(IEEE 754)

m = 00,0000000000000000000000000000000000000000000000000001(U1)
m = 2-52

min(IEEE 754) = 2-52 x 2-1022 = 2-1074
min(IEEE 754) = 4,9406564584124654417656879286822
x 10-324
min(IEEE 754) = ±4,9
x 10-324

5dceea3c70ed7cc0ccdd44cbae0d591e.gif    
   
   

77a78d35ce44df0129186e14fbf5290d.gif

Wartości zdenormalizowane pozwalają przedstawiać bardzo małe liczby zmiennoprzecinkowe, które bez tej opcji zostałyby zaokrąglone do 0. Zwiększa to precyzję wykonywanych operacji zmiennoprzecinkowych i jest cechą bardzo pożądaną. Liczbę zero można traktować jak liczbę zdenormalizowaną, w której mantysa wynosi 0.

 
       

 

Nieskończoność

Standard IEEE 754 pozwala reprezentować dodatnią i ujemną nieskończoność. Pole znaku określa, z którą nieskończonością mamy do czynienia - dodatnią czy ujemną. Cecha posiada wszystkie bity ustawione na 1 (maksymalna wartość cechy), a bity mantysy są wyzerowane.

Nieskończoność pole
znaku
pole
cechy
pole
mantysy
0/1 1...1 0...0

Wartość typu nieskończoność jest bardzo pożądana w systemie zmiennoprzecinkowym, ponieważ pozwala ona prowadzić obliczenia po wystąpieniu nadmiaru. Wyniki działań z nieskończonościami są dokładnie zdefiniowane w standardzie IEEE 754 - opisujemy je na końcu rozdziału.

Nieliczby

Standard IEEE 754 definiuje dwie specjalne wartości, które nie reprezentują liczb. Stąd nazywane są w literaturze terminem NaN (Not a Number - Nie Liczba). Nieliczby mogą być dwojakiego rodzaju - tzw. ciche - QNaN (ang. Quiet NaN) lub głośne SNaN (ang. Signaling NaN). W obu przypadkach cecha zawiera same 1, a pole mantysy zawiera bity 1. Jeśli najstarszy bit ułamkowy mantysy jest ustawiony na 1, to kod reprezentuje cichą nieliczbę - QNaN.

Cicha Nieliczba
QNaN
pole
znaku
pole
cechy
pole
mantysy
0/1 1...1 1X...X

Jeśli najstarszy bit mantysy ustawiony jest na 0, kod reprezentuje głośną nieliczbę:

Głośna Nieliczba
SNaN
pole
znaku
pole
cechy
pole
mantysy
0/1 1...1 0X...X

Nieliczby mają wiele zastosowań. Ciche nieliczby przechodzą przez działania arytmetyczne. Najczęściej oznaczają one wartość niezdefiniowaną. Głośne nieliczby powodują powstanie wyjątków w operacjach arytmetycznych. Najczęściej oznaczają one wartość niedozwoloną. Typowym zastosowaniem głośnych nieliczb jest wstępna inicjalizacja zmiennych. Jeśli programista nie wprowadzi do zmiennej wartości, czyli nie zainicjuje jej, to będzie ona zawierała wartość SNaN. Próba użycia takiej zmiennej w jakimkolwiek wyrażeniu arytmetycznym spowoduje wygenerowanie wyjątku i przerwanie obliczeń.

Wyniki operacji z wartościami specjalnymi

Standard IEEE 754 bardzo dokładnie precyzuje wyniki operacji, w których jednym z argumentów (lub obydwoma) jest wartość specjalna. W poniższej tabelce zebraliśmy najważniejsze zasady przeprowadzania takich operacji:

Operacja Wynik
n / ±Nieskończoność 0
±Nieskończoność x ±Nieskończoność ±Nieskończoność
±wartość niezerowa / 0 ±Nieskończoność
Nieskończoność + Nieskończoność Nieskończoność
±0 / ±0 NaN
Nieskończoność - Nieskończoność NaN
±Nieskończoność / ±Nieskończoność NaN
±Nieskończoność x 0 NaN

Zainteresowanych tym tematem odsyłamy do artykułu o komputerach Konrada Zuse.

4d358dfd366885d234068abc9d8508b4.gif

W poniższej tabelce podsumowujemy wszystkie możliwe wartości reprezentowane przez format IEEE 754. Więcej danych na temat standardu IEEE 754 znajdziesz w witrynie http://standards.ieee.org/.

Interpretacja kodu IEEE 754
Pole
znaku
Pole
cechy
Pole
mantysy
Wartość
0 0...0 0..0 +0 (zero dodatnie)
0 0...0 0...1
:
1...1
Dodatnia liczba zdenormalizowana
0 0...1
:
1...0
0...0
:
1...1 
Dodatnia liczba zmiennoprzecinkowa
0 1...1 0...0 +Nieskończoność
0 1...1 0...01
:
01...1
SNaN (głośna nieliczba)
0 1...1 10...0
:
1...1
QNaN (cicha nieliczba)
1 0...0 0...0 -0 (zero ujemne)
1 0...0 0...1
:
1...1
Ujemna liczba zdenormalizowana
1 0...01
:
1...10
0...0
:
1...1
Ujemna liczba zmiennoprzecinkowa
1 1...1 0...0 -Nieskończoność
1 1...1 0...01
:
01...1
SNaN (głośna nieliczba)
1 1...1 10...0
:
1...1
QNaN (cicha nieliczba)
612c587756da268db4f0421602176ea8.gif

Zadanie 1 (średnio trudne)

Każdy współczesny procesor Pentium zintegrowany jest wewnętrznie z koprocesorem arytmetycznym, który wykonuje sprzętowo operacje na liczbach zmiennoprzecinkowych. Wewnętrznie stosuje on rozszerzony typ danych zmiennoprzecinkowych o następującej specyfikacji formatu:

Format rozszerzony zapisu zmiennoprzecinkowego koprocesora arytmetycznego
80 bitów - rozszerzona precyzja (1 bit)   b79 (15 bitów)   b78 ... b64 (BIAS=16383) (64 bity)   ,b63 ... b0 (U1)
Opis pół bitowych bit znaku bity kodu cechy bity ułamkowe mantysy

Na podstawie materiału przedstawionego w tym rozdziale wyznacz kolejno:

  1. Zakres możliwych do przedstawienia w tym formacie liczb dziesiętnych
  2. Najmniejszą dziesiętną liczbę zdenormalizowaną
  3. Precyzję zapisu, czyli liczbę znaczących cyfr dziesiętnych.

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.

 

Źródło: mgr Jerzy Wałaszek