Übungsblatt 3: Softwareentwicklung I (WS 2006/07)

Werbung
Prof. Dr. A. Poetzsch-Heffter
Dipl.-Inform. J.O. Blech
Dipl.-Inform. M.J. Gawkowski
Dipl.-Inform. N. Rauch
Technische Universität Kaiserslautern
Fachbereich Informatik
AG Softwaretechnik
Übungsblatt 3: Softwareentwicklung I (WS 2006/07)
Ausgabe: 7. November 2006
Abgabe: 13. November 2006, 12.00 Uhr
Abnahme praktischer Teil: xxx. November 2003
Aufgabe 1
Operatorpräzedenzen
(3 Punkte)
Gegeben seien die folgenden ML-Funktionsdeklarationen:
a) fun f (x, y) = x + y * y >= x;
(1 Punkt)
b) fun m (a, b) = b + a div b = b mod a;
(1 Punkt)
Machen Sie die Operatorpräzedenzen explizit, indem Sie beide Ausdrücke gemäß den Präzedenzen der auftretenden
Operatoren klammern, und begründen Sie Ihre Antwort.
Beispiel: Aus dem Ausdruck not x andalso y orelse x andalso not y wird der Ausdruck (((not
x) andalso y) orelse (x andalso (not y))).
Hinweis: Eine Auflistung der Präzedenzen einzelner Operatoren finden Sie auf der Seite von Standard ML of New
Jersey, http://www.smlnj.org/doc/basis/pages/top-level-chapter.html
infix
infix
infixr
infix
infix
infix
7
6
5
4
3
0
* / div mod
+ - ^
:: @
= <> > >= < <=
:= o
before
All Operatoren, die hier aufgelistet wurden, assozieren nach links, z.B.: Der Ausdruck 3+4+5 wird als (3+4)+5
interpretiert und nicht als 3+(4+5).
c) Welchen Typ haben die Funktionen f und m? Begründen Sie Ihre Antwort.
Aufgabe 2
Syntax-, Typisierungs- und Laufzeitfehler
(1 Punkte)
(5 Punkte)
Schreiben Sie die unten aufgelisteten Ausdrücke in einer sml-Datei auf und bestimmen Sie experimentell, zu welchem
Ergebnis das Auswerten von ihnen führt. Zu jedem Ausdruck beantworten Sie die folgenden Fragen: Zu welchem
Ergebnis führt das Auswerten des Ausdrucks? Was für ein Fehler ist eventuell aufgetreten? Was ist die Ursache des
Fehlers? Für den Fall, dass man einem Ausdruck eine sinnvolle Semantik zuordnen kann, schlagen Sie eine Verbesserung vor.
a) 13.6 * 0.89;
b) 2 + 2 = 4.0;
c) implode(rev (explode "Reit nie tot ein Tier"));
d) ((~4)=(~(1+3)))=true;
e) "Erstsemestler" > "Zweitsemestler";
f) true=(2<>4)=(true orelse not true);
g) false <> true;
h) ((6 mod 5)=5)
orelse false;
i) (fn x => (x + 1))[];
j) (if true then 1 else 2 = false)=1;
k) (if 3.0 < 4
then true else false);
l) if "true" then 13 else 14;
m) "bi"^(if false then "la" else "ba")^"bu";
n) #1(false,true);
o) ((10 mod 2), true) = (5-(4+1),if true then (not not true) else false);
p) x=true;
q) val my_? = "myquestionmark";
r) 1.0e~3;
s) (1.0e~3)=0.001;
t) (fn x
=> (real(trunc x)) + (x - (real(trunc x))) ) 3.14;
Aufgabe 3
Die Datenstruktur String (praktisch)
(4 Punkte)
Schreiben Sie eine ML-Funktion dual2decimal vom Typ string → int, die eine Zeichenkette, die eine binäre
Zahl ibin darstellt, als Eingabe nimmt und diese in den Integerwert von ibin konvertiert.
Beispiele:
dual2decimal "" = 0
dual2decimal "0" = 0
dual2decimal "1" = 1
dual2decimal "100" = 4
dual2decimal "111" = 7
dual2decimal "00101" = 5
Aufgabe 4
Rekursion (praktisch)
(10 Punkte)
a) Schreiben Sie eine ML-Funktion fakultaet : int → int, die zu einer ganzen Zahl n ≥ 0 das Produkt aller
Zahlen k mit 1 ≤ k ≤ n, also n!, berechnet.
(2 Punkte)
Beispiele:
1. Der Wert von 0! vordefiniert 1.
2. 1! = 1
3. 2! = 1 ∗ 2 = 2
4. 3! = 1 ∗ 2 ∗ 3 = 6
b) Schreiben Sie eine ML-Funktion ngeraden : int → int list, die zu einer ganzen Zahl n ≥ 0 eine Liste von n
ersten geraden Zahlen berechnet. Beispiele:
1. ngeraden(0) = []
2. ngeraden(5) = [0, 2, 4, 6, 8]
c) Schreiben Sie eine ML-Funktion power : int ∗ int → int, die zu zwei ganzen Zahlen n und k ≥ 0 die k-te
Potenz von n, also nk , berechnet.
(2 Punkte)
d) Schreiben Sie eine ML-Funktion findapprox : real ∗ real ∗ (real list) → int ∗ int, die ein Tupel
(d, n, l) als Argument entgegennimmt und ein Paar von ganzen Zahlen (status, erg) zurückgibt. Dabei soll
findapprox die folgende Funktionalität besitzen: Kommt in der Liste l mindestens eine Zahl n0 mit |n−n0 | < d vor,
dann soll das Ergebnis als (0, i) definiert werden, wobei i der kleinste Listen-Index mit |n − (List.nth(l, i))| < d.
Kommt in der Liste keine solche Zahl, d.h. ∀ i. 0 ≤ i < List.length(l) −→ |n − (List.nth(l, i))| > d, dann soll
die Funktion (−1, −1) als das Ergebnis zurückliefern.
(2 Punkte)
Beispiele:
1. findapprox(1.12, 47.34, []) = (−1, −1)
2. findapprox(1.12, 47.34, [−3.4, 78.1345, 46.21]) = (−1, −1)
3. findapprox(1.12, 47.34, [−3.4, 78.1345, 46.21, 47.0, 47.2]) = (0, 3)
e) (Die verschränkte Rekursion) Betrachten Sie das folgende Beispiel für verschränkt rekursive Funktionsdelarationen.
1
2
3
4
5
6
fun odd n = if n=0 then false
else (if n=1 then true
else even(n-1))
and even n = if n=0 then true
else (if n=1 then false
else odd(n-1))
7
8
9
10
11
12
13
14
15
16
17
18
19
- even
val it
- even
val it
- even
0;
= true : bool
1;
= false : bool
2;
20
21
22
23
24
val it = true : bool
- even 3;
val it = false : bool
- odd 0;
val it = false : bool
- odd 1;
val it = true : bool
- odd 2;
val it = false : bool
- odd 3;
val it = true : bool
-
k+1 1
Aufgabestellung: Es sei eine Potenzreihe 1− 12 + 13 − 14 +. . . = Σ∞
k=1 (−1)
k gegeben. Bekanntlich, approximiert
diese Reihe den Wert ln 2. Schreiben Sie eine Funktion log2 : int → real, die zu einer ganzen Zahl n ≥ 1 die
Summe Σnk=1 (−1)k+1 k1 berechnet. Ihre Funktionsdeklaration soll auf dem oben veranschaulichten Prinzip der
verschränkten Rekursion basieren. Vergleichen Sie die Genauigkeit des Ergebnises des Aufrufes log2(n) mit dem
Ergebnis des Aufrufs von Math.ln 2.0;.
(2 Punkte)
Aufgabe 5
Binärer Zähler (praktisch)
(6 Punkte)
Definieren Sie eine ML-Funktion tick, die einen tickenden binären Zähler simuliert. tick soll eine Liste von booleschen Werten b, die eine binäre Zahl darstellt (hierbei soll true den Wert 1 repräsentieren und false den Wert 0),
als Eingabe nehmen und eine Liste von booleschen Werten b’, die eine binäre Zahl darstellt, zurückgeben. Dabei soll
der Wert der binären Zahl, die von b’ dargestellt wird, um 1 größer sein als der Wert der Zahl, die von b dargestellt
wird.
Beispiele:
tick([]) = [true]
tick([false]) = [true]
tick([true,false]) = [true,true]
tick(tick(tick([true,false]))) = [true,false,true]
tick(tick(tick(tick(tick(tick([true,false])))))) = [true,false,false,false].
Hinweis: Bekanntlich verläuft schriftliches Addieren zweier ganzen Zahlen von rechts nach links. Dagegen werden
Listen von links nach rechts verarbeitet. Nutzen Sie ggf. eine Funktion der Datenstruktur List.
Aufgabe 6
Terminierung
Betrachten Sie die folgenden Funktiondeklarationen der Funktionen find1 und find2.
51
52
fun find_helper1(n,e,l) =
if e=List.nth(l,n)
(2 Punkte)
53
54
then n
else find_helper1(n+1,e,l)
55
56
fun find1 (e,l) = find_helper1(0,e,l)
57
58
59
60
61
62
fun find_helper2(n,e,l) =
if Real.<(Real./(e,List.nth(l,n)),1.0)
then n
else find_helper2(n+1,e,l)
63
64
fun find2 (e,l:real list) = find_helper2(0,e,l)
65
Beschreiben Sie, für welche Eingaben diese Funktionen terminieren und für welche nicht. Schlagen Sie sinnvolle
Verbesserungen für diese Deklarationen vor, so dass diese immer terminieren.
Herunterladen