Funcții matematice C++: sqrt, pow, abs și rotunjire
Funcțiile matematice din C++ reduc codul necesar pentru rădăcini, puteri, valori absolute și rotunjire. Totuși, o funcție corectă poate produce un rezultat nepotrivit dacă alegi tipul greșit sau confunzi aproximarea reală cu un calcul întreg exact.
În acest material
Funcțiile matematice din C++ reduc codul necesar pentru rădăcini, puteri, valori absolute și rotunjire. Totuși, o funcție corectă poate produce un rezultat nepotrivit dacă alegi tipul greșit sau confunzi aproximarea reală cu un calcul întreg exact.
Pentru exercițiile de algoritmică este esențial să separi întrebările numerice: vrei o aproximație a rădăcinii sau vrei să demonstrezi că numărul este pătrat perfect? Cele două cerințe nu se rezolvă identic.
Cum funcționează
std::sqrt din calculează rădăcina pătrată în virgulă mobilă. Pentru date reale obișnuite este potrivită, dar comparația directă sqrt(n)==un_int poate depinde de rotunjire. O strategie pentru întregi este să obții un candidat, apoi să îl corectezi prin comparații întregi. În program limităm n la intervalul 0..10^12, astfel încât pătratele candidaților să încapă în long long.
std::pow calculează puteri în virgulă mobilă în utilizările uzuale. Nu este alegerea potrivită pentru a calcula exact o putere modulară sau pentru a construi o limită întreagă fără verificare. Pentru un exponent întreg nenegativ, înmulțirile controlate sau exponentierea rapidă oferă un model mai clar, cu analiza overflow-ului separată.
std::abs oferă valoarea absolută prin supraîncărcări pentru diferite tipuri. Rezultatul trebuie să fie reprezentabil: cel mai mic întreg cu semn poate avea un modul care nu încape în același tip. Pentru diferența a-b, conversia la un tip suficient de larg trebuie făcută înainte de scădere, nu după ce overflow-ul s-a produs.
std::floor rotunjește spre minus infinit, std::ceil spre plus infinit, iar std::round la cel mai apropiat întreg, cu jumătățile îndepărtate de zero. Conversia directă double către int trunchiază spre zero dacă rezultatul este reprezentabil. Diferențele devin clare pentru valori negative. Programul citește și un x între -1000 și 1000, apoi afișează cele trei rotunjiri fără zecimale. Formatarea nu schimbă valoarea calculată și nu transformă orice aproximare într-un întreg exact.
Exemplu urmărit pas cu pas
Pentru n=49, candidatul rădăcinii este 7 și testul întreg 7·7==49 confirmă pătratul perfect. Pentru n=50, partea întreagă a rădăcinii rămâne 7, dar egalitatea este falsă.
Pentru x=-2.5, floor produce -3, ceil produce -2 și round produce -3. Conversia la int ar produce -2. Pe x=2.5, floor este 2, ceil este 3 și round este 3. Testarea doar pe numere pozitive ar ascunde o parte importantă a regulilor.
Implementare C++17
#include <cmath>
#include <iomanip>
#include <iostream>
int main() {
long long n;
double x;
std::cin >> n >> x;
long long r = static_cast<long long>(std::sqrt(static_cast<long double>(n)));
while ((r + 1) * (r + 1) <= n)
++r;
while (r * r > n)
--r;
std::cout << r << ' ' << (r * r == n ? "DA" : "NU") << '\n';
std::cout << std::fixed << std::setprecision(0) << std::floor(x) << ' '
<< std::ceil(x) << ' ' << std::round(x) << '\n';
}
De ce funcționează și cât costă
Corectarea candidatului continuă până când r²<=n<(r+1)². Aceste două inegalități definesc exact rădăcina întreagă inferioară. Testul r²==n verifică apoi pătratul perfect fără egalități între valori reale aproximative.
Exemplul folosește memorie O(1). În intervalul restrâns al datelor, sqrt oferă un candidat apropiat și corecțiile sunt mici; algoritmul nu este prezentat ca o metodă generală de aritmetică pentru întregi de dimensiune arbitrară.
Greșeli frecvente
Nu considera setprecision o corecție matematică a erorilor. Nu compara rezultate reale cu egalitate când problema admite toleranță. Verifică domeniul funcției: rădăcina pătrată reală cere argument nenegativ. Nu folosi un epsilon ales arbitrar pentru orice scară de valori.
Exersează
Explică rezultatele floor(-3.1), ceil(-3.1) și conversia la int a lui -3.1.
Rezolvare explicată: Rezultatele sunt -4, -3 și -3. Prima operație merge spre minus infinit; celelalte două coincid aici, dar din reguli diferite.
Continuă să înveți
Tipuri de date, expresii și putere rapidă.
Întrebări frecvente
Ce diferență este între floor și conversia la int?
floor merge spre minus infinit, iar conversia trunchiază spre zero în domeniul reprezentabil. Pentru -2.5 obții -3, respectiv -2.
Cum tratează round valoarea -2.5?
O rotunjește la -3. Jumătățile sunt rotunjite în direcția opusă lui zero, deci 2.5 devine 3.
De ce nu folosesc pow pentru puteri modulare?
Rezultatul în virgulă mobilă poate fi aproximativ sau prea mare. Exponentierea modulară reduce controlat rezultatele intermediare și păstrează exactitatea în limitele declarate.
abs funcționează pentru orice int?
Nu dacă modulul nu poate fi reprezentat în tipul rezultatului. Cazul valorii minime a unui tip cu semn trebuie tratat prin limite sau printr-o reprezentare potrivită.
Cum verific un pătrat perfect?
Calculează un candidat pentru rădăcina întreagă, corectează-l în limite sigure și verifică egalitatea r*r==n. Analizează separat dacă produsul încape în tip.
Un pas mai departe
Se încarcă progresul…