Pagina Modulului 5
Ora 30 - Modulul 5

Implementarea ecuației de gradul II

Program complet pentru ax + bx + c = 0, tratarea cazurilor speciale, afișarea soluțiilor și testare extinsă

45min teorie + 15min probleme PbInfo + exerciții practice
Competențele 4.1, 5.1
Săptămâna 2
Sigla liceului
TEORIE - 45 minute

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.

Scrierea programului complet în C++
Calculul discriminantului Δ = b - 4ac
Tratarea cazurilor: Δ>0, Δ=0, Δ<0
Gestionarea situației când a = 0 (degenerează în ecuație de grad I)
Afișarea soluțiilor cu precizia cerută
Testarea programului cu multiple seturi de date
Depanarea greșelilor comune

Dicționar: Implementarea ecuației de gradul II

Termeni și funcții C++ folosite în programul complet:

ConceptCe face?Cod C++
doubletip de date pentru numere reale cu preciziedouble a, b, c;
cmathbiblioteca cu funcții matematice#include <cmath>
sqrt(x)calculează radicalul (√x)sqrt(delta)
fixed + setprecisionafișare cu nr. exact de zecimalefixed << setprecision(2)
if / else if / elseramificări pe cazuri diferiteif (delta > 0) {...}
iomanipbiblioteca 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 − 4ac
    double 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ă)

// Pseudocod complet: Implementare ecuație grad II CITEȘTE a, b, c DACĂ a = 0 ATUNCI // ecuație de gradul I: bx + c = 0 DACĂ b 0 ATUNCI SCRIE -c / b ALTFEL DACĂ c = 0 ATUNCI SCRIE "infinit" ALTFEL SCRIE "imposibil" ALTFEL delta b*b - 4*a*c DACĂ delta > 0 ATUNCI x1 (-b + sqrt(delta)) / (2*a) x2 (-b - sqrt(delta)) / (2*a) SCRIE x1, x2 // ordonate crescător! DACĂ delta = 0 ATUNCI SCRIE -b / (2*a) ALTFEL SCRIE "nu exista solutii reale"
Pașii algoritmului:
  1. Citește coeficienții a, b, c.
  2. Dacă a = 0 atunci
    • Rezolvă ecuația de gradul I: bx + c = 0 (folosind algoritmul de la ora 28).
  3. 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.
Implementare în C++ (cu comentarii)
#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)
PasInstrucțiuneabcdeltax1x2
1cin >> a >> b >> c1-32
2if (a==0) → NU1-32
3delta=9-81-321
4if (delta>0)→DA1-321
5x1=(3+1)/21-3212
6x2=(3-1)/21-32121
7cout (ordonate)Ieșire: 1.00 2.00
Traseu de execuție #2: x − 2x + 1 = 0 (Δ = 0)
PasInstrucțiuneabcdeltax1
1cin >> a >> b >> c1-21
2if (a==0) → NU1-21
3delta=4-41-210
4else if (delta==0)→DA1-210
5x1=2/21-2101.00
Rezolvarea ecuației ax + bx + c = 0
#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

De ce trebuie să tratăm separat cazul a=0?
Pentru că dacă a=0, ecuația nu mai este de gradul II, ci devine liniară. Dacă am aplica formulele pentru gradul II, am împărți la 2a = 0, ceea ce duce la eroare. De asemenea, discriminantul nu mai are sens. Așadar, trebuie să detectăm această situație și să rezolvăm ecuația ca pe una de gradul I.
Ce se întâmplă dacă delta este foarte aproape de zero, dar nu exact zero din cauza erorilor de calcul?
În calculele cu double, din cauza reprezentării în virgulă mobilă, putem obține valori precum 1e-15 în loc de 0. În astfel de cazuri, este recomandat să folosim o toleranță: considerăm delta = 0 dacă |delta| < 1e-9 (sau o valoare similară). Astfel, tratăm corect cazul soluției duble.
Cum afișăm soluțiile dacă sunt numere iraționale (de exemplu, √2)?
De obicei, în problemele de programare se cere afișarea cu un număr fix de zecimale (de exemplu, 2). Astfel, vom aproxima valoarea. Dacă s-ar cere forma exactă, ar trebui să păstrăm expresia, dar acest lucru depășește nivelul acestui modul.
Pot folosi else if pentru a trata cazurile delta?
Da, este chiar recomandat. Structura 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

Două reale distincte
O soluție dublă
Nici o soluție reală

x - 2x + 1 = 0

Două reale distincte
O soluție dublă
Nici o soluție reală

x + x + 1 = 0

Două reale distincte
O soluție dublă
Nici o soluție reală

0·x + 2x - 4 = 0 (a=0)

Două reale distincte
Ecuație de grad I (o soluție)
Nici o soluție
PROBLEME PBINFO - 15 minute

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:
  1. Citim coeficientii.
  2. Aplicam formula delta=b*b-4*a*c.
  3. 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:
  1. Calculam delta.
  2. Daca delta > 0, sunt doua radacini.
  3. Daca delta == 0, este o radacina dubla.
  4. 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:
  1. Verificam cazul a==0.
  2. Calculam delta.
  3. Daca delta < 0, nu calculam radical.
  4. 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:
  1. Δ > 0: introd. 1 -3 2 → aștepti 1.00 2.00
  2. Δ = 0: introd. 1 -2 1 → aștepti 1.00
  3. Δ < 0: introd. 1 1 1 → nu exista solutii reale
  4. a=0, b≠0: introd. 0 2 -4 → 2.00
  5. a=0, b=0, c=0: introd. 0 0 0 → infinit
  6. a=0, b=0, c≠0: introd. 0 0 5 → imposibil
EXERCIȚII PRACTICE - 2 sarcini / 20 minute

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;
}
// Pseudocod – greșeli frecvente la ecuația de gradul II // ✗ a = 0 → trebuie a == 0 (comparare, nu atribuire!) // ✗ / 2*a → trebuie / (2*a) (paranteze la numitor!) // ✗ int → trebuie double (numere reale!) // ✗ lipsă sqrt → trebuie #include <cmath> // ✓ Verifică tipul datelor, operatorii și parantezele

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, nu int.
  • if (a = 0) în loc de if (a == 0).
  • În cazul a=0, nu se verifică b=0 etc.
  • La calculul lui x1, x2: / 2*a trebuie să fie /(2*a).
  • if (delta = 0) în loc de if (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ă.

Repetă rezolvarea pentru n ecuații: citește n, apoi n triplete (a,b,c)
for(int i=1; i<=n; i++) { cin >> a >> b >> c; /* rezolvă */ }
„Se citesc n triplete și pentru fiecare se rezolvă ecuația"
// Pseudocod – rezolvare n ecuații de gradul II CITEȘTE n PENTRU i 1, n EXECUTĂ CITEȘTE a, b, c // rezolvă ecuația a·x + b·x + c = 0 // (același algoritm ca la PbInfo #125) SCRIE rezultat pe linie nouă SFÂRȘIT PENTRU

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;
}

Descarcă toate exercițiile și soluțiile