Cum funcționează
Problema pare să fie despre fracții, dar e de fapt despre sortarea după o valoare calculată.
Capcana: nu poți compara fracțiile după numărător sau după numitor. 7/(-2) și 9/(-3) au
numărători apropiați, dar valori foarte diferite. Singura comparație corectă e între valorile
zecimale, deci acestea se calculează o dată, la citire, și se rețin.
De aceea structura are trei câmpuri, nu două:
struct Fractie {
int a, b; // datele originale
double valoare; // rezultatul calculat, folosit la sortare
};
Câmpul valoare e redundant ca informație — s-ar putea recalcula oricând — dar îl calculezi o
singură dată în loc de mii de ori în timpul sortării. Este un tipar util în general.
Conversia (double) e obligatorie. În C++, a / b între două int dă împărțire întreagă:
1 / 4 ar fi 0, nu 0.25. Scriind (double)fr[i].a / fr[i].b forțezi împărțirea reală. Fără
ea, toate fracțiile subunitare devin 0 și sortarea iese complet greșită.
Sortarea e cea prin selecție directă, ca la
ordonarea elevilor, cu < pentru crescător. Se
interschimbă structura întreagă, deci numărătorul și numitorul rămân lipite de valoarea lor.
Observă că numitorii negativi funcționează natural: 7 / -2 dă -3.5, iar sortarea îl plasează
primul. Nu e nevoie să „normalizezi" semnul.
La afișare, cout scrie numerele reale fără zecimale inutile: -3 în loc de -3.000000, exact ca
în exemplu.
Greșeli frecvente
- Împărțirea fără
(double) — 1 / 4 devine 0. Cea mai frecventă și cea mai costisitoare
greșeală aici.
- Sortarea după numărător sau numitor — ordinea rezultată n-are legătură cu valoarea fracției.
- Recalcularea valorii în condiția de sortare — funcționează, dar se repetă inutil.
- Interschimbarea doar a câmpului
valoare — datele originale rămân desperecheate. Cu struct
se mută tot.
- Uitarea că numitorul poate fi negativ — nu necesită tratare specială; împărțirea se descurcă.