Sa incepem cu eternul exemplu 2/7 si sa vedem cum il facem de mana:
2 | 7
0 +----------
- | 0.285714
20
14
--
60
56
--
40
35
--
50
49
--
10
7
--
30
28
--
2
In acest moment ne oprim. De ce? Deoarece restul 2 a mai aparut si
la inceputul impartirii. Este evident ca de acum totul se va repeta:
coboram un zero, sapte in douazeci de doua ori, scriem doi rest sase
si asa mai departe. Asadar zecimalele catului se repeta incepand cu 2
si terminand cu 4. Rezultatul este 0.(285714).
Algoritmul intr-o prima schita este deci:
Repeta
Coboara o cifra si fa impartirea
Pana cand (Restul obtinut a mai aparut)
La o prima vedere, s-ar parea deci ca trebuie sa memoram toate
resturile obtinute in cursul impartirii si sa vedem cand se repeta
unul dintre ele. Daca unul dintre aceste resturi este zero, inseamna
ca fractia este neperiodica.
Intrucat numarul de zecimale este O(N) (si poate fi egal cu N-1 pentru
anumite numere prime N), si intrucat restul dupa extragerea fiecarei
zecimale trebuie comparat cu resturile anterioare, problema in aceasta
faza ruleaza in timp O(N^2). De asemenea, consuma memorie O(N) pentru
vectorul de resturi. Totusi, urmatoarea observatie (fara demonstratie)
simplifica mult lucrurile:
OBSERVATIE: Daca M si N sunt prime intre ele, atunci numarul de cifre
neperiodice ale fractiei M/N este egal cu maximul dintre exponentii
lui 2 si 5 in descompunerea in factori primi a lui N.
De exemplu, daca N=1400=2^3*5^2*7, atunci exponentul lui 2 este 3,
iar exponentul lui 5 este 2, deci numarul de cifre neperiodice este
Max(3,2)=2. Exponentii celorlalti factori primi (de exemplu 7) nu
influenteaza numarul de cifre neperiodice.
Acum avem avantajul ca stim sigur unde se deschide paranteza care
indica periodicitatea: acolo unde se termina cifrele neperiodice.
Algoritmul in noua lui varianta (Green Power, radical imbunatatita)
este:
1. Afla numarul de cifre neperiodice, Nep
2. Extrage Nep cifre. Fie R restul ramas.
3. Daca R=0, fractia este neperiodica
Altfel continua extragerea cifrelor pana cand se obtine din nou restul R
Cam asta este. Sa mai vedem si ce inseamna extragerea unei cifre:
a) Se coboara un 0 ---> M:=M*10
b) Se separa catul ---> WriteLn(M div N)
c) Se pastreaza restul ---> M:=M mod N
Se observa ca nu mai am nevoie sa pastrez nici macar vectorul de
resturi, pentru ca stiu exact ce valoare caut - valoarea R. Deci
memoria este O(1) (constanta). De asemenea, un rest obtinut nu mai
este comparat cu toate cele obtinute inaintea lui, ci doar cu R - de
unde timpul de rulare O(N).
Cam asta e; rezultatele vin peste inca vreo zi sau doua.
|
|