1. Rotunjirea numerelor reale
După cum am discutat deja, atunci când un număr real este atribuit unei int
variabile, acesta este întotdeauna rotunjit în jos la cel mai apropiat număr întreg mai mic - partea fracțională este pur și simplu aruncată.
Dar este ușor să ne imaginăm o situație în care un număr fracționar trebuie rotunjit la cel mai apropiat număr întreg în orice direcție sau chiar rotunjit în sus. Ce faci in acest caz?
Pentru aceasta și pentru multe situații similare, Java are clasa Math
, care are metodele round()
, ceil()
și floor()
.
Math.round()
metodă
Metoda Math.round()
rotunjește un număr la cel mai apropiat număr întreg:
long x = Math.round(real_number)
Dar există o altă nuanță aici: această metodă returnează un long
număr întreg (nu un int
). Deoarece numerele reale pot fi foarte mari, creatorii Java au decis să folosească cel mai mare tip întreg disponibil din Java: long
.
În consecință, dacă un programator dorește să atribuie rezultatul unei int
variabile, atunci ea trebuie să indice în mod explicit compilatorului că acceptă posibila pierdere de date (în cazul în care numărul rezultat nu se încadrează într-un int
tip).
int x = (int) Math.round(real_number)
Exemple:
Afirmație | Rezultat |
---|---|
|
|
|
|
|
|
Math.ceil()
metodă
Metoda Math.ceil()
rotunjește un număr la un număr întreg. Iată exemple:
Afirmație | Rezultat |
---|---|
|
|
|
|
|
|
Math.floor()
metodă
Metoda Math.floor()
rotunjește un număr la un număr întreg. Iată exemple:
Afirmație | Rezultat |
---|---|
|
|
|
|
|
|
Desigur, atunci când rotunjiți un număr la un număr întreg, este mai ușor să utilizați pur și simplu un operator de tip cast:(int)
Afirmație | Rezultat |
---|---|
|
|
Dacă vă este dificil să vă amintiți aceste nume, o scurtă lecție de engleză vă va ajuta:
Math
înseamnă matematicăRound
înseamnă rotundCeiling
înseamnă tavanFloor
înseamnă podea
2. Cum sunt structurate numerele în virgulă mobilă
Tipul double
poate stoca valori în intervalul de la până la . Această gamă uriașă de valori (în comparație cu tipul) se explică prin faptul că tipul (precum și ) are o structură internă complet diferită de tipurile întregi. Pe plan intern, tipul își codifică valoarea ca două numere: primul se numește mantisa , iar al doilea se numește exponent .-1.7*10308
+1.7*10308
int
double
float
double
Să presupunem că avem numărul 123456789
și îl stocăm într-o double
variabilă. Când o facem, numărul este convertit în , iar în interior tipul stochează două numere — și . Semnificativul („partea semnificativă a numărului” sau mantisa) este evidențiat cu roșu, în timp ce exponentul este evidențiat cu albastru.1.23456789*108
double
23456789
8
Această abordare face posibilă stocarea atât a unor numere foarte mari, cât și a celor foarte mici. Dar pentru că reprezentarea numărului este limitată la 8 octeți (64 de biți) și unii dintre biți sunt utilizați pentru a stoca exponentul ( precum și semnul mantisei și semnul exponentului), cifrele maxime disponibile pentru a reprezenta mantisa . este 15 .
Aceasta este o descriere foarte simplificată a modului în care sunt structurate numerele reale.
3. Pierderea preciziei la lucrul cu numere reale
Când lucrați cu numere reale, rețineți întotdeauna că numerele reale nu sunt exacte . Pot exista întotdeauna erori de rotunjire și erori de conversie la conversia de la zecimal la binar. În plus, cea mai comună sursă de eroare este pierderea preciziei la adunarea/scăderea numerelor la scări radical diferite.
Acest ultim fapt este puțin uimitor pentru programatorii începători.
Dacă scadem din , obținem .1/109
109
109
Scăderea numerelor pe scări radical diferite | Explicaţie |
---|---|
|
Al doilea număr este extrem de mic , ceea ce va face ca semnificația sa (evidențiată cu gri) să fie ignorată. Cele 15 cifre semnificative sunt evidențiate cu portocaliu. |
Ce putem spune, programarea nu este la fel cu matematica.
4. Capcană la compararea numerelor reale
Un alt pericol îl așteaptă pe programatori atunci când compară numerele reale. Apare atunci când lucrați cu numere reale, deoarece se pot acumula erori de rotunjire. Rezultatul este că există situații în care se așteaptă ca numerele reale să fie egale, dar nu sunt. Sau invers: se așteaptă ca numerele să fie diferite, dar sunt egale.
Exemplu:
Afirmație | Explicaţie |
---|---|
|
Valoarea variabilei a va fi 1000000000.0 Valoarea variabilei c va fi 1000000000.0 (numărul din b variabilă este excesiv de mic) |
În exemplul de mai sus, a
și c
nu ar trebui să fie egale, dar sunt.
Sau să luăm un alt exemplu:
Afirmație | Explicaţie |
---|---|
|
Valoarea variabilei a va fi 1.0 Valoarea variabilei b va fi1.0 |
5. Un fapt interesant desprestrictfp
Java are un cuvânt cheie special (strictfp
strict floating point ) , care nu se găsește în alte limbaje de programare. Și știi de ce ai nevoie? Înrăutățește acuratețea operațiunilor cu numere în virgulă mobilă . Iată povestea cum a apărut:
GO TO FULL VERSION