Programarea Calculatoarelor: Laborator 2

În această lucrare se vor rezolva probleme care să testeze gândirea recursivă. Pentru implementare, se vor folosi tot funcții cu operatorul condițional ? :

Exemplul 1: să se determine partea întreagă a unui număr real x aflat în intervalul [0, 1000).

Pornim de la definiția părții întregi: [x] = n (cu n întreg) dacă n <= x < n+1. Observăm că relația are aceeași structură ca și problema dată: cunoaștem că x se află în intervalul [n, n+1) și putem da direct răspunsul: partea întreagă este n (intervalul e suficient de mic pentru a avea o singură variantă posibilă).

Folosim descompunerea în subprobleme mai mici prin tehnica înjumătățirii: comparăm x cu mijlocul intervalului inițial [a, b) și în funcție de rezultat, aflăm dacă se află în prima sau a doua jumătate. Rămânem astfel cu o problemă de acelasi tip (aflarea părții întregi a unui număr dintr-un interval), dar cu un interval mai mic, ceea ce ne apropie de cazul de bază (interval de lungime 1).

Pentru a scrie cele de mai sus precis, matematic, rezumăm în felul următor:
Rezultatul problemei pentru numărul x și intervalul [a, b) este:
-- dacă b - a = 1, intregul a
-- altfel, daca x < (a+b)2, rezultatul este dat de aceeasi problema cu numarul x si primul interval [a, (a+b)/2)
-- altfel rezultatul este dat de aceeasi problema, cu numarul x si al doilea interval [(a+b)/2, b)

Formularea "problema pentru numarul ...", si faptul ca problema trebuie sa dea un rezultat indica faptul ca putem inlocui formularea "problema" cu "functie", si "pentru numerele ..." cu "parametri". Deci:
f(x, a, b) =
-- daca b - a = 1, atunci a
-- altfel, daca x < (a+b)/2, atunci f(x, a, (a+b)/2)
-- altfel, f(x, (a+b)/2, b)

int partint(double x, int lo, int hi)
{
  return hi - lo <= 1 ? lo :
    x < (lo+hi)/2 ? partint(x, lo, (lo+hi)/2) : partint(x, (lo+hi)/2, hi);
}

Combinand aceasta tehnica de injumatatire cu cea din exemplele de la curs pentru a ne opri la o precizie data, putem sa gasim (cu o anumita precizie) si radacina unei functii monotone pe un interval [a, b], daca stim ca functia schimba semnul pe acest interval.

Exemplul 2. Calculul restului modulo 9 (cu suma cifrelor):

Să se scrie o funcție care determină restul unui număr dat ca parametru la împărțirea cu 9. Se permit doar operații numerice de comparare, împărțire modulo 10 și adunare.
Știm că restul la împărțirea cu 9 este același pentru număr și suma cifrelor lui (care va fi în general mai mică). Deci scriem recursiv o funcție care calculează suma cifrelor numărului (vezi pentru comparație funcția de inversare a cifrelor din notițele de curs. Suma cifrelor ar putea să fie tot un număr pe mai multe cifre, deci aplicăm procedura până când obținem un număr de o singură cifră pentru care returnăm restul cerut.


Marius Minea
Last modified: Sun Mar 54 17:38:25 EET 2006