Tipuri de date și variabile

Ce încape într-un int, când ai nevoie de long long și de ce împărțirea a două numere întregi dă un întreg.

Ce este o variabilă

O variabilă este un loc în memorie cu un nume și un tip. Numele îl alegi tu. Tipul spune ce fel de valori încap acolo și cât spațiu ocupă.

int n;              // un întreg, neinițializat
int m = 25;         // un întreg, cu valoarea 25
double media = 8.5; // un număr real
char litera = 'A';  // un caracter
bool gasit = false; // adevărat sau fals

Declararea și inițializarea se pot face separat. Dacă știi însă valoarea de la început, dă-o direct la declarare.

Tipurile care îți trebuie efectiv

C++ are multe tipuri. La bac folosești cinci, iar cel mai des pe două dintre ele: int și long long.

tipce țineinterval aproximativocteți
intnumere întregi−2·10⁹ … 2·10⁹4
long longnumere întregi mari−9·10¹⁸ … 9·10¹⁸8
charun caracter−128 … 1271
doublenumere realefoarte larg, cu aproximare8
booltrue sau false—1

Din tabel reține ordinul de mărime, cifrele exacte nu contează: un int ține până pe la două miliarde.

Depășirea, adică bug-ul care nu dă nicio eroare

Dacă un rezultat nu încape în tip, nu primești niciun mesaj. Primești un număr greșit, adesea negativ.

int a = 2000000000;
int b = 2000000000;
cout << a + b;      // afișează un număr negativ

Suma este 4·10⁹ și nu încape într-un int. Valoarea „se rotește" și iese ceva fără sens.

Situațiile în care se întâmplă asta în practică:

  • Produse. Două numere de ordinul 10⁵ înmulțite dau 10¹⁰, deci depășește. Suma acelorași numere nu.
  • Sume de multe elemente. O mie de valori de ordinul 10⁷ dau 10¹⁰.
  • Factoriale și puteri. 20! are 19 cifre. La 21! se depășește chiar și long long.

Soluția este să declari long long de la început acolo unde te aștepți la valori mari:

long long produs = 1;
for (int i = 1; i <= n; i++)
    produs = produs * i;

Atenție la o capcană mai greu de văzut: tipul rezultatului depinde de tipul operanzilor, nu de al variabilei în care pui rezultatul.

int a = 100000, b = 100000;
long long p = a * b;    // GREȘIT: a*b se calculează ca int și depășește
long long q = 1LL * a * b;  // corect: forțăm calculul pe long long

Împărțirea întreagă

La începători, de aici vin cele mai multe rezultate greșite.

Dacă ambii operanzi sunt întregi, / face împărțire întreagă și aruncă partea fracționară.

cout << 7 / 2;      // 3, nu 3.5
cout << 1 / 2;      // 0
cout << 7 % 2;      // 1  — restul

Rezultatul nu se rotunjește, se trunchiază. 9 / 10 este 0, nu 1.

Ca să obții un rezultat real, cel puțin un operand trebuie să fie real:

int suma = 17, n = 5;
cout << suma / n;               // 3
cout << (double)suma / n;       // 3.4
cout << 1.0 * suma / n;         // 3.4

În schimb, când lucrezi cu cifre, împărțirea întreagă este exact ce îți trebuie:

n / 10      // taie ultima cifră
n % 10      // ia ultima cifră

Pe perechea aceasta se bazează jumătate din problemele de la Subiectul II. În pseudocod, n / 10 se scrie [n/10].

Restul, la numere negative

% cu operanzi negativi dă în C++ un rest cu semnul deîmpărțitului: -7 % 2 este -1, nu 1. Dacă testezi paritatea unui număr care poate fi negativ, scrie x % 2 != 0 în loc de x % 2 == 1, altfel numerele impare negative îți scapă.

Caractere

Un char ține un caracter, scris între apostrofuri simple: 'A', '7', ' '. Intern este un număr, codul ASCII al caracterului. De aici vin câteva trucuri utile:

char c = 'C';
cout << (int)c;          // 67, codul lui 'C'
cout << (char)(c + 1);   // 'D'

Cifra ca text și cifra ca număr sunt lucruri diferite:

char c = '7';
int cifra = c - '0';     // 7, valoarea numerică

Scăderea lui '0' funcționează pentru că cifrele au coduri consecutive. Același truc merge la litere: c - 'a' îți dă poziția literei în alfabet.

Numere reale

double ține numere cu zecimale, dar aproximativ. Nu toate valorile se reprezintă exact, așa că nu compara niciodată două reale cu ==:

double x = 0.1 + 0.2;
if (x == 0.3) ...        // poate fi fals!

Se compară cu o toleranță: if (fabs(x - 0.3) < 0.0001). fabs este modulul unui număr real și vine din <cmath>.

Regula practică pentru examen: dacă problema se poate rezolva cu întregi, rezolv-o cu întregi. Numerele reale aduc numai probleme de precizie, iar la bac apar rar.

Constante

Dacă o valoare nu se schimbă niciodată, declar-o constantă:

const int MAX = 1000;
int v[MAX];

E mai clar decât un 1000 apărut din senin în mijlocul programului. Și dacă trebuie schimbat, îl schimbi într-un singur loc.

De reținut

  • int ține până pe la 2·10⁹. Peste, folosește long long.
  • Depășirea nu dă eroare, dă rezultat greșit. Atenție la produse și la sume lungi.
  • a b se calculează în tipul operanzilor. 1LL a * b forțează calculul pe tipul mare.
  • / între întregi trunchiază. n/10 și n%10 sunt perechea pentru cifre.
  • c - '0' transformă cifra-caracter în valoare numerică.
  • Nu compara double cu ==.