Monday, June 13, 2011

HW: Reprezentacia cisel pomocou floating point

Jedna sa o mnozinu realnych cisel, ktora je v pocitaci reprezentovana konecnou podmnozinou racionalnych cisel. Doposial sme hovorili o radovej mriezke s pevnou radovou ciarkou, ktora ma obmedzeny rozsah cisel, ktore sa daju zobrazit. Ak zmenime rozsah (ale nie zmena presnosti), tak ze zvolime

  • vhodne konstantne meritko
  • alebo vhodne premenne meritko 
tak dostaneme pohyblivu radovu ciarku. To co sme vlastne spravili je, ze sme pridali exponent e. M.z^e potom odpoveda posunu radovej ciarky v cisle M o e. 



Pre kazdy prvok A z tejto mnoziny plati, ze A patri ±M · ze-t


A je prvkom mnoziny 
M je mantisa;  0 <= M  < z-1
z je baza 
t je presnost 
e je exponent, alebo posunutie radovej ciarky, emin ≤ e < emax

Mantisa nesie informaciu o hodnote cisla a exponent nesie informaciu o pozicii radovej ciarky. Radova mriezka je rozdelena na dve podmriezky pre mantisu a exponent. Mantisa nam teda povie ake cislice zapisujeme a exponent (obcas charakteristika) nam zase povie, kam umiestnit ciarku.




Z obrazku je vidno, ze existuje viac moznosti zapisu FP ciarky. Prve cislo je -25*10^5 a druhe 0,02*10^-5. Vidite, ze v pripade prveho cisla je zapis mantisy aj exponentu v doplnkovom kode, pricom v druhom pomocou aditivneho alebo priameho kodu a mantisa je v absolutnej hodnote, pretoze znamienko sme strcili dopredu. 

V pripade prveho cisla je M = -25, z = 10, e = 5
V pripade druheho cisla je M = 0,02, z = 10, e = -5

Tieto dva priklady dobre ilustruju, ako sa daju FP zapisovat. Existuje este zapis, ktory sa nazyva normalizovany a to je taky tvar cisla, kedy uz nejde mantisu posunut viac dolava. Takyto zapis zjednodusuje aritmeticke operacie, ale nezarucuje normalizovany tvar vysledku, ktory treba potom zase normalizovat.  Pre normalizovany tvar plati:
      • epxonent je najmensi mozny 
      • mantisa je posunuta co najviac vlavo 


Priklad:

V pripade, ze M a A(e) je rozne od nuly a zaroven z = 2 a pouzijeme normalizovany zapis, potom v MSB mantisy bude vzdy jednicka. Tuto jednicku nemusime zobrazovat, cim si usetrime miesto v mriezke. Musime ju ale vzdy uvazovat v operaciach! Tento princip sa pouziva napriklad v standarde ANSI/IEEE Std. 754. 

Predtym, ako sa pustime do prikladov, tak sa mi este ziada ozrejmit sposoby zapisu. Ide o to, ze existuju standardne formaty zapisu 

US Air Force MIL-STD-1750A 


z = 2

BFLM

z = 16
A(E) je aditivny kod 
M je v priamom kode, preto znamienko dopredu a mantisa v absolutnej hodnote 

ANSI/IEEE Std 754-1985

z = 2
Tento zapis nam umoznuje vyuzit skrytej 1cky. Ak tuto moznost nevyuzijeme, tak namiesto 24 bitov pre mantisu zostane 23. Mantisa je opat v priamom kode, znamienko na zaciatku a exponent + 127, teda aditivny kod s K = 127. 

Nacase sa pusitit do nejakych prikladov :). Operacie nad cislami v FP si uvedieme v dalsom prispevku. 

58, z = 10
58  = 111010
My toto cislo potrebujeme dostat do tvaru A = M.z^e a zaroven musime dbat na to, aky kod pouzivame a ake cislo v nom mozme zobrazit. 

v MILD-STD                       
Pre zobrazenie mantisy pouzivame doplnkovy kod. Z definicie 
D(A) = 
  • A; 0 <= A < 1/2 Z
  • Z + A; -1/2*Z <= A < 0
musi platit, ze zobrazitelne cislo bude -1/2*Z <= A < 1/2*Z a v nasom pripade to znamena ze cislo bude medzi -1 <= A < 1. Cislo 58 je ale o trosku vacsie ako 1 :) a preto s tym musime nieco robit ... 58 je mozne zapisat ako 58 = 0,58 * 10^-2 a ekvivalent tohto zapisu v 2-kovej sustave bude 

                         111010 = 0,111010 * (010 ^ 110)    {58 = 0,58 * (2 ^ 6) pre z = 2}

a teda M = 0,111010, z = 010, e = 110. Uz vieme, ze doplnkovy kod pre kladne cisla je rovnaky ako cislo, ktore chceme zobrazit. V tomto pripade mozme pisat vysledok 

                D(M)                                    D(e)
0111 0100 0000 0000 0000 0000 | 00000110
-1                                                                -23    7                 0

Cislo v M je zlomkova cast cisla a preto index zacina na -1 a konci na -23. V exponente mame zase cislo cele a bity zacinajuc 7 .. 0


v BFLM
Tu je format zapisu trochu odlisny. Baza je 16. Na zaciatku mame znamienko, na ktore mame jeden bit. Kedze cislo je kladne, tak mozme pisat s = 0. Mantisu piseme v absolutnej hodnote, pretoze to je priamy kod a exponent mame pre istotu v kode aditivnom, kde K = 64 (K = 1/2*Ze, Ze = z^(n+1) = 2^7). Dobry gulas :). 

Priamy kod P(A) = 
  • A; 0 =< A < z^n 
  • z^n + |A|; -z^n < A =< 0
A aditivny kod Ak(A) = A + K pre -K =< A < Z - K 

Pre |M| plati, ze |M| < 1, pretoze sa zase zobrazuje zlomkova cast. Zase vyuzijeme, ze 
111010 = 0,111010 * (010 ^ 110). No pruser je, ze tentokrat je z = 16, takze to este upravime 
111010 = 0,0011 1010 * (10000^10) {58 = 0,0058 * (16^2) pre z = 16} Na tomto mieste by sa asi patrilo vysvetlit, preco je to 16^2. Prepisme si cislo do hexa, 0011 1010 je v hexa 3A a to posunime na 0,3A, teda o dve pozicie, teda 3A = 0,3A.16^2. 

M = 0,00111010
Ak(E) = E + K = 10 + 1000000 = 1000010

s          Ak(E)                               | M |
0 | 1 0 0 0 0 1 0 | 0 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 |
       6                      0    -1                                                                                     -23


pre ANSI/IEEE 

tu si prepoziciam zapis ziskany v MILD-STD 

                         111010 = 0,111010 * (010 ^ 110)

mantisu uz nemozme posunut dolava a tak mame normalizovany tvar. 


s          Ak(E)                               | M |
0 | 1 0 0 0 0 1 1 0 | 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 
       7                          0    -1                                                                                 -22


A my vsetci vieme, ze ta jednicka tam je.

-58, z = 10

-58 bude opat znamenat, ze musime cislo zmensit na -0,58*10^2. 
D(-0,58) potrebujeme pre MILD-STD. Z definicie vieme, ze vysledok bude Z +  A, teda 10 - 0,11101 = 
  10,00000
- 00,11101
------------
   01,000110 

D(M) = 1,000110 
E =  110

                D(M)                                    D(e)
1000 1100 0000 0000 0000 0000 | 00000110
-1                                                                -23    7                 0


v dalsich dvoch kodoch nam vlastne len pribudne bit s, s = 1.