Ce vei învăța astăzi?
Trecem de la formulă la un program complet: tratăm toate cazurile speciale, adăugăm validare și facem o simulare pas cu pas a mișcării.
Dicționar: Matematică ↔ C++ (Simulare)
| Concept matematic | Cum se citește | În C++ | Observație |
|---|---|---|---|
| x(t) = x₀ + v·t | „poziția la momentul t" | pos = x0 + v * t; | formula de bază MRU |
| v₀ (viteza inițială MRUV) | „v zero" | double v0; | viteza la momentul t=0 |
| a (accelerația) | „a m/s" | double a; | a < 0 = decelerare (frânare) |
| t (timpul la pătrat) | „t pătrat" | t * t | NU t^2 (^=XOR în C++) |
| |x₁ - x₂| (distanța) | „modul diferență" | abs(pos1 - pos2) | include <cmath> |
| ≈ 0 (aproape zero) | „aproximativ zero" | dist < 0.01 | prag de detecție întâlnire |
| do-while (repetare) | „execută... cât timp" | do { } while(cond); | minim 1 execuție |
| setw(n), setprecision(p) | „lățime n, p zecimale" | #include <iomanip> | formatare tabelar |
Analogie: De la formulă la program
GPS-ul din mașină
Un GPS face exact ce noi facem acum: primește pozițiile (x₀) și vitezele (v) vehiculelor, apoi simulează mișcarea pas cu pas pentru a prezice unde va fi fiecare. Cazurile speciale? Dacă două mașini merg cu aceeași viteză pe aceeași bandă — nu se întâlnesc niciodată (sau merg mereu împreună)!
x = x0 + v*t; | t = (x20-x10)/(v1-v2); | v / 3.6Tratarea tuturor cazurilor
Un program robust trebuie să gestioneze toate situațiile posibile, nu doar cazul fericit.
| Caz | Condiție matematică | Ce se întâmplă | Cod C++ |
|---|---|---|---|
| Normal | v₁ ≠ v₂ și t ≥ 0 | Se întâlnesc la momentul t | t = (x20-x10)/(v1-v2) |
| Merg împreună | v₁ = v₂ și x₁₀ = x₂₀ | Mereu în aceeași poziție | if(v1==v2 && x10==x20) |
| Paralele | v₁ = v₂ și x₁₀ ≠ x₂₀ | Nu se întâlnesc niciodată | if(v1==v2 && x10!=x20) |
| Trecut | t < 0 | S-au depărtat deja | if(t < 0) |
Trace: x₁₀=0, v₁=5, x₂₀=100, v₂=10
t = (100-0)/(5-10) = 100/(-5) = -20 → t negativ! Mobilele se îndepărtează. Mobilul 2 era la 100 și merge mai repede (v₂=10 > v₁=5), deci fuge de mobilul 1.
Împărțire la zero: Dacă v₁ = v₂, formula (x20-x10)/(v1-v2) face împărțire la 0! Verifică ÎNTÂI dacă v1 == v2 înainte de a calcula t.
Simulare pas cu pas
Ideea simulării: În loc să calculăm doar momentul întâlnirii, afișăm pozițiile ambelor mobile la fiecare secundă — ca un tabel de valori. Verificăm vizual rezultatele.
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main() {
double x10, v1, x20, v2;
int tmax;
cout << "Mobil 1 (x0, v): "; cin >> x10 >> v1;
cout << "Mobil 2 (x0, v): "; cin >> x20 >> v2;
cout << "Simulare pana la t = "; cin >> tmax;
cout << left << setw(6) << "t"
<< setw(12) << "Pos_M1"
<< setw(12) << "Pos_M2"
<< setw(12) << "Distanta" << endl;
cout << "--------------------------------------" << endl;
bool gasit = false;
for (int t = 0; t <= tmax; t++) {
double pos1 = x10 + v1 * t;
double pos2 = x20 + v2 * t;
double dist = abs(pos1 - pos2);
cout << setw(6) << t
<< setw(12) << fixed << setprecision(1) << pos1
<< setw(12) << pos2
<< setw(12) << dist;
if (dist < 0.01 && !gasit) {
cout << " << INTALNIRE!";
gasit = true;
}
cout << endl;
}
if (!gasit) cout << "\nNu s-au intalnit in intervalul [0, " << tmax << "]." << endl;
return 0;
}
De ce folosim <iomanip> aici? Nu este pentru calcule. Este doar pentru aspectul tabelului: setw(12) lasă spațiu pentru o coloană, iar fixed << setprecision(1) afișează pozițiile cu o zecimală, de exemplu 50.0. Dacă nu vrei tabel aliniat, poți afișa simplu cu cout << pos1.
t Pos_M1 Pos_M2 Distanta
--------------------------------------
0 0.0 100.0 100.0
5 50.0 125.0 75.0
10 100.0 150.0 50.0
15 150.0 175.0 25.0
20 200.0 200.0 0.0 << INTALNIRE!
Conversie unități de viteză
În fizică se folosește m/s, dar în viața reală km/h. Conversia: 1 km/h = 1000m / 3600s = 1/3.6 m/s.
| km/h | m/s | Exemplu real |
|---|---|---|
| 5 | ≈ 1.39 | Pas rapid |
| 36 | 10 | Bicicletă |
| 50 | ≈ 13.89 | Mașină în oraș |
| 130 | ≈ 36.11 | Autostradă |
double kmh_to_ms(double v) { return v / 3.6; }
double ms_to_kmh(double v) { return v * 3.6; }
// Exemplu de utilizare:
double v_auto = 90; // km/h
cout << v_auto << " km/h = " << kmh_to_ms(v_auto) << " m/s";
// Afiseaza: 90 km/h = 25 m/s
Program complet cu meniu
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main() {
int optiune;
do {
cout << "\n=== LABORATORUL DE FIZICA ===" << endl;
cout << "1. Calculeaza pozitia unui mobil" << endl;
cout << "2. Punct de intalnire (2 mobile)" << endl;
cout << "3. Simulare pas cu pas" << endl;
cout << "4. Conversie km/h <-> m/s" << endl;
cout << "0. Iesire" << endl;
cout << "Optiune: "; cin >> optiune;
if (optiune == 1) {
double x0, v, t;
cout << "x0, v, t: "; cin >> x0 >> v >> t;
cout << "Pozitia: " << x0 + v * t << " m" << endl;
}
else if (optiune == 2) {
double x10, v1, x20, v2;
cout << "Mobil1 (x0, v): "; cin >> x10 >> v1;
cout << "Mobil2 (x0, v): "; cin >> x20 >> v2;
if (v1 == v2) {
if (x10 == x20)
cout << "Merg mereu impreuna!" << endl;
else
cout << "Nu se intalnesc (viteze egale)." << endl;
} else {
double t = (x20 - x10) / (v1 - v2);
if (t < 0)
cout << "Nu se intalnesc (t=" << t << " < 0)." << endl;
else
cout << "Se intalnesc la t=" << t
<< "s, x=" << x10+v1*t << "m" << endl;
}
}
else if (optiune == 3) {
double x10, v1, x20, v2;
int tmax;
cout << "Mobil1 (x0, v): "; cin >> x10 >> v1;
cout << "Mobil2 (x0, v): "; cin >> x20 >> v2;
cout << "Simuleaza pana la t="; cin >> tmax;
for (int t = 0; t <= tmax; t++) {
double d = abs((x10+v1*t)-(x20+v2*t));
cout << "t=" << setw(3) << t
<< " M1=" << setw(8) << x10+v1*t
<< " M2=" << setw(8) << x20+v2*t
<< " d=" << d;
if(d < 0.01) cout << " *** INTALNIRE ***";
cout << endl;
}
}
else if (optiune == 4) {
double v;
int sub;
cout << "1=km/h->m/s 2=m/s->km/h: "; cin >> sub;
cout << "Viteza: "; cin >> v;
if(sub == 1) cout << v << " km/h = " << v/3.6 << " m/s" << endl;
else cout << v << " m/s = " << v*3.6 << " km/h" << endl;
}
} while (optiune != 0);
cout << "La revedere!" << endl;
return 0;
}
Compararea double-urilor: if(v1 == v2) funcționează bine aici deoarece valorile vin direct de la citire. Dar în general, pentru double-uri calculate, e mai sigur: if(abs(v1-v2) < 0.0001).
Extensie: Mișcarea cu accelerație (MRUV)
Dacă viteza se schimbă uniform, avem MRUV: x(t) = x₀ + v₀·t + a·t/2, unde a = accelerația.
x = x0 + v0*t + a*t*t/2.0; | v = v0 + a*t;Exemplu: frânare
O mașină la v₀=20 m/s frânează cu a=-5 m/s. Când se oprește? v(t)=0 → 0 = 20 + (-5)·t → t = 4 secunde. Distanța de frânare: x = 20·4 + (-5)·16/2 = 80 - 40 = 40 m.
Trace: Simulare MRUV (frânare v₀=20, a=-5)
| t | v = v₀+a·t | C++: v0+a*t | x = x₀+v₀·t+a·t/2 | C++: x0+v0*t+a*t*t/2.0 |
|---|---|---|---|---|
| 0 | 20 | 20+(-5)*0=20 | 0 | 0+20*0+(-5)*0*0/2=0 |
| 1 | 15 | 20+(-5)*1=15 | 17.5 | 0+20*1+(-5)*1/2=17.5 |
| 2 | 10 | 20+(-5)*2=10 | 30 | 0+20*2+(-5)*4/2=30 |
| 3 | 5 | 20+(-5)*3=5 | 37.5 | 0+20*3+(-5)*9/2=37.5 |
| 4 | 0 | 20+(-5)*4=0 | 40 | OPRIT la 40m |
double x0 = 0, v0 = 20, a = -5; // franare
for(int t = 0; t <= 5; t++){
double v = v0 + a*t;
double x = x0 + v0*t + a*t*t/2.0;
if(v < 0) { cout << "Oprit la t=" << -v0/a << "s"; break; }
cout << "t=" << t << " v=" << v << " x=" << x << endl;
}
Verificare cunoștințe
1. Ce se întâmplă dacă v1=v2=10, x10=5, x20=5?
2. În simulare, cum detectăm întâlnirea?
3. De ce folosim do-while pentru meniu?
4. Cum convertim 90 km/h în m/s?
5. Dacă t_întâlnire < 0, ce înseamnă?
6. În MRUV, ce face termenul a·t/2?
Întrebări frecvente (FAQ)
Putem folosi switch pentru meniu! Dar logica din fiecare opțiune e complexă, deci e mai clar cu if-else. Ambele funcționează — switch e mai elegant pentru selecții simple.
cin intră în stare de eroare și nu mai citește nimic. Soluție avansată: cin.clear(); cin.ignore(1000,'\n'); după fiecare citire eșuată.
Verifică cu valori calculate manual. Ex: x10=0, v1=10, x20=100, v2=5 → t = 100/(10-5) = 20s, x = 0+10×20 = 200m. Simularea trebuie să arate INTALNIRE la t=20.
Cu #include <cmath>, da — abs() funcționează pentru double. Fără cmath, abs() din cstdlib e doar pentru int! Alternativă sigură: fabs() din cmath.
PbInfo - Pozitia dupa timp
x=x0+v*t
Enunț:
Cerință: Se citesc x0, v si t. Afiseaza pozitia mobilului.
Date de intrare:
x0 v t.
Date de ieșire:
Pozitia x.
Exemplu:
Intrare:
10 3 4
Ieșire:
22
Explicație: 10+3*4=22.
Cum gândim soluția:
- Citim datele.
- Aplicam x=x0+v*t.
- Afisam x.
Tip: Formula este directa, fara bucla.
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;
int main() {
double x0, v, t;
cin >> x0 >> v >> t;
cout << x0 + v * t;
}
PbInfo - Punctul de intalnire
Doua mobile
Enunț:
Cerință: Se citesc x1, v1, x2, v2. Afiseaza timpul intalnirii daca este pozitiv.
Date de intrare:
x1 v1 x2 v2.
Date de ieșire:
Timpul intalnirii sau mesaj.
Exemplu:
Intrare:
0 5 20 1
Ieșire:
5
Explicație: Cele doua mobile se intalnesc dupa 5 secunde.
Cum gândim soluția:
- Daca vitezele sunt egale, tratam separat.
- Calculam t=(x2-x1)/(v1-v2).
- Verificam t>=0.
Tip: Daca t este negativ, intalnirea a fost in trecut.
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;
int main() {
double x1, v1, x2, v2;
cin >> x1 >> v1 >> x2 >> v2;
if (v1 == v2)
cout << "Nu se intalnesc";
else {
double t = (x2 - x1) / (v1 - v2);
if (t >= 0)
cout << t;
else cout << "Timp negativ";
}
}
PbInfo - Pozitia la intalnire
Timp si spatiu
Enunț:
Cerință: Se citesc doua miscari. Afiseaza timpul si pozitia intalnirii.
Date de intrare:
x1 v1 x2 v2.
Date de ieșire:
t si pozitia.
Exemplu:
Intrare:
0 5 20 1
Ieșire:
5 25
Explicație: La t=5, pozitia este 25.
Cum gândim soluția:
- Calculam t.
- Daca t>=0, calculam x=x1+v1*t.
- Afisam t si x.
Tip: Pozitia poate fi calculata cu oricare dintre cele doua mobile.
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;
int main() {
double x1, v1, x2, v2;
cin >> x1 >> v1 >> x2 >> v2;
if (v1 == v2) {
cout << "Nu";
return 0;
}
double t = (x2 - x1) / (v1 - v2);
if (t < 0)
cout << "Nu";
else cout << t << " " << x1 + v1 * t;
}
Exercițiul Practic: Implementare mișcare
Consolidează implementarea mișcării prin validare, simulare text și folosirea formulelor în programe complete. Poți păstra programele mici la început; meniul este doar o organizare mai mare.
Atenție la semnul vitezei: în fizică, o viteză negativă poate însemna mers în sens opus. În această sarcină de validare tratăm v ca „viteză ca mărime”, deci cerem v >= 0. Dacă vrei să permiți mersul înapoi, validezi doar timpul, nu și viteza.
Sarcina 1: Validare date de intrare
Adaugă validare: viteza trebuie să fie ≥ 0, iar timpul ≥ 0. Dacă nu, cere din nou cu do-while.
Pași de rezolvare
- Citește
x0 - Citește
vcu do-while: repetă dacăv < 0 - Citește
tcu do-while: repetă dacăt < 0 - FOR
i = 0..t: afișeazăx0 + v*i
do { cin >> v; } while(v < 0);De ce funcționează? Validarea cu do-while garantează intrare corectă — bucla se repetă cât timp condiția e falsă. Fizic, viteza și timpul nu pot fi negative în MRU.
#include <iostream>
using namespace std;
int main(){
double x0, v;
cout << "x0: "; cin >> x0; // pozitia initiala (poate fi orice)
do {
cout << "v (>=0): "; cin >> v; // viteza trebuie >= 0
if(v < 0) cout << "Viteza negativa! Reincearca." << endl;
} while(v < 0); // repeta pana citim v valid
int t;
do {
cout << "t (>=0): "; cin >> t; // timpul trebuie >= 0
} while(t < 0); // do-while = se executa cel putin o data
for(int i=0; i<=t; i++)
cout << "t=" << i << " x=" << x0+v*i << endl; // formula MRU
return 0;
}
Sarcina 2: Animație text
Afișează pe o linie de 50 caractere pozițiile celor 2 mobile cu 'A' și 'B'. La poziții egale afișează 'X'. Afișează la fiecare secundă.
Pași de rezolvare
- Definește constantele:
x10=0, v1=3, x20=40, v2=1 - FOR
t = 0..15: calculeazăp1, p2(int) - Creează o linie de 50 puncte, pune 'A' la
p1, 'B' lap2 - Dacă
p1 == p2: pune 'X' (coliziune) - Afișează linia cu
t=prefix
int p1 = (int)(x10 + v1*t);De ce funcționează? Convertim pozițiile reale (double) în indici de array (int). Fiecare rând de 50 caractere = o „fotografie" la momentul t. Dacă doi indici coincid → 'X' (coliziune).
#include <iostream>
using namespace std;
int main(){
double x10=0, v1=3, x20=40, v2=1; // date initiale: 2 mobile
for(int t=0; t<=15; t++){
int p1 = (int)(x10 + v1*t); // pozitia mobil A (coloana)
int p2 = (int)(x20 + v2*t); // pozitia mobil B (coloana)
if(p1<0)p1=0; if(p1>49)p1=49; // limitam la 0..49
if(p2<0)p2=0; if(p2>49)p2=49;
char linie[51];
for(int i=0;i<50;i++) linie[i]='.'; // umplem cu puncte
linie[50]='\0'; // terminatorul de sir
linie[p1]='A'; // punem mobilul A
if(p1==p2) linie[p1]='X'; // intalnire: afisam X
else linie[p2]='B'; // altfel: punem si mobilul B
cout << "t=" << t << " |" << linie << "|" << endl;
}
return 0;
}