Sunteți pe pagina 1din 13

Metode Numerice – Curs 4

III.2.2. Reprezentarea în virgulă mobilă

Una dintre cele mai răspândite reprezentări internă (în PC-uri) a numerelor
reale este reprezentarea în virgulă mobilă. Reprezentarea în virgulă mobilă
presupune existenţa unei baze b (întotdeauna presupusă pară) şi a unei precizii p.
Un număr în virgulă mobilă este un număr de forma
α1 α 2 α p −1
±(α0 + + 2 +…+ p −1 )bE, αk ∈ {0, 1, ...b-1} pentru orice k = 0, p − 1 , E ∈Z.
b b b
Mai precis, denumirea de număr în virgulă mobilă va fi utilizată pentru numerele
reale care se reprezintă exact sub forma de mai sus. În această reprezentare α0, α1,
…, αp-1 se numesc cifre semnificative. Fiecărei reprezentări în virgulă mobilă i se
asociază două numere întregi, Emin şi Emax, ce reprezintă valorile limită permise
pentru exponentul E (Emin ≤ E ≤ Emax). Tabelul de mai jos exemplifică cei patru
parametri (baza, precizia, valorile limită ale exponentului) ce caracterizează
reprezentarea în virgulă mobilă în diverse sisteme

Sistem baza b precizia p Emin Emax


IEEE single-precission 2 24 -126 127
IEEE double-precission 2 53 -1022 1023
Cray 2 48 -16383 16384
calculator HP 10 12 -499 499
mainframe IBM 16 6 -64 63

Reprezentarea în virgulă mobilă se numeşte normalizată dacă se impune condiţia ca


cifra cea mai semnificativă α0 să fie nenulă. Reprezentarea normalizată are
următoarele avantaje:
• reprezentarea fiecărui număr este unică
• nu de pierd cifre pentru reprezentarea primele zerourilor de la dreapta
virgulei

1
Mădălina Roxana Buneci Metode Numerice – Curs - 2007

• în sistemele binare (corespunzătoare bazei b =2) prima cifră poate să nu mai


fie stocată (deoarece este întotdeauna 1).
Restricţia α0 ≠ 0, face imposibilă reprezentarea lui zero. O reprezentare naturală a
lui zero este 1,0⋅ b E min −1 .
Numărul de numere în virgulă mobilă normalizată este
2(b-1)bp-1(Emax - Emin +1).
Cel mai mic număr pozitiv normalizat se notează UFL (underflow level) şi este
E min
UFL = b .
Cel mai mare număr normalizat se notează OFL (overflow level) şi este
b −1 b −1 b −1 E
OFL = (b-1 + + 2 +…+ p−1 ) b max
b b b
E max +1 1
=b (1 - ).
bp
Ca urmare nu toate numerele reale sunt reprezentabile exact. Numerele prea mari
pentru a fi reprezentate corespund unei depăşiri superioare de capacitate (overflow),
iar numerele prea mici unei depăşiri inferioare de capacitate (underflow). Pentru a
fi reprezentat un număr real x este aproximat cu un număr în virgulă mobilă pe care
convenim să-l notăm fl(x). Aproximarea lui x prin fl(x) poartă numele de rotunjire,
iar eroarea introdusă de eroare de rotunjire. Există mai multe modalităţi pentru
rotunjire:
• trunchiere (rotunjire prin tăiere): se reţin primele p cifre din reprezentarea
α1 α 2 α p −1
normalizată a lui x = ± (α0 + + 2 +…+ p −1 + …)bE; deci
b b b
α1 α 2 α p −1
fl(x) = ± (α0 + + 2 +…+ p −1 )bE.
b b b
• rotunjire la cel mai apropiat număr în virgulă mobilă (rotunjire la par):
fl(x) este cel mai apropiat număr în virgulă mobilă de x; în caz de egalitate
(dacă există două numere în virgulă mobilă egal depărtate de x) se consideră
acel număr în virgulă mobilă a cărui ultimă cifră este pară.
Rotunjirea la par determină o acurateţe mai mare a reprezentării. Acurateţea
sistemului în virgulă mobilă este caracterizată de aşa numita precizie a maşinii (sau

2
Metode Numerice – Curs 4

epsilon maşină), notată εmach. Precizia a maşinii este definită ca cel mai mic număr
pozitiv ε cu proprietatea că
fl(1.+ ε) > 1.
Dacă regula de rotunjire este trunchierea atunci
εmach = b1 - p,
iar dacă regula de rotunjire este rotunjirea la par atunci
1 1- p
εmach = b .
2
Eroarea relativă maximă cu care fl(x) aproximează x este dată de
fl(x ) − x
≤ εmach.
x
Deşi amândouă sunt "mici", precizia maşinii (εmach) şi cel mai mic număr pozitiv
normalizat UFL (în reprezentare în virgulă mobilă fixată) nu trebuie confundate. De
obicei Emin < -p şi deci între ele există relaţia
0 < UFL < εmach < OFL.
Fie x un număr real aproximat de
α1 α 2 α p −1
fl(x) =±(α0 + + 2 +…+ p −1 )bE.
b b b
Exponentul E poate lua atât valori pozitive cât şi valori negative. Cel mai adesea
exponentul este “decalat “ şi reprezentat ca un număr întreg pozitiv (fără semn).
Aceasta deoarece ordinea lexicografică (stabilită între şirurile de cifre din
reprezentare) şi ordinea naturală sunt compatibile în cazul numerelor întregi fără
semn. În consecinţă, compararea exponenţilor (şi a numerelor reale
corespunzătoare) poate fi făcută eficient. Astfel reprezentarea internă a unui număr
α1 α 2 α p −1
real x aproximat prin fl(x) = ± (α0 + + 2 +…+ p −1 )bE se face sub forma
b b b

s ed α0α1…αp-1

3
Mădălina Roxana Buneci Metode Numerice – Curs - 2007

unde s este semnul lui x (se completează cu 0 dacă semnul este + şi cu 1 dacă
semnul este -) iar ed este exponentul obţinut prin adunarea unui decalaj D la
exponentul E:
ed = E + D.

III.2.3. Standardul IEEE-754

IEEE este acronim pentru Institute of Electrical and Electronics Engineers,


o organizaţie ce are drept principal scop elaborarea standardelor pentru produsele
hardware şi software. Standardul IEEE-754 se referă la aritmetica în virgulă mobilă
în sistemele binare. Acest standard precizează formatul de reprezentare în memorie
în simplă şi dublă precizie a unui număr real. Reprezentarea se face în virgulă
mobilă normalizată:
α1 α 2 α p −1
x ≈ fl(x) = ± (1 + + 2 +…+ p −1 )2E, p = 24, 53.
2 2 2
Sunt admise şi aşa numitele numere denormalizate ("denormalized floating-point
numbers"):
α1 α 2 α p −1
± (0 + + 2 +…+ p −1 )2E, p = 24, 53,
2 2 2
cu cel puţin una dintre cifrele binare α1, α2, …, αp-1 nenule.
Standardul IEEE-754 defineşte două valori speciale pentru situaţii excepţionale:
• Inf, pe post de "infinit" ("infinity"), pentru rezultatul împărţirii unui număr
finit la zero.
• NaN, pe post de "non-număr" ("not a number"), pentru rezultatul
următoarelor operaţii
▹ Adunare : Inf + (-Inf)
▹ Înmulţire: 0⋅Inf
▹ Împărţire: 0/0 sau Inf/Inf
▹ Calculul restul împărţirii unui număr x la 0 sau a lui Inf la x
▹ Calculul rădăcinii pătrate x pentru x < 0.
Scopul acestor valori este acela de a permite continuarea calculului.

4
Metode Numerice – Curs 4

α1 α 2 α p −1
Un număr în virgulă mobilă ±(α0 + + 2 +…+ p −1 )2E se reprezintă intern
2 2 2
conform IEEE-754 sub forma

s ed α1…αp-1

unde pentru s se rezervă un bit ce se completează cu 0 dacă numărul este pozitiv şi


cu 1 dacă numărul este negativ, iar pentru exponentul decalat ed se rezervă k biţi
(k=8, 11). Decalajul considerat este D = 2k-1 - 1, deci
ed = E + 2k-1 -1,
Pe k biţi se pot reprezenta ca numere întregi fără semn 2k valori, de la 0 la 2k
– 1. Valorile 0 şi 2k – 1 sunt rezervate pentru numerele denormalizate şi pentru
valorile speciale Inf şi Nan. Deci pentru un număr în virgulă mobilă normalizată
trebuie îndeplinită condiţia 1 ≤ ed ≤ 2k-2. De aici rezultă că -2k-1+2 ≤ E ≤ 2k-1-1. De
exemplu, pe k = 8 biţi se pot reprezenta numere întregi fără semn de la 0 la 255.
Decalajul considerat este 27 - 1 = 127, deci exponentul E ia valori de la – 126 la
127. Numărul de biţi rezervaţi pentru exponent determină intervalul de numere reale
reprezentabile în calculator. Numărul de biţi rezervaţi pentru mantisă determină
precizia de reprezentare (gradul de detaliere) a numerelor. Reprezentarea ±(α0 +
α1 α 2 α p −1
+ 2 +…+ p −1 )2E fiind normalizată, există siguranţa că α0 = 1, ceea ce
2 2 2
permite omiterea sa (bit ascuns) pentru creşterea preciziei de reprezentare, dar
complică prelucrarea informaţiei.
Formatele de reprezentare a numerelor în virgulă mobilă (conform standardului
IEEE 754) sunt:
• simplă precizie (single-precission) pe 32 de biţi:
• 1 bit pentru semnul mantisei
• 8 biţi pentru exponentul decalat (Emin = -126, Emax = 127)
• 23 biţi pentru mantisă (p = 24, α0 = 1 se omite)
• dublă precizie (double-precission) pe 64 de biţi
• 1 bit pentru semnul mantisei
• 11 biţi pentru exponentul decalat (Emin = -1022, Emax = 1023)

5
Mădălina Roxana Buneci Metode Numerice – Curs - 2007

• 52 biţi pentru mantisă (p = 53, α0 = 1 se omite)


Regula de rotunjire este rotunjirea la par. Deci pentru
• simplă precizie, εmach = 2-24 ≈ 10-7 (7 cifre zecimale semnificative).
• dublă precizie, εmach = 2-53 ≈ 10-16 (16 cifre zecimale semnificative).

Considerăm o reprezentare în memorie, în simplă precizie:

s e7e6e5e4e3e2e1e0 α1 α2 α23

α1 α 2 α 23
Fie ed = e0 + e12 + e222 + … + e727 şi m = + 2 +…+ 23 . Valoarea v
2 2 2
reprezentată se determină după cum urmează:
▹ dacă 0 < ed < 255, atunci v = (-1)s⋅(1 + m)⋅2ed - 127.

▹ dacă ed = 0, αk = 0 pentru orice k= 1,23 şi s = 0, atunci v = 0.

▹ dacă ed = 0, αk = 0 pentru orice k= 1,23 şi s = 1, atunci v = - 0.

▹ dacă ed = 0 şi există αk ≠ 0, atunci v = (-1)s⋅ m ⋅2 - 126


; v este o valoare
denormalizată
▹ dacă ed = 255, αk = 0 pentru orice k= 1,23 şi s = 0, atunci v = Inf.

▹ dacă ed = 255, αk = 0 pentru orice k= 1,23 şi s = 1, atunci v = -Inf.

▹ dacă ed = 255 şi există αk ≠ 0, atunci v = NaN.

Fie reprezentarea în memorie, în dublă precizie:

s e10e9 …e0 α1 α2 α52

α1 α 2 α 52
Fie ed = e0 + e12 + e222 + … + e10210 şi m = + 2 +…+ 52 . Valoarea v
2 2 2
reprezentată se determină după cum urmează:
▹ dacă 0 < ed < 2047, atunci v = (-1)s⋅(1 + m)⋅2ed - 1023.

▹ dacă ed = 0, αk = 0 pentru orice k= 1,52 şi s = 0, atunci v = 0.

6
Metode Numerice – Curs 4

▹ dacă ed = 0, αk = 0 pentru orice k= 1,52 şi s = 1, atunci v = - 0.

▹ dacă ed = 0 şi există αk ≠ 0, atunci v = (-1)s⋅ m ⋅2 - 1022


; v este o valoare
denormalizată
▹ dacă ed = 2047, αk = 0 pentru orice k= 1,52 şi s = 0, atunci v = Inf.

▹ dacă ed = 2047, αk = 0 pentru orice k= 1,52 şi s = 1, atunci v = -Inf.

▹ dacă ed = 2047 şi există αk ≠ 0, atunci v = NaN.


Exemple:
Să se reprezinte în simplă precizie numerele: 228,15 - 27, 25 0,1 1,2
x = 228,15
x = 228 + 0,15
228 = 128 + 64 + 32 + 4 = 27 + 26 +25 +22 = 111001002
0,15 ⋅ 2 = 0,30 = 0 + 0,3
0,3 ⋅ 2 = 0,6 = 0 + 0,6
0,6 ⋅ 2 = 1,2 = 1 + 0,2
0,2 ⋅ 2 = 0,4 = 0 + 0,4
0,4 ⋅ 2 = 0,8 = 0 + 0,8
0,8 ⋅ 2 = 1,6 = 1 + 0,6

x = 11100100,00100110011001…
Forma normalizată:
x = 0,111001000010011001…⋅ 28 = 1,11001000010011001…⋅ 27
ed = 7 + 28-1 - 1 = 135, ed2 = 100001102
m = 11001000010011001100110 [011]
(am omis primul bit =1, iar cei trei biţi din paranteză sunt utilizaţi pentru rotunjire la
par)
fl(x) = 1, 11001000010011001100110⋅ 28
Reprezentare în virgulă mobilă, simplă precizie, (cu bit ascuns) pentru 228,15:

0 100 0011 0 110 0100 0010 0110 0110 0110


4 3 6 4 2 6 6 6

7
Mădălina Roxana Buneci Metode Numerice – Curs - 2007

Deci reprezentării cu bit ascuns a lui 228,15 îi corespunde 43642666 în


hexazecimal.
x = - 27, 25
|x| = 27 + 0,25
27 = 16 + 8 + 2 + 1 = 24 + 23 +21 +20 = 110112
0,25 = 2-2 = 0,012
x = 11011,01
Forma normalizată: x = 0,1101101× 25 = 1,101101× 24
ed = 4 + 28-1 -1 = 131, ed2 = 100000112
Reprezentare în virgulă mobilă, simplă precizie (cu bit ascuns) pentru –27,25:

11000001110110100000000000000000
C 1 D A 0 0 0 0
Deci reprezentării cu bit ascuns a lui -27,25 îi corespunde C1DA0000 în
hexazecimal.
x = 0,1
0,1 ⋅ 2 = 0,2
0,2 ⋅ 2 = 0,4
0,4 ⋅ 2 = 0,8
0,8 ⋅ 2 = 1,6 = 1 + 0,6
0,6 ⋅ 2 = 1,2 = 1 + 0,2
0,2 ⋅2 = 0,4
0,110 = 0, 00011001100110011…
x = 0, 110011001100…⋅2-3 = 1,10011001100110011001100 110…⋅2-4
fl(x) =1, 10011001100110011001101 ⋅ 2-4
(după cei 23 de biţi ai mantisei urmează 110, şi deci rotunjirea se face prin
adăugarea unei unităţi).
ed = - 4 + 28-1 -1 = 123 = 26 + 25 + 24 + 23 + 2 + 1 , ed2 = 11110112
Reprezentare în virgulă mobilă, simplă precizie (cu bit ascuns) pentru 0,1:

0 0 1 1 11 0 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1
3 D C C C C C D

8
Metode Numerice – Curs 4

Deci reprezentării cu bit ascuns a lui 0,1 îi corespunde 3DCCCCCD în hexazecimal.


x = 1,2
1,2 = 1 + 0,2
0,2 ⋅ 2 = 0,4
0,4 ⋅ 2 = 0,8
0,8 ⋅ 2 = 1,6 = 1 + 0,6
0,6 ⋅ 2 = 1,2 = 1 + 0,2
0,2 ⋅2 = 0,4
x = 1, 0011001100110011…
x = 1,00110011001100110011001 100…⋅20
fl(x) =1,00110011001100110011010 ⋅ 20
(după cei 23 de biţi ai mantisei urmează 100, deci rotunjirea se face astfel încât
ultimul bit să aibă valoare pară).
ed = 0 + 28-1 -1 = 127 = 26 + 25 + 24 + 23 + 22 +2 +1 , ed2 = 11111112
Reprezentare în virgulă mobilă, simplă precizie (cu bit ascuns) pentru 1,2:

0 0 1 1 11 1 1 1 0 0 1 1 0 01 1 0 01 1 0 01 1 0 01 1 0 1 0
3 F 9 9 9 9 9 A
Deci reprezentării cu bit ascuns a lui 1,2 îi corespunde 3F99999A în hexazecimal.

Următorul program în C verifică reprezentările de mai sus.

#include <stdio.h>
#include <conio.h>
void main(){
long int *i;
float f1=228.15,f2=-27.25, f3=0.1, f4=1.2;
clrscr();
i=(long int*) &f1;
printf("\nNumar in virgula mobila:%f\n\tFormat intern %08lX
(hexazecimal)",f1,*i);
i=(long int*) &f2;
printf("\nNumar in virgula mobila:%f\n\tFormat intern %08lX
(hexazecimal)",f2,*i);

9
Mădălina Roxana Buneci Metode Numerice – Curs - 2007

i=(long int*) &f3;


printf("\nNumar in virgula mobila:%f\n\tFormat intern %08lX
(hexazecimal)",f3,*i);
i=(long int*) &f4;
printf("\nNumar in virgula mobila:%f\n\tFormat intern %08lX
(hexazecimal)",f4,*i);
getch();
}

Programul afişează

Numar in virgula mobila: 228.149994


Format intern 43642666 (hexazecimal)
Numar in virgula mobila: -27.250000
Format intern C1DA0000 (hexazecimal)
Numar in virgula mobila: 0.100000
Format intern 3DCCCCCD (hexazecimal)
Numar in virgula mobila: 1.200000
Format intern 3F99999A (hexazecimal)

III.2.4. Aritmetica în virgulă mobilă

Din secţiunea precedentă rezultă că nu toate numerele reale pot fi


reprezentate exact într-un sistem în virgulă mobilă. De asemenea în urma evaluării
unei expresii ai cărei operanzi sunt reprezentabili rezultatul obţinut nu este neapărat
reprezentabil. În mod ideal
x flop y = fl(x op y)
unde op este un operator binar (+, - , *, /), iar flop desemnează corespondentul
operatorului respectiv în aritmetica în virgulă mobilă. Sistemele ce satisfac
standardul IEEE-754 ating acest ideal în situaţia în care x op y se găseşte în
intervalul de numere reale reprezentabile [UFL, OFL].
Depăşirea superioară de capacitate (overflow) cauzează de obicei probleme
mai serioase decât depăşirea inferioară de capacitate (underflow), deoarece nu
există nici o aproximaţie bună pentru un număr real oarecare "mare". Un număr

10
Metode Numerice – Curs 4

real foarte mic poate fi în mod rezonabil aproximat cu zero. Pe multe sisteme de
calcul depăşirea superioară de capacitate este fatală, în timp ce în caz de depăşire
inferioară de capacitate, numărul respectiv este asociat cu zero.
Anumite legi ale aritmeticii reale nu sunt valabile într-un sistem în virgulă
mobilă. Astfel adunarea şi înmulţirea în virgulă mobilă sunt comutative, dar nu
asociative. De exemplu, dacă ε este un număr pozitiv mai mic decât εmach, dar mai
mare decât εmach/2, atunci
(1 + ε) + ε = 1, iar 1 + (ε + ε) > 1.
Rezultatul unei operaţii în virgulă mobilă poate să fie semnificativ diferit
faţă de rezultatul aceleaşi operaţii în aritmetica exactă. Să considerăm numărul real
1
x = . Se reprezintă în baza 2, prin x = 0,0001100110011…=1,
10
10011001100110011001101…2-4. În simplă precizie este aproximat de fl(x) = 1,
10011001100110011001101⋅2-4, ceea ce introduce o eroarea de
0.000000000000000000000000011001100 în binar sau aproximativ 0.000000047 în
zecimal. Programul în C de mai jos pune în evidenţă cum se propagă această eroare
prin înmulţire:

#include <stdio.h>
#include <conio.h>
void main(){
float f=1./10,z=10;
int i;
clrscr();
for(i=1;i<33;i*=2){
printf("\n0.1*10^%d-10^%d = %f ",i+1,i,f*(z*10)-z);
z=z*z;
}
getch();
}
Programul afişează
0.1*10^2 - 10^1 = 0.000000
0.1*10^3 - 10^2 = 0.000001
0.1*10^5 - 10^4 = 0.000149

11
Mădălina Roxana Buneci Metode Numerice – Curs - 2007

0.1*10^9 - 10^8 = 1.490116


0.1*10^17 - 10^16 = 149011616.000000
0.1*10^33 - 10^32 = 1490116168828835360000000.000000
1
Membrul drept ar fi trebuit să fie 0, deoarece ⋅10i+1 - 10i =0.
10
În cazul scăderii a două numere reale x şi y, poate apărea următorul fenomen
(catastrophic cancellation)
(fl(x ) − fl(y )) − fl(x − y )
 εmach,
fl(x − y )

dacă fl(x) este egal (sau foarte apropiat de) fl(y). În următorul program (în C)
aproximăm sin(x) printr-o sumă parţială a seriei

(− 1)n
∑ (2n + 1)! x 2 n +1
n =0

Seria fiind alternantă şi convergentă, o sumă parţială de ordin n, aproximează suma


2 n +1
x
seriei (i.e. sin(x)) cu o eroare absolută maximă de . Programul de mai jos
(2n + 1)!
reprezintă versiunea în C pentru calculul sumei care aproximează sin(x):

#include<stdio.h>
#include<conio.h>
#include<math.h>
void main(){
float x,s,t,eps,x2;
int i,n;
clrscr();
printf("x=");scanf("%f",&x);
printf("Eroarea=");scanf("%f",&eps);
t=x;s=0;i=1; x2=x*x;
while (fabs(t)>=eps){
s+=t;printf("\n%f",s);
t=-t*(x2/(4*i*i+2*i));
i++;
}
printf("\nsin(%f) = %f",x,s);
printf("\nsin(%f) = %f" ,x,sin(x));

12
Metode Numerice – Curs 4

getch();
}
Pentru x=2 şi eroare 10-7 se obţine aproximaţia 0.909297 corectă a lui sin(2).
Pentru x = 40 şi eroare 10-7 se obţine aproximaţia 523443136.0 a lui sin(40) !
Valoarea corectă este 0.745113…Acest rezultat se datorează fenomenului de
reducere (catastrophic cancellation).

13

S-ar putea să vă placă și