Ce vei învăța astăzi?
Astăzi vom implementa complet algoritmul pentru ecuația de gradul II, vom trata toate cazurile (inclusiv a=0, delta negativ etc.) și vom scrie un program robust, bine testat.
Dicționar: Implementarea ecuației de gradul II
Termeni și funcții C++ folosite în programul complet:
| Concept | Ce face? | Cod C++ |
|---|---|---|
| double | tip de date pentru numere reale cu precizie | double a, b, c; |
| cmath | biblioteca cu funcții matematice | #include <cmath> |
| sqrt(x) | calculează radicalul (√x) | sqrt(delta) |
| fixed + setprecision | afișare cu nr. exact de zecimale | fixed << setprecision(2) |
| if / else if / else | ramificări pe cazuri diferite | if (delta > 0) {...} |
| iomanip | biblioteca pentru formatare | #include <iomanip> |
Recapitulare: Ecuația de gradul II
Forma generală: ax + bx + c = 0, cu a ≠ 0 (dacă a = 0, devine ecuație de gradul I).
Discriminantul: Δ = b - 4ac
- Dacă Δ > 0: două soluții reale distincte:
x₁ = (-b + √Δ) / (2a),x₂ = (-b - √Δ) / (2a) - Dacă Δ = 0: o soluție reală dublă:
x = -b / (2a) - Dacă Δ < 0: nu există soluții reale (soluții complexe, pe care nu le tratăm în acest modul)
Δ = b − 4acdouble delta = b*b - 4*a*c;„delta se declară ca double pentru precizie maximă"x₁ = (−b + √Δ) / (2a)x1 = (-b + sqrt(delta)) / (2*a);„Atenție la paranteze: (2*a) trebuie grupat!"
| a | Δ | Soluții | Exemplu |
|---|---|---|---|
| a ≠ 0 | Δ > 0 | două reale distincte | x - 3x + 2 = 0 → Δ = 1, x₁ = 1, x₂ = 2 |
| a ≠ 0 | Δ = 0 | o soluție dublă | x - 2x + 1 = 0 → Δ = 0, x = 1 |
| a ≠ 0 | Δ < 0 | nici o soluție reală | x + x + 1 = 0 → Δ = -3 |
| a = 0 | - | se rezolvă ca ecuație de gradul I (bx + c = 0) | 0·x + 2x - 4 = 0 → x = 2 |
Algoritmul detaliat (pseudocod și diagramă)
Pașii algoritmului:
- Citește coeficienții a, b, c.
- Dacă a = 0 atunci
- Rezolvă ecuația de gradul I: bx + c = 0 (folosind algoritmul de la ora 28).
- Altfel (a ≠ 0)
- Calculează Δ = b*b - 4*a*c.
- Dacă Δ > 0:
- Calculează x1 = (-b + sqrt(Δ)) / (2*a)
- Calculează x2 = (-b - sqrt(Δ)) / (2*a)
- Afișează x1 și x2 (de obicei cu două zecimale)
- Dacă Δ = 0:
- Calculează x = -b / (2*a)
- Afișează x (soluție dublă)
- Dacă Δ < 0:
- Afișează un mesaj că nu există soluții reale.
#include <iostream>
#include <cmath> // pentru sqrt()
#include <iomanip> // pentru setprecision
using namespace std;
int main() {
double a, b, c, delta, x1, x2;
cout << "Introdu coeficientii a, b, c: ";
cin >> a >> b >> c;
if (a == 0) {
// cazul particular: ecuație de gradul I
if (b != 0) {
x1 = -c / b;
cout << "Ec de grad I: solutia x = " << fixed << setprecision(2) << x1;
} else if (c == 0) {
cout << "Infinitate de solutii (a=0,b=0,c=0)";
} else {
cout << "Nu exista solutie (a=0,b=0,c≠0)";
}
} else {
// cazul general
delta = b*b - 4*a*c;
if (delta > 0) {
x1 = (-b + sqrt(delta)) / (2*a);
x2 = (-b - sqrt(delta)) / (2*a);
cout << fixed << setprecision(2);
cout << "x1 = " << x1 << ", x2 = " << x2;
} else if (delta == 0) {
x1 = -b / (2*a);
cout << fixed << setprecision(2);
cout << "x1 = x2 = " << x1;
} else {
cout << "Nu exista solutii reale (delta < 0)";
}
}
return 0;
}
Atenție: Folosim double pentru mai multă precizie, mai ales când delta este aproape de zero. Funcția sqrt() necesită header-ul <cmath>.
Programul complet: Ecuația de gradul II
Traseu de execuție #1: x − 3x + 2 = 0 (Δ > 0)
| Pas | Instrucțiune | a | b | c | delta | x1 | x2 |
|---|---|---|---|---|---|---|---|
| 1 | cin >> a >> b >> c | 1 | -3 | 2 | — | — | — |
| 2 | if (a==0) → NU | 1 | -3 | 2 | — | — | — |
| 3 | delta=9-8 | 1 | -3 | 2 | 1 | — | — |
| 4 | if (delta>0)→DA | 1 | -3 | 2 | 1 | — | — |
| 5 | x1=(3+1)/2 | 1 | -3 | 2 | 1 | 2 | — |
| 6 | x2=(3-1)/2 | 1 | -3 | 2 | 1 | 2 | 1 |
| 7 | cout (ordonate) | Ieșire: 1.00 2.00 | |||||
Traseu de execuție #2: x − 2x + 1 = 0 (Δ = 0)
| Pas | Instrucțiune | a | b | c | delta | x1 |
|---|---|---|---|---|---|---|
| 1 | cin >> a >> b >> c | 1 | -2 | 1 | — | — |
| 2 | if (a==0) → NU | 1 | -2 | 1 | — | — |
| 3 | delta=4-4 | 1 | -2 | 1 | 0 | — |
| 4 | else if (delta==0)→DA | 1 | -2 | 1 | 0 | — |
| 5 | x1=2/2 | 1 | -2 | 1 | 0 | 1.00 |
#include <iostream>
#include <cmath> // pentru sqrt
using namespace std;
int main() {
double a, b, c, delta, x1, x2;
cin >> a >> b >> c;
if (a == 0) {
// tratare ec grad I
if (b != 0) cout << "x = " << -c/b;
else if (c == 0) cout << "Infinitate de solutii";
else cout << "Imposibil";
} else {
delta = b*b - 4*a*c;
if (delta > 0) {
x1 = (-b + sqrt(delta)) / (2*a);
x2 = (-b - sqrt(delta)) / (2*a);
cout << "x1 = " << x1 << ", x2 = " << x2;
} else if (delta == 0) {
x1 = -b/(2*a);
cout << "x = " << x1;
} else {
cout << "Nu exista solutii reale";
}
}
return 0;
}
Atenție la paranteze! Scrierea (-b + sqrt(delta)) / 2*a (fără paranteze la 2*a) va calcula (...)/2 * a în loc de (...) / (2*a). Aceasta este cea mai frecventă greșeală!
Greșeli frecvente și cum să le eviți
| Greșeală | Exemplu greșit | Corect | Explicație |
|---|---|---|---|
| Nu verificăm a = 0 (degenerează în ecuație de grad I) | delta = b*b - 4*a*c; direct, fără if(a==0) |
if(a==0) { /*tratare grad I*/ } else { /*calcul delta*/ } |
Dacă a=0, formula discriminantului nu mai are sens, iar împărțirea la 2a ar da eroare. |
| Confundarea formulelor pentru x1, x2 | x1 = (-b + sqrt(delta)) / 2*a (lipsă paranteze) |
(-b + sqrt(delta)) / (2*a) |
În C++, împărțirea și înmulțirea au aceeași prioritate, deci / 2*a înseamnă (.../2)*a. |
| Folosirea tipului int pentru coeficienți | int a,b,c; |
double a,b,c; |
Împărțirile trebuie să fie reale, altfel pierdem precizia. |
Uităm să includem <cmath> pentru sqrt |
#include <iostream> doar |
#include <cmath> |
Funcția sqrt nu este definită fără acest header. |
| Nu afișăm soluțiile cu formatare corectă | cout << x1; (poate afișa 2e+000) |
cout << fixed << setprecision(2) << x1; |
Pentru un aspect curat și cerințele problemelor. |
Sfaturi de depanare:
- Testează programul cu ecuații simple: x - 3x + 2 = 0 (soluțiile 1 și 2).
- Verifică și cazurile limită: a=0 (2x-4=0), a=0,b=0 (0=0 sau imposibil).
- Adaugă temporar
cout << "delta=" << delta;pentru a vedea valoarea. - Dacă primești NaN sau Inf, probabil ai împărțire la zero sau radical din număr negativ.
- Pentru delta foarte aproape de zero, folosește o tolerană (ex: abs(delta) < 1e-9) pentru a-l considera zero.
Verificare cunoștințe
1. Pentru ecuația x - 5x + 6 = 0, ce valoare are delta și câte soluții reale sunt?
2. Ce afișează programul pentru a=0, b=3, c=6?
3. Ce header trebuie inclus pentru a folosi funcția sqrt()?
4. Pentru a=2, b=4, c=2, care este soluția?
Întrebări frecvente (FAQ) extins
else if pentru a trata cazurile delta?
if (delta > 0) { ... } else if (delta == 0) { ... } else { ... } este clară și eficientă.
Interpretarea geometrică
Ecuația de gradul II poate fi privită ca intersecția parabolei y = ax + bx + c cu axa Ox (y=0).
- Dacă Δ > 0, parabola taie axa în două puncte distincte.
- Dacă Δ = 0, parabola este tangentă axei (vârful atinge axa).
- Dacă Δ < 0, parabola nu intersectează axa Ox (este deasupra sau dedesubt).
Programul nostru poate fi extins să afișeze și această interpretare, dar nu este necesar pentru PbInfo.
Întrebări de examen: Ce modificări trebuie pentru coeficienți complecși? Cum tratăm cazul b foarte mare (depășire tip double)? Când e suficient double vs. long double? Cum afișăm soluțiile complexe când Δ < 0?
Exercițiu: Alege cazul corect
Pentru fiecare ecuație, alege tipul soluțiilor:
x - 4x + 3 = 0
x - 2x + 1 = 0
x + x + 1 = 0
0·x + 2x - 4 = 0 (a=0)
PbInfo - Discriminantul
Delta pentru gradul II
Enunț:
Cerință: Se citesc a, b, c. Calculeaza discriminantul delta=b*b-4*a*c.
Date de intrare:
Coeficientii a, b, c.
Date de ieșire:
Valoarea lui delta.
Exemplu:
Intrare:
1 -3 2
Ieșire:
1
Explicație: delta = 9 - 8 = 1.
Cum gândim soluția:
- Citim coeficientii.
- Aplicam formula delta=b*b-4*a*c.
- Afisam delta.
Tip: Nu ai nevoie de sqrt pentru aceasta cerinta.
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;
int main() {
double a, b, c;
cin >> a >> b >> c;
double delta = b * b - 4 * a * c;
cout << delta;
return 0;
}
PbInfo - Numar de radacini reale
Decizie dupa delta
Enunț:
Cerință: Se citesc a, b, c, cu a nenul. Afiseaza cate radacini reale are ecuatia.
Date de intrare:
Coeficientii a, b, c.
Date de ieșire:
0, 1 sau 2.
Exemplu:
Intrare:
1 -3 2
Ieșire:
2
Explicație: Delta este pozitiv.
Cum gândim soluția:
- Calculam delta.
- Daca delta > 0, sunt doua radacini.
- Daca delta == 0, este o radacina dubla.
- Altfel nu sunt radacini reale.
Tip: Este o aplicatie directa de if / else if / else.
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;
int main() {
double a, b, c;
cin >> a >> b >> c;
double d = b * b - 4 * a * c;
if (d > 0) cout << 2;
else if (d == 0) cout << 1;
else cout << 0;
return 0;
}
PbInfo - Radacinile reale
Formula completa
Enunț:
Cerință: Se citesc a, b, c. Afiseaza radacinile reale daca exista, altfel mesajul Nu exista.
Date de intrare:
Coeficientii a, b, c.
Date de ieșire:
Radacinile reale sau mesajul Nu exista.
Exemplu:
Intrare:
1 -5 6
Ieșire:
2 3
Explicație: Radacinile ecuatiei sunt 2 si 3.
Cum gândim soluția:
- Verificam cazul a==0.
- Calculam delta.
- Daca delta < 0, nu calculam radical.
- Altfel aplicam formula radacinilor.
Tip: Include cmath pentru sqrt.
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double a, b, c;
cin >> a >> b >> c;
if (a == 0) {
cout << "Nu este gradul II";
return 0;
}
double d = b * b - 4 * a * c;
if (d < 0) cout << "Nu exista";
else if (d == 0) cout << - b / (2 * a);
else {
cout << (- b - sqrt(d)) / (2 * a) << " ";
cout << (- b + sqrt(d)) / (2 * a);
}
return 0;
}
Testează TOATE ramurile programului:
- Δ > 0: introd. 1 -3 2 → aștepti 1.00 2.00
- Δ = 0: introd. 1 -2 1 → aștepti 1.00
- Δ < 0: introd. 1 1 1 → nu exista solutii reale
- a=0, b≠0: introd. 0 2 -4 → 2.00
- a=0, b=0, c=0: introd. 0 0 0 → infinit
- a=0, b=0, c≠0: introd. 0 0 5 → imposibil
Exercițiul Practic: Implementarea ecuației de gradul II
Consolidează implementarea completă pentru ecuația de gradul II și verifică ramurile importante ale programului.
Sarcina 1: Analiză cod
Următorul cod conține mai multe greșeli. Găsește-le și corectează-le.
#include <iostream>
using namespace std;
int main() {
int a, b, c, delta, x1, x2;
cin >> a >> b >> c;
if (a = 0) {
cout << -c/b;
} else {
delta = b*b - 4*a*c;
if (delta > 0) {
x1 = (-b + sqrt(delta)) / 2*a;
x2 = (-b - sqrt(delta)) / 2*a;
cout << x1 << " " << x2;
} else if (delta = 0) {
x1 = -b / 2*a;
cout << x1;
} else {
cout << "nu exista";
}
}
return 0;
}
De ce funcționează? Fiecare greșeală vine dintr-o confuzie tipică – atribuire vs comparare (= vs ==), precedența operatorilor (/2*a = împărțire la 2 apoi ori cu a!), și tipuri de date. Codul corectat folosește double, operatori corecți și paranteze explicite.
Greșeli:
- Lipsă
#include <cmath>pentru sqrt. - Tipuri de date: ar trebui
double, nuint. if (a = 0)în loc deif (a == 0).- În cazul a=0, nu se verifică b=0 etc.
- La calculul lui x1, x2:
/ 2*atrebuie să fie/(2*a). if (delta = 0)în loc deif (delta == 0).- Lipsă
fixed << setprecision.
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main() {
double a,b,c,delta,x1,x2;
cin>>a>>b>>c;
if(a==0){
if(b==0){
if(c==0) cout<<"infinit";
else cout<<"nu exista";
} else {
x1=-c/b;
cout<0){
x1=(-b-sqrt(delta))/(2*a);
x2=(-b+sqrt(delta))/(2*a);
if(x1>x2) swap(x1,x2);
cout<
Sarcina 2: Implementare pentru 5 ecuații
Scrie un program care citește un număr n, apoi n triplete (a,b,c) și pentru fiecare afișează soluțiile (sau mesajul corespunzător), fiecare pe o linie nouă.
De ce funcționează? Folosim o buclă for care repetă de n ori algoritmul complet de rezolvare. Fiecare iterație citește un nou triplet (a,b,c) și afișează rezultatul pe o linie nouă. Algoritmul interior este identic cu cel de la PbInfo #125.
#include <iostream> // cin, cout
#include <cmath> // sqrt
#include <iomanip> // fixed, setprecision
using namespace std;
int main() {
int n; // numărul de ecuații
double a,b,c,delta,x1,x2;
cin >> n; // citim câte ecuații avem
for(int i=1; i<=n; i++){ // repetăm de n ori
cin >> a >> b >> c; // citim coeficienții ecuației i
if(a==0){ // caz degenerat
if(b==0){
if(c==0) cout << "infinit\n";
else cout << "nu exista solutii reale\n";
} else {
x1 = -c/b; // ecuație grad I
cout << fixed << setprecision(2) << x1 << endl;
}
} else {
delta = b*b - 4*a*c; // Δ = b-4ac
if(delta > 0){ // două rădăcini
x1 = (-b - sqrt(delta)) / (2*a);
x2 = (-b + sqrt(delta)) / (2*a);
if(x1 > x2) swap(x1,x2);
cout << fixed << setprecision(2) << x1 << " " << x2 << endl;
} else if (delta == 0){ // rădăcină dublă
x1 = -b / (2*a);
cout << fixed << setprecision(2) << x1 << endl;
} else { // fără sol. reale
cout << "nu exista solutii reale\n";
}
}
}
return 0;
}