Întrucât caracterele se codifică în memoria calculatorului prin
numere întregi fără semn, în limbajul Java asupra lor se pot aplica
toate operațiile pentru numere întregi. Totusi, datorită
particularităților pe care le prezintă, noi vom trata tipul char
separat.
Tipul | Lungimea | Intervalul de valori |
byte | 1 octet (8 biți) | [-128, 127] |
short | 2 octeți (16 biți) | [-32768, 32767] |
int | 4 octeți (32 biți) | [-2147483648, 2147683647] |
long | 8 octeți (64 biți) | [-9223372036854775808, 9223372036854775807] |
Se observă, deci, că deosebirea dintre diferitele tipuri de date
întregi constă în lungimea reprezentării lor interne, care condiționează
și mulțimea de valori a tipului respectiv. Este evident că mulțimea de
valori a fiecăruia din aceste tipuri este numai o submulțime a mulțimii
numerelor întregi.
Reprezentarea internă a datelor de tip byte,
short, int si long se face sub forma de numere întregi cu
semn, în sistemul de numerație binar. Primul bit
al reprezentării interne este interpretat drept semn (0 pentru + si
1 pentru -). Numerele întregi pozitive se reprezintă, deci,
prin numere binare care încep cu cifra 0. Numerele întregi negative se
reprezintă prin complementul la doi al modulului lor.
Avand în vedere că cu n cifre în baza 2 se pot reprezenta 2n valori, se obțin domeniile de valori indicate în tabelul de mai sus. De exemplu, pentru tipul byte există 28=256 valori. Limitele domeniilor de valori pentru fiecare tip întreg se pot
exprima în binar în funcție de numărul de biți astfel:
|
În sistemul zecimal, literalii întregi sunt șiruri de cifre
zecimale care pot fi precedate de semn și nu conțin în interiorul lor
separatori, cum sunt punctul, virgula sau apostroful (care se folosesc
de noi în scrierea uzuală a numerelor) și nu incep cu cifra 0.
Exemple corecte de literali întregi în sistemul zecimal: - de tip int: 0 -5 276315 -176426 - de tip long: 0L -5L 3567286542987L Exemple de literali întregi scriși greșit: |
În sistemul octal, literalii întregi sunt numere cu sau fără
semn, scrise în sistemul de numerație octal (cu baza opt) și care încep
cu cifra 0. Amintim că cifrele sistemului octal sunt 0, 1, 2, 3, 4,
5, 6, 7.
Exemple de literali corecți în sistemul octal: 016724 -04507 |
În sistemul hexazecimal, literalii întregi sunt numere cu sau
fără semn, scrise în sistemul de numerație hexazecimal (cu baza 16) și
care încep cu prefixul 0x. Amintim că cifrele sistemului
hexazecimal sunt: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. În
locul majusculelor se pot folosi și minusculele corespunzătoare.
Exemple de literali corecți în sistemul hexazecimal: 0x37B2E -0x2ab7f3 |
Sistemele octal și hexazecimal prezintă avantajul că au ca
baze puteri ale lui 2. Din această cauză, conversia din aceste sisteme
de numerație în binar pentru numerele pozitive se face simplu: fiecare
cifra octală se reprezintă în binar prin trei biți, iar fiecare cifră
fexazecimală prin patru biți.
|
Exemplu Să considerăm urmatoarea aplicație din fișierul CastInt.java.
Compilând și rulând pe calculator această aplicație obținem următorul rezultat afișat pe ecran:
- valorile variabilelor i3 și i4 au fost atribuite corect, deoarece conversia s-a făcut de la lungimea de un octet la cea de 4 octeți, astfel că nu s-au alterat valorile; - valorile variabilelor b3 și b4 au fost atribuite corect, deși conversia s-a făcut prin (cast) de la lungimea de 4 octeți la cea de 1 octet. Explicația este că valorile atribuite se încadrau în intervalul de valori permise pentru tipul byte; - în cazul variabilei b5 s-a atribuit valoarea -77, deși în instrucțiunea b5=(byte)i3 variabila i3 are valoarea 22195. Prin conversie s-au modificat deci atât valoarea, cât și semnul, deoarece 22195 nu se încadrează în mulțimea de valori a tipului byte.
|
Tipul rezultatului operațiilor aritmetice cu numere
întregi se stabileste astfel: a/ în cazul operațiilor de incrementare (++) și decrementare (--) tipul rezultatului este același cu tipul operandului; b/ pentru toate celelalte operații, dacă cel puțin unul din operanzi este de tip long, atunci rezultatul este de tip long; altfel, rezultatul este de tip int. Remarcăm, deci, că singurele operații aritmetice care pot da rezultat de tip byte sau short sunt cele de incrementare sau decrementare. Împarțirea întreagă O consecință a modului de stabilire a rezultatului operațiilor aritmetice este că, atunci când se face o operație de împărțire (/) între două numere întregi, rezultatul este un numar întreg (de tip int sau long, după caz). La împărțire se calculează, deci, numai partea întreagă a câtului. Excepția de împărțire la zero Este posibil ca, în operatia de împarțire întreagă, al doilea
operand (împărțitorul) să fie egal cu zero. În acest caz, mașina
virtuală Java generează o excepție de împărțire la zero, care
face parte din clasa ArithmeticException. În programul de mai
jos, din fișierul ImpartireZero.java,
se testează o astfel de situație.
Se observă că în expresia a/b opeandul b are
valoarea zero. La executarea acestui program se afișeaza pe ecran
următorul mesaj:
Acest mesaj se interpretează astfel: s-a produs o excepție din clasa ArithmeticException în firul de execuție "main"; excepția constă în împărțire (/) la zero și a apărut în metoda main a clasei ImpartireZero, fiind localizată în fișierul sursă ImpartireZero.java linia 6. Se poate constata cu ușurință că, într-adevar, operația care a produs excepția se găsește în locul indicat. Înlocuind în acest fișier operația a/b prin c/b (astfel încât ambii operanzi sunt nuli) caonstatăm că, dacă repetăm compilarea și execuția, obținem aceeași excepție. Așa dar, la depistarea excepției de împărțire la zero, mașina virtuală Java testează numai împărțitorul, nu și deîmpărțitul. Depășirea binară La efectuarea unor operații cu numere întregi este posibil ca rezultatul să fie un numar binar mai lung decât spațiul alocat în memorie pentru tipul de date respectiv. De exemplu, dacă se înmulțesc două numere de tip int (reprezentate pe 32 biți fiecare), rezultatul poate fi un numar mai lung de 32 biți, deci a cărui valoare nu se mai încadrează în mulțimea de date a tipului int. O astfel de situație se numește depășire binară. În limbajul Java, apariția depășirii binare nu este considerată o excepție, ci calculul continuă, dar se rețin numai octeții din dreapta ai rezultatului, atâți cât corespund reprezentării interne a tipului de date respectiv (4 octeți pentru int și 8 octeți pentru long). În consecința se pierd octeții cei mai semnificativi și are loc, deci, modificarea valorii și chiar a semnului rezultatului, la fel ca în cazul conversiei de la un tip cu lungime mai mare la unul cu lungime mai mică. Exemplu
Remarcăm că la calcularea valorilor variabilelor b3, b4 și s3 a fost necesar să se folosească conversia explicită (cast), deoarece valorile expresiilor din paranteze din partea dreaptă a operandului de atribuire sunt de tip int, în timp ce variabilele din partea stânga sunt de tip byte sau short. În mod similar s-a folosit castul la calcularea lui i5, deoarece expresia m2/m1 este de tipul long. Se poate constata cu usurință, suprimând din program operatorii cast din expresiile respective, că dacă nu se folosesc acești operatori sunt semnalate erori de compilare. În schimb, nu a fost necesar să se recurgă la cast la calcularea valorii lui b5, deoarece expresia ++b este de tip byte. Executând acest program, se obțin pe ecran următoarele
rezultate:
Din aceste rezultate constatăm că: - s-a obținut s3=-1 si nu s3=-1.222222...
deoarece în expresia s2/s1 ambii operanzi sunt de tipuri
întregi, deci rezultatul este întreg (împărțire întreagă). Din același
motiv s-a obținut i5=-222222 si nu -222222.222222....; |
/* Testarea operatorilor de comparatie in cazul tipurilor de date intregi */ class ComparInt { |
Executând acest program se obțin pe ecran următoarele rezultate sub
forma de valori booleene:
false true true false false true false true |
Având în vedere că true înseamnă adevărat, iar false
înseamnă fals, se poate constata cu ușurinta că aceste
rezultate sunt corecte. Remarcăm, de asemenea, că rezultatul comparației
depinde numai de valorile numerelor comparate, nu și de tipul acestora.
Operații de deplasare binarăUrmând "tradiția" limbajului C, limbajul Java conține și operatori de deplasare binară. Aceștia sunt operatori binari (cu doi operanzi) fără efect lateral. Tipul rezultatului operației se stabilește la fel ca în cazul operațiilor aritmetice cu numere întregi. Valoarea rezultată se stabilește astfel: se ia reprezentarea internă a primului operand și se deplasează la stânga sau la dreapta cu un numar de poziții binare egal cu cel de al doilea operand.Operatorii de deplasare și efectele lor sunt prezentate în
tabela de mai jos, în care a și s sunt operanzi care
aparțin unor tipuri întregi.
Deplasarea la stânga cu s poziții este echivalenta cu înmulțirea numărului cu 2s. Dacă s este suficient de mare, poate avea loc o depășire binară, la fel ca în cazul înmulțirii aritmetice (cu operatorul *). Deplasarea la dreapta cu s poziții cu operatorul >> este echivalenta cu împărțirea întreagă la 2s. Deplasarea biților la dreapta cu s pozitii cu operatorul >>> are asupra numerelor pozitive același efect ca cel al operatorului >>. În schimb, în cazul operanzilor negativi, în cazul operatorului >>> nu se mai conservă semnul, iar modulul numărului se modifică. Aceasta se întâmplă, întrucât pe pozițiile eliberate din partea stângă se înserează bitul 0. Exemplu
Rezultatele afișate la executarea acestui program sunt
următoarele:
Având în vedere că 23=8 și 24=16,
rezultatele obținute pot fi verificate cu ușurință. Constatăm ca singura
deosebire dintre efectele operatorilor >> și
>>> apare când primul operand este negativ.
Operații logice pe bițiTot urmând "tradiția" limbajelor C/C++, în limbajul Java se pot utiliza pentru tipurile de date întregi și operatorii logici pe biți ~, &, | si ^. Aceștia sunt operatori fără efect lateral. Operațiile logice se fac la nivel de bit, adică între fiecare bit al operandului din stânga și bitul corespunzător al operandului din dreapta, considerându-se ca 0 este echivalent cu false, iar 1 este echivalent cu true.Operatorul unar ~ exprimă negația logică,
deci înlocuirea lui 0 cu 1 și invers. Acțiunea operatorilor este dată în tabela de mai jos, în care a
și b sunt cei doi operanzi, iar ai si bisunt
biții de pe pozitia i a acestor operanzi. În tabelă se dă
efectul fiecărei operații asupra bitului i al rezultatului.
Exemplu
Rezultatele afișate la executarea acestui program sunt
următoarele:
|
Exemplu În programul din fișierul AtribComp.java se testează unele operații de atribuire compusă. Iată acest program:
La executarea programului se obțin pe ecran următoarele
rezultate:
Prima linie afișată conține: |