Ujemne potegi - algorytm

0

Zaczynam zabawe z algorytmika i jestem w trakcie czytania ksiazki Wirth Niklaus - Algorytmy + struktury danych = programy. Niestety mam problem ze zrozumieniem jednego z przykladow podanego w ksiazce, a dokladniej 2 linijek, ktore zaznaczylem w kodzie.
Prosilbym o wytlumaczenie w zrozumialy sposob.
Program ma wypisac kolejne ujemne potegi 2.
Przykladowo dla n = 4 wypisze
0.5
0.25
0.125
0.0625

A kod w pascalu taki :

program potega(output); 
 {reprezentacja dziesiętna ujemnych potęg liczby 2} 
 const n =4;  
 type cyfra =0..9; 
 var i, k, r : INTEGER; 
     d : array[1..n] of CYFRA; 

 begin 
 d[1]:=0;
 for k :=1 to n do  { wypisz 4 kolejne potegi }
   begin 
		write('0.');
		r :=0; 
		for i :=1 to k-1 do 
			begin 
				r :=10 *r +d[i];   { TUTAJ NIE ROZUMIE }
				d[i]:=r div 2; 
				r :=r -2 *d[i];   { TUTAJ NIE ROZUMIE }
				write(d[i]) 
			end; 
		d[k] :=5; writeln('5') 
   end; 
 end.

 
0
r :=10 *r +d[i];   { TUTAJ NIE ROZUMIE }

Ustawia wartość r na 10*r oraz dodaje do tego wartość z tablicy d znajdującą się pod indeksem i.
Poczytaj o tablicach, to zrozumiesz.

0

to rozumie doskonale. Wiem jak dzialaja tablice itp tylko nie rozumie tego algorytmu dlaczego akurat razy 10 itp

0

r to jest tak jakby reszta z dzielenia. Wydaje mi się, że jeśli zastąpisz: r := r - 2 * d[i]; na r := r mod 2; to kod będzie działał identycznie, ale lepiej będzie widać o co chodzi.

Algorytm wykorzystuje fakt, iż negatywna potęga dwójki ma tyle samo cyfr znaczących ile wynosi (-log2 liczba) (edit tutaj się rozpędziłem, generalnie ostatnia cyfra znacząca jest na '-log2 liczba'-tym miejscu po przecinku). Dlatego w k-tej iteracji jest wypisywane tylko k cyfr po przecinku i tylko k komórek w tablicy d ma zainicjowane wartości. W każdej iteracji algorytm dzieli liczbę zapisaną w tablicy d algorytmem dzielenia pisemnego, z tą różnicą, że w pierwszej iteracji jest tam zero, a algorytm wykorzystując fakt, że każda negatywna potęga dwójki kończy się cyfrą 5 (tzn to ostatnia znacząca cyfra) zarówno dopisuje końcową piątkę jak i inicjuje tablicę jedną instrukcją (d[k] := 5). Jest to dość nieintuicyjne i ja bym to chętnie zmienił, no ale co mi tam :P

0

Dalej tego nie rozumie... Moglbys to napisac bardziej na chlopski rozum niz jezykiem matematycznym bo ja dopiero zaczynam i malo co z tego rozumie. A po co np sie mnozy razy te 10 ?

0

Przecież napisałem, że chodzi o dzielenie pisemne. Załóżmy, że mamy 0.125 i k = 4

Kolejne przypisania:

i := 1
r := 10 * 0 + 1
d[1] := 1 div 2
r := 2 - 2 * 0
write(0)
i := 2
r := 10 * 1 + 2
d[2] := 12 div 2
r := 12 - 2 * 6
write(6)
i := 3
r := 10 * 0 + 5
d[3] := 5 div 2
r := 5 - 2 * 2
write(2)

r pozostaje 1 i gdyby zrobić następną iterację to wyszłoby write(5), ale autor omija ten krok i robi write(5) bezpośrednio przez co może olać poprawną inicjalizację. Linijka d[1] := 0; nie jest nawet potrzebna, bo ta komórka nie jest odczytywana przed pierwszym jej nadpisaniem w pętli.

Jak widać mając 0.125 i wykonując iterację dostajemy 0.0625 zarówno w tablicy jak i na ekranie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1