DUzun's Web
Programare, proiecte personale, divertisment

DUzun it's ME
 
  
Floating point

Reprezentarea numerelor reale în formatul maşinii
Standardul IEEE 754 floating-point (virgula plutitoare [i])

Autor:
Uzun Dumitru

Introducere

Dat fiind faptul că în calculatoare se foloseşte punctul, nu virgula, la notarea fracţiilor zecimale, voi folosi notaţia cu punct.

Există mai multe metode de reprezentare a numerelor reale în calculatoare. Un mod de reprezentare este plasarea punctului undeva pe la mijlocul fracţiei, ceea ce este echivalent cu rezervarea a doi întregi – unul pentru partea întreagă şi altul pentru partea fracţionară a numărului. Astfel, având un număr de patru cifre (două pentru partea întreagă şi două pentru cea fracţionară), fracţia 1/100 ar fi reprezentată ca 00.01, iar 329/10 ca 32.90

O altă modalitate de reprezentare a numerelor reale este folosirea numerelor raţionale, adică doi întregi reprezintă numărătorul şi numitorul.

Reprezentarea cea mai des folosită este cea cu virgula plutitoare (floating-point). Această reprezentare se aseamănă mult cu notaţia ştiinţifică a numerelor. De exemplu, 148.554 poate fi reprezentat ca 1.48554 × 102, sau 0.148554 × 103. Astfel, ceea ce trebuie să reprezentăm este un număr întreg pentru mantisă[ii] şi un număr întreg pentru exponent, baza de numeraţie[iii] şi caracteristica[iv] fiind implicite. Cu alte cuvinte, mantisa reprezintă precizia (rezoluţia) numărului, iar exponentul – valoarea (domeniul de lucru: fracţii, unităţi, sute, mii, ş.a.m.d).

Virgula plutitoare rezolvă unele probleme de reprezentare. Virgula fixă are o fereastră fixă de reprezentare, ceea ce împiedică de a reprezenta numere foarte mari sau foarte mici. De asemenea, virgula fixă tinde să piardă din precizie când două numere mari sunt împărţite.

Pe de altă parte, virgula plutitoare impune un fel de „fereastră alunecătoare” a preciziei, potrivită proporţiilor numărului, ceea ce-i permite să reprezinte numere de la 10x până la 10-x cu uşurinţă.

Mai departe vor fi studiate doar numerele în formatul floating-point.

 

Forma de stocare în memorie:

După cum s-a menţionat mai sus, pentru numerele floating-point este nevoie de reprezentat doar mantisa şi exponentul numărului în notaţia ştiinţifică, însă mantisa poate fi număr pozitiv sau negativ. Deci mai este nevoie de un bit pentru semnul numărului.

Să facem câteva notaţii:
nr  – numărul real
s    – semnul
c    – caracteristica
m   – mantisa
e    – exponentul
d    – deplasarea

Cu aceste notaţii orice număr real poate fi scris ca nr = (-1)s × c.m × 10e  (în baza 2).

Figura ce urmează arată formatul intern[v] al numerelor cu virgulă plutitoare:

Semn (s)

Exponent (d + e)

Mantisă (m)

0 sau 1 – un bit

deplasarea + exponentul real

normalizată sau denormalizată

Semnul:

Bitul de semn[vi] doar indică semnul, nimic mai mult: 0 pentru număr pozitiv şi 1 pentru număr negativ.

Exponentul:

Spre deosebire de reprezentarea numerelor întregi negative[vii] în formatul maşinii, exponentul în formatul floating-point foloseşte deplasarea[viii] pentru a putea reprezenta valorinegative. Deplasarea este o constantă care se calculează în funcţie de mărimea câmpului exponentului, şi anume este jumate din valoarea maximă care poate fi reprezentată de acest câmp. De ex., dacă câmpul exponentului are capacitatea de reprezentare pe intervalul [0..255], când adăugăm deplasarea (d = 127), e ia valori din [‑127..128], astfel (e + d) numai bine se încadrează în câmpul exponentului şi de aici putem reprezenta exponentul negativ (e < 0).

Mantisa:

Mantisa poate fi normalizată sau denormalizată[ix]. Dacă exponentul este egal cu zero (e + d = 0), mantisa este denormalizată şi caracteristica se consideră nulă (c = 0). Iar dacă exponentul este diferit de zero (e + d <> 0), mantisa este normalizată, iar caracteristica se consideră 1 (c = 1)[x]. Altfel spus, când mantisa este normalizată, ea împrumută o cifră caracteristicii (1.nnn), iar când este denormalizată, ea reprezintă toate cifrele singură (0.1nnn), iar caracteristica nu reprezintă nici o cifră. De ex., numărul 1.00101001 se va scrie în forma normalizată 1.00101001 × 100, iar în cea denormalizată ca 0.100101001 × 101.

Observaţi că 101.110 nu poate fi reprezentat în forma denormalizată, deoarece câmpul exponentului nu poate fi nul în acest caz (e + d <> 0).

Având în vedere că caracteristica ia doar valorile 0 sau 1[xi], şi acestea în funcţie de forma numărului (denormalizat sau normalizat), nu este nevoie să rezervăm un câmp special pentru caracteristică.

Forma normală a mantisei este cea normalizată, iar cea denormalizată este rezervată pentru a putea reprezenta valorile speciale.

Sumar:

1.      Bitul de semn este 0 pentru numere pozitive şi 1 pentru cele negative.

2.      Baza exponentului este 2, implicit.

3.      Câmpul exponentului conţine valoarea exponentului plus deplasare.

4.      Deplasarea este constantă pentru fiecare format de reprezentare şi este jumate din valoarea maximă posibilă a câmpului exponentului.

5.      Caracteristica totdeauna se consideră 1 pentru forma normalizată şi 0 pentru  cea denormalizată, implicit.

Capacitatea numerelor Floating-Point

Să examinăm puţin formatul float[xii]. Observaţi că în esenţă luăm un număr de 32 biţi şi manipulăm câmpurile lui pentru a acoperi un domeniu cât mai mare de valori. Ceva totuşi trebuie să se piardă, şi anume se pierde precizia. De exemplu, întregii obişnuiţi de 32 biţi, cu toată precizia centrată în jurul lui zero, pot cu exactitate să stocheze întregi cu o rezoluţie de 32 biţi. Floating-point, pe de altă parte, nu poate reprezenta această rezoluţie cu doar 24 biţi ai săi. Dar totuşi aproximează această valoare, tăind numărul din partea de jos. De exemplu:

  11110000 11001100 10101010 00001111 = // întreg de 32 biţi
= +1.1110000 11001100 10101010 x 231    = // float de 32 biţi
=  11110000 11001100 10101010 00000000   // valoarea corespunzătoare

Aceasta aproximează valoarea de 32 biţi, dar nu dă o reprezentare exactă. Pe de altă parte, în afară de capacitatea de a reprezenta componentele fracţionare (de care întregii sunt lipsiţi), valorile floating-point pot reprezenta numere în jurul lui 2127, în comparaţie cu valoarea maximă a întregilor de 32 biţi de aproximativ 232.

Sunt cinci valori distincte pe care numerele floating-point de 32 biţi nu le pot reprezenta[xiii]:

1.            Numerele negative mai mici ca -(2-2-23) × 2127                            (negative overflow)

2.            Numerele negative mai mari ca -2-149                                               (negative underflow)

3.            Zero

4.            Numerele pozitive mai mici ca 2-149                                                  (positive underflow)

5.            Numerele pozitive mai mari ca (2-2-23) × 2127                              (positive overflow)

Overflow (supraîncărcarea) înseamnă că valorile au crescut prea mari pentru reprezentare, foarte asemănător cum poţi supraîncărca întregii.

Underflow (subîncărcarea) e o problemă mai puţin importantă, deoarece ea denotă doar o pierdere a preciziei, care este garantată să fie aproape aproximată cu zero.

Valori Speciale

IEEE rezervă valorile exponentului cu toţi biţii 0 şi toţi biţii 1 pentru a indica valorile speciale în schema floating-point.

Zero

După cum s-a menţionat mai sus, zero nu este reprezentabil direct în forma simplă, datorită asumării că caracteristica normalizată este totdeauna 1 (vom avea nevoie să specificăm o caracteristică nulă pentru a produce valoarea zero). Zero este o valoare specială însemnată de câmpul exponentului umplut cu zero şi câmpul mantisei umplut cu zero. Observaţi că +–0 şi -0 sunt valori distincte, cu toate că ele ambele se compară ca egale.

Infinit

Valorile +infinit şi -–infinit sunt indicate de un exponent cu toţi biţii 1 şi o mantisă cu toţi biţii 0. Bitul de semn distinge infinitul pozitiv şi negativ. Capacitatea reprezentării infinitului ca o valoare specială este utilă, pentru că permite operaţiilor să continue după situaţii de overflow. Operaţiile cu valorile infinite sunt bine definite în standardul IEEE floating-point.

Not A Number (Nu e Număr)

Valoarea NaN (Not a Number) este folosită pentru a indica o valoare care nu reprezintă un număr adevărat. NaN-urile sunt reprezentate de o segvenţă specială de biţi cu câmpul exponentului umplut cu 1 şi o mantisă nenulă. Sunt două categorii de NaN: QNaN (Quiet NaN – tăcut) şi SNaN (Signalling NaN – alarmant).

QNaN este un NaN cu bitul semnificativ al mantisei setat. QNaN-urile se propagă liber prin cele mai multe operaţii aritmetice. Aceste valori rezultă din operaţie atunci când rezultatul nu este definit matematic.

Un SNaN este un NaN cu bitul semnificativ al mantisei gol. Se utilizează pentru a semnala o excepţie când se foloseşte în operaţii. SNaN-urile pot fi comode pentru a fi atribuite variabilelor neiniţializate, cu scopul de a capta utilizarea prematură.

Semantic, QNaN-urile denotă operaţii nedeterminate, în timp ce SNaN-urile denotă operaţii invalide.

Sumar

Tabelul ce urmează acoperă toate valorile posibile pe care le poate lua un număr în formatul floating-point, indicând pentru fiecare caz configuraţia câmpurilor de biţi:

Valorile Float

Semn

Exponent (e)

Mantisa (m)

Valoare

0

00..00

00..00

+0

0

00..00

00..01
. . .
11..11

Real Pozitiv Denormalizat
0.m × 2(-d+1)

0

00..01
. . .
11..10

XX..XX

Real Pozitiv Normalizat
1.m × 2(e-d)

0

11..11

00..00

+Infinit

0

11..11

00..01
. . .
01..11

SNaN

0

11..11

10..00
. . .
11..11

QNaN

1

00..00

00..00

-0

1

00..00

00..01
. . .
11..11

Real Negativ Denormalizat
-0.m × 2(-d+1)

1

00..01
. . .
11..10

XX..XX

Real Negativ Normalizat
-1.m× 2(e-d)

1

11..11

00..00

-Infinit

1

11..11

00..01
. . .
01..11

SNaN

1

11..11

10..00
. . .
11.11

QNaN

Spre deosebire de notaţiile utilizate anterior, aici e reprezintă valoarea câmpului exponentului, adică exponentul real plus deplasare (e := e + d).

 

Anexă

1.     Reprezentarea în formatul maşinii a numerelor floating-point[xiv]:

Semn

Exponent

Caracteristică

Mantisă

Float

1 [31]

8 [30-23]

–

23 [22-00]

Double

1 [63]

11 [62-52]

–

52 [51-00]

Long Double[xv]

1 [79]

15 [78-64]

1 [63]

63 [62-00]

2.     Deplasări:

 

Zecimal

Binar

Hexazecimal

Float (8 biţi)

127

0111 1111

7F

Double (11 biţi)

1023

011 1111 1111

3FF

Long Double (15 biţi)

16383

011 1111 1111 1111

3FFF

3.     Domeniul de valori:

Format [biţi]

Denormalizate

Normalizate

Aproximaţia zecimală

Float [32]

2-149 la (1-2-23)×2-126

2-126 la (2-2-23)×2127

~10-44.85 la ~1038.53

Double [64]

2-1074 la (1-2-52)×2-1022

2-1022 la (2-2-52)×21023

~10-323.3 la ~10308.3

Long Double [80]

2-16444 la (1-2-62)×2-16382

2-16382 la (2-2-62)×216383

~10-4950.14 la ~104931.69

Odată ce semnul numerelor floating-point este dat de bitul special din faţă, domeniul negativ al acestor numere se obţine prin negarea valorilor de mai sus.

4.     Operaţii Speciale:

Operaţiile cu numerele speciale sunt bine definite de către IEEE. În cel mai rău caz, orice operaţie cu un NaN dă un rezultat NaN. Alte operaţii sunt după cum urmează:

Operaţia

Rezultatul

n ÷ ±Infinit

0

±Infinit × ±Infinit

±Infinit

±nonzero ÷ 0

±Infinit

Infinit + Infinit

Infinit

±0 ÷ ±0

NaN

Infinit - Infinit

NaN

±Infinit ÷ ±Infinit

NaN

±Infinit × 0

NaN

 

Cuprins:


Introducere
Forma de stocare în memorie
Capacitatea numerelor Floating-Point
Valori Speciale
Sumar
Anexă

 


[i] Floating-point se traduce „punct plutitor”. În calculatoare pentru separarea părţi fracţionare în număr se foloseşte punctul, nu virgula, deoarece în multe ţări, inclusiv SUA, se utilizează anume această notaţie.

[ii] Partea fracţionară a numărului.

[iii] În formatul maşinii baza de numeraţie este 2. Iar 10 în baza doi este 2 în baza zece (102 = 210), de aceea nu voi specifica explicit baza numerelor în exemple, ci voi considera că 10 este în baza 2.

[iv] Partea întreagă a numărului.

[v] Vezi anexa – 1

[vi] if (nr < 0)  then s = 1 else if (nr > 0) then s = 0

[vii] –|nr| = not |nr| 1.

De ex., nr. -2 pe 4 biţi se reprezintă astfel: -0010 = not 0010 1 = 1101 1 = 1110. Astfel -2 2 =0 este acelaşi lucru cu 1110 0010 = 0000 şi overflow.

[viii] d = max{e} div 2. Vezi anexa – 2

[ix] Normalizată:    (-1)s × 1.m × 10e
  Denormalizată: (-1)s × 0.m × 10e

[x] if (d e = 0) then c = 0  else c = 1

[xi] Caracteristica nu poate avea alte valori, având la dispoziţie doar o cifră binară. Deci este 1 când reprezintă o cifră şi 0 când nu reprezintă nici o cifră.

[xii] Vezi anexa – 3

[xiii] Se are în vedere forma normalizată a numărului, care este forma standard.

[xiv] În parantezele parate se indică biţii pe care se reprezintă numărul

[xv] Acest format este un caz particular, deoarece el se foloseşte de către coprocesor pentru efectuarea operaţiilor cu numerele reale şi de acea caracteristica se reprezintă explicit (un bit).

News

arr_d Limba / Language


 


arr_r Login

Flag Counter