Repetition i Pascal
I I Scheme använde vi rekursion för all slags repetition.
I Efterom Scheme är ett funktionellt språk återsänder alla
språkkonstruktioner ett värde men i Pascal (mellan-)lagras värden i variabler.
I Man kan alltså ha styrstrukturer som inte kräver rekursion för repetitiva beräkningar.
I Pascal har flera sådana och jag kommer ge exempel på hur de används.
I Jag använder två olika exempel som vi redan studerat både i Scheme och Pascal
DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 1 / 20
Exemplen – fac
Orginalet
(define fac (lambda (n)
(if (= n 0) 1
(* n (fac (- n 1))))))
Svansrekursiv
(define fac (lambda (n)
(define fac-svans (lambda (m res)
(if (> m n) res
(fac-svans (+ m 1) (* res m))))) (fac-svans 2 1)))
DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 2 / 20
Pascal Programexempel
Exemplen – fac i Pascal
Direktkopia av den svansrekursiva Scheme-varianten
FUNCTION fac(n: Integer): Integer;
FUNCTION facsvans(m, res: Integer): Integer;
BEGIN
IF m > n THEN facsvans := res ELSE
facsvans := facsvans(m + 1, res * m) END;
BEGIN
fac := facsvans(2, 1) END;
Pascal Programexempel
Exemplen – fac – motivering
Betraktar man en ”trace” på fac-svans eller gör en utskrift från motsvarande Pascal-program får man
m res
2 1
3 2
4 6
5 24
6 120
Vi ser att resultatet erhålls genom att parametrarna m och res uppdateras för varje anrop och att det som lagrats i parametern res lämnas som resultat då mpasserat värdet för n.
Det räcker alltså att sätta initalvärden på res och m och uppdatera dem utan extra anrop.
I Pascal kan man formulera detta direkt utan rekursion.
Repetition i Pascal – ”while”
FUNCTION fac(n : Integer) : Integer;
VAR m, res : Integer; { variabler för mellanlagring}
{ ersätter inre funk.param.}
BEGIN
m := 2; res := 1; { initialvärden }
WHILE m <= n DO BEGIN { villkoret inverterat } res := res * m; { uppdatera res }
m := Succ(m); { uppdatera m }
END; { slut på ”slingan” }
fac := res { återsänd resultatet } END;
DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 5 / 20
Repetition i Pascal – ”while” formellt
I Syntaxdiagram:
while (villkors-)
uttryck do sats
I I funktionenfacär satsen en sammansatt sats eftersom jag vill utföra mer än en sak.
I IWHILE-satsen kollar man om villkoret är uppfyllt innan man gör något.
Skulle villkoret inte vara uppfyllt då programmet ”stöter på ”WHILE-satsen så utförs ingenting
I Man måste, som vid rekursion, vara noga med att se till att man kommer till en situation där villkoret inte längre är uppfyllt. Man har ingen
kompilatoranalys till hjälp.
I Man kan tänka sig att man först vill göra något och sedan kolla om man ska göra om. Pascal stöder även detta.
DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 6 / 20
Pascal Programexempel
Repetition i Pascal – ”repeat . . . until”
FUNCTION fac(n: Integer): Integer;
VAR m, res : Integer;
BEGIN
m := 1; res := 1;
REPEAT
res := res * m;
m := Succ(m);
UNTIL m > n;
fac := res END;
Pascal Programexempel
Repetition i Pascal – ”repeat . . . until” formellt
I Syntaxdiagram:
repeat sats until (villkors-)
uttryck
;
I Man kan utan sammansatt sats sätta in flera satser mellanREPEAToch UNTIL
I Man utför alla satser minst en gång
I Man måste även här vara noga med att slutvillkoret kommer att uppfyllas
I Eftersom vi vet både start och slutvillkor och dessa är taljämförelser så kan vi ju faktiskt avgöra exakt hur många gånger vi ska utföra
modifikationen av variablerna. Det kan vi utnyttja på två sätt:
Repetition i Pascal – ”for . . . to/downto”
FUNCTION fac(n: Integer): Integer;
VAR m, res : Integer;
BEGIN
res := 1;
FOR m := 2 TO n DO res := res * m;
fac := res END;
FUNCTION fac(n: Integer): Integer;
VAR res : Integer;
BEGIN res := 1;
FOR n := n DOWNTO 2 DO res := res * n;
fac := res END;
DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 9 / 20
Repetition i Pascal – ”for . . . to/downto” formellt
I Syntaxdiagram:
for (variabel-)
identifierare := uttryck
to downto
uttryck do sats
I Mindre formellt (och lättare att resonera kring):
FOR variabel := startvärde TO / DOWNTO slutvärde DO sats
DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 10 / 20
Pascal Programexempel
Repetition i Pascal – ”for . . . to/downto” formellt
I FOR variabel := startvärde TO / DOWNTO slutvärde DO sats
I IFOR ...TO-satsen kontrolleras att startvärdet är mindre än eller lika med slutvärdet, annars utförs ingenting
I Självklart tvärtom iFOR ...DOWNTO-satsen
I Satsen utförs för varje värde, inklusive start- och slutvärdena
I Start och slutvärdena ska vara av samma (diskreta typ)
I Steget är alltid i någon mening 1
I Repetition med de nu visade konstruktionerna kallasiteration
Pascal Programexempel
Rekursion kontra iteration – för- och nackdelar
I Vid rekursion behöver man ”bara” tänka på
I Hur vet man att man är klar?
I Vad gör man då?
I Hur tar man ett steg närmare lösningen?
I Vid iteration måste man tänka på allt samtidigt men
I Iteration är resurssnålt
I För att rekursion ska vara resurssnålt måste man
I använda ett språk som kan eliminera svansrekursion (som Scheme, ML, Haskell eller Miranda)
I skriva svansrekursiva program (inte alltid enkelt)
I Vi har nu tre olika loopkonstruktioner:
1. REPEAT ... UNTIL villkor;
2. WHILE villkor DO sats;
3. FOR styrvariabel := start TO slut DO s;
FOR styrvariabel := start DOWNTO slut DO s;
Iteration – exempel 2 (fib) i Scheme
I Rekursivt i Scheme:
(define fib (lambda (n)
(if (< n 2) 1
(+ (fib (- n 1)) (fib (- n 2))))))
I Svansrekursivt
(define fib (lambda (n)
(define fib-inner (lambda (m f1 f2)
(if (> m n) f2
(fib-inner (+ m 1) f2 (+ f1 f2))))) (fib-inner 1 0 1)))
DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 13 / 20
Iteration – exempel 2 (fib) i Scheme . . .
Trace av svansrekursiva varianten
> (fib 5)
|(fib-inner 1 0 1)
|(fib-inner 2 1 1)
|(fib-inner 3 1 2)
|(fib-inner 4 2 3)
|(fib-inner 5 3 5)
|(fib-inner 6 5 8)
|8 8
DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 14 / 20
Pascal Programexempel
Iteration – exempel 2 (fib) i Pascal
FUNCTION fib(n : Integer) : Integer;
FUNCTION inner(m, f1, f2 : Integer) : Integer;
BEGIN
IF m > n THEN inner := f2
ELSE inner := inner(m + 1, f2, f1 + f2) END;
BEGIN
fib := inner(1, 0, 1) END;
Pascal Programexempel
Iteration – exempel 2 (fib) med WHILE
FUNCTION fib(n : Integer) : Integer;
VAR m, f1, f2, tmp : Integer;
BEGIN
m := 1; f1 := 0; f2 := 1;
WHILE m <= n DO BEGIN m := Succ(m);
tmp := f2;
f2 := f1 + f2;
f1 := tmp END;
fib := f2 END;
Iteration – exempel 2 (fib) med REPEAT
FUNCTION fib(n : Integer) : Integer;
BEGIN
fib := inner(1, 0, 1) m := 1; f1 := 0; f2 := 1;
REPEAT
m := Succ(m);
tmp := f2;
f2 := f1 + f2;
f1 := tmp UNTIL m > n;
fib := f2 END;
DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 17 / 20
Iteration – exempel 2 (fib) med FOR ...TO
FUNCTION fib(n : Integer) : Integer;
VAR m, f1, f2, tmp : Integer;
BEGIN
f1 := 0; f2 := 1;
FOR m := 1 TO n DO BEGIN tmp := f2;
f2 := f1 + f2;
f1 := tmp END;
fib := f2 END;
DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 18 / 20
Pascal Programexempel
Iteration – exempel 2 (fib) med FOR ...DOWNTO
FUNCTION fib(n : Integer) : Integer;
VAR f1, f2, tmp : Integer;
BEGIN
f1 := 0; f2 := 1;
FOR n := n DOWNTO 1 DO BEGIN tmp := f2;
f2 := f1 + f2;
f1 := tmp END;
fib := f2 END;
Pascal Programexempel
Iteration – exempel 3: iterate i newton-programmet
FUNCTION iter(x, eps: Real;
FUNCTION next(x:Real; FUNCTION f(x:Real):Real):Real;
FUNCTION f(x: Real):Real): Real;
BEGIN
WHILE abs(x-next(x, f)) >= eps DO x := next(x, f);
iter := x END;