Theoretischer Teil

Werbung
Aufgabensammlung
zur
Einführung in die Programmierung
Inhaltsverzeichnis
1
Logik, Mengenlehre, Funktionen
2
2
URM-Programmierung
5
3
Hoare-Kalkül
8
4
Komplexität
13
5
Abstrakte Datentypen
17
6
Formale Sprachen, BNF, EBNF
23
7
Zahldarstellung
29
1
1. 2
1
Logik, Mengenlehre, Funktionen
Aufgabe 1.1
a) Erstellen Sie eine Wahrheitstafel für (A ⇒ B) ⇒ B
b) Erstellen Sie eine Wahrheitstafel für (A ∧ ¬B) ∨ (¬A ∧ B)
c) Erstellen Sie eine Wahrheitstafel für ((A ⇒ B) ∧ (B ⇒ C)) ⇒ (A ⇒ C)
Lösung zu 1.1
a) Wahrheitstafel:
A B
A ⇒ B (A ⇒ B) ⇒ B
0
0
1
0
0
1
1
1
1
0
0
1
1
1
1
1
b) (A ∧ ¬B) ∨ (¬A ∧ B) stellt das ausschließende oder“ (exclusive or, XOR) dar:
”
A B
A ∧ ¬B ¬A ∧ B (A ∧ ¬B) ∨ (¬A ∧ B)
0
0
0
0
0
0
1
0
1
1
1
0
1
0
1
1
1
0
0
0
c) Hier sind einige Zwischenschritte sinnvoll:
A B C
A ⇒ B B ⇒ C (A ⇒ B) ∧ (B ⇒ C) A ⇒ C ((A ⇒ B)∧(B ⇒ C))
⇒ (A ⇒ C)
0
0
0
1
1
1
1
1
0
0
1
1
1
1
1
1
0
1
0
1
0
0
1
1
0
1
1
1
1
1
1
1
1
0
0
0
1
0
0
1
1
0
1
0
1
0
1
1
1
1
0
1
0
0
0
1
1
1
1
1
1
1
1
1
Aufgabe 1.2
Bilden Sie die logischen Verneinungen von
a)
b)
c)
d)
e)
Wenn es regnet, dann wird die Straße nass
(a ≤ b) ∨ (a = 0)
x>0∧y <0
Alle Vielfachen von 10 sind durch 2 und durch 5 teilbar
p(x) = T RU E, wobei p(x) eine Funktion sei, die einen boole’schen Wert liefert (also ein Prädikat).
Können Sie den Ausdruck verkürzen?
Lösung zu 1.2
(Wir benutzen die Schreibweise ¬X für die Negation der logischen Aussage X statt X.)
a) Wenn es regnet, dann wird die Straße nass ist gleichbedeutend zu es regnet nicht oder die Straße ist nass. Die
Verneinung hiervon ist es regnet und die Straße ist nicht nass. Alle anderen Kombinationen (z.B. es regnet nicht
und die Straße ist nass) sind keine logische Negation der obigen Aussage.
b) Nach der ersten de Morgansche Regel ¬(A ∨ B) = ¬A ∧ ¬B ist
¬((a ≤ b) ∨ (a = 0)) ≡ ¬(a ≤ b) ∧ ¬(a = 0) ≡ (a > b) ∧ (a 6= 0)
c) Hier benutzen wir die zweite de Morgansche Regel ¬(A ∧ B) = ¬A ∨ ¬B und erhalten
¬((x > 0) ∧ (y < 0)) ≡ ¬(x > 0) ∨ ¬(y < 0) ≡ (x ≤ 0) ∨ (y ≥ 0)
1. 3
d) Formal lautet die Aussage:
∀x ∈ N : x ist Vielfaches von 10 → 2|x ∧ 5|x.
Die Negation davon ist:
∃x ∈ N : x ist Vielfaches von 10 9 (2|x ∧ 5|x)
Dazu ist äquivalent
∃x ∈ N : x ist Vielfaches von 10 ∧ (2 ∤ x ∨ 5 ∤ x).
In Worten:
Es gibt ein Vielfaches von 10, das nicht durch 2 oder nicht durch 5 teilbar ist.
e) Der Ausdruck p(x) = T RU E ist selber schon äquivalent zum Ausdruck p(x), die Negation erhalten wir also
einfach durch ¬p(x).
Aufgabe 1.3
Paul sagt: Max lügt.“
”
Max sagt: Otto lügt.“
”
Otto sagt: Max und Paul lügen.“
”
Wer lügt hier nun wirklich, wer sagt die Wahrheit?
Lösung zu 1.3
Wenn Paul die Wahrheit sagt, dann muß Max lügen, also Otto die Wahrheit sagen. Dies ist aber ein Widerspruch
zu der Annahme, dass Paul nicht lügt. Also lügt Paul, damit sagt Max die Wahrheit und Otto lügt.
Man kann die Aufgabe auch formal lösen:
Wir bezeichnen mit P die Aussage Paul sagt die Wahrheit“und mit ¬P die Aussage Paul lügt“. Entsprechend
”
”
verwenden wir O, ¬O, M, ¬M .
Dann ist der erste Satz gleichbedeutend mit P ↔ ¬M , der zweite Satz entspricht M ↔ ¬O und die dritte Aussage
ist O ↔ (¬M ∧ ¬P ).
Die Aufgabe besteht nun darin, eine Belegung der Variablen“P, M und O mit Wahrheitswerten wahr, falsch ∈ B
”
zu finden, sodass alle drei Aussagen den Wahrheitswert wahr haben. Dazu kann man eine Tabelle erstellen: (Wir
verwenden f für falsch und w für wahr)
P
f
f
f
f
w
w
w
w
M
f
f
w
w
f
f
w
w
O
f
w
f
w
f
w
f
w
P ↔ ¬M
f
f
w
w
w
w
f
f
M ↔ ¬O
f
w
w
f
f
w
w
f
O ↔ (¬M ∧ ¬P )
f
w
w
f
w
f
w
f
Nur die eingerahmte Zeile erfüllt alle drei Aussagen.
Die Wahrheitstabelle für ↔ ist dabei:
A
w
w
f
f
B
w
f
w
f
A↔B
w
f
f
w
Aufgabe 1.4
Betrachten Sie die Mengen M1 = {3, 5, 7} und M2 = {4, 5, 6} . Bilden Sie
a)
b)
c)
d)
e)
die Potenzmengen,
das kartesische Produkt M1 × M2 ,
den Schnitt,
die Vereinigung und
die Differenzmengen M1 − M2 und M2 − M1 .
1. 4
Finden Sie Beispiele für
a) eine partielle Funktion von M1 nach M2 ,
b) eine totale Funktion von M1 nach M2 ,
c) eine Relation (die nicht zugleich Funktion ist) auf M1 × M2 .
Lösung zu 1.4
a) P(M1 ) = {∅, {3}, {5}, {7}, {3, 5}, {3, 7}, {5, 7}, {3, 5, 7}}
P(M2 ) = {∅, {4}, {5}, {6}, {4, 5}, {4, 6}, {5, 6}, {4, 5, 6}}
M1 × M2 = {(3, 4), (3, 5), (3, 6), (5, 4), (5, 5), (5, 6), (7, 4), (7, 5), (7, 6)}
M1 ∩ M2 = {5}
M1 ∪ M2 = {3, 4, 5, 6, 7}
M1 − M2 = {3, 7}
M2 − M1 = {4, 6}
b) {(3, 4), (5, 4)} ist eine partielle Funktion, {(3, 4), (5, 4)(7, 5)} ist eine totale Funktion und {(3, 4), (5, 4)(5, 6)}
ist eine Relation, aber keine Funktion.
Aufgabe 1.5
Betrachten Sie f : Z × Z → Z, f (x, y) = 2x + 3y und g : Z → Z, g(x) = 5x − 1.
a) Berechnen Sie f (g(x), x) für x = 1.
b) Berechnen Sie f (f (x, y), g(y)) für x = 1 und y = 2.
c) Bestimmen Sie die Vorschrift der zusammengesetzten Funktion g ◦ f .
Lösung zu 1.5
a) f (g(1), 1) = f ((5 ∗ 1 − 1), 1) = f (4, 1) = 2 ∗ 4 + 3 ∗ 1 = 11
b) f (f (1, 2), g(2)) = f (2 ∗ 1 + 3 ∗ 2, 5 ∗ 2 − 1) = f (8, 9) = 2 ∗ 8 + 3 ∗ 9 = 43
c) g ◦ f : Z × Z → Z, mit g(f (x, y)) = g(2x + 3y) = 5(2x + 3y) − 1 = 10x + 15y − 1.
Aufgabe 1.6
Betrachten Sie die Funktionen f1 : N → N, f2 : N2 → N, g1 : N → N und g2 : N → N
definiert durch
f1 (x) =
1
falls x = 0
2 + f1 (x − 1)) falls x > 0
f2 (x, y) = f1 (x) + 2f1 (y)
g1 (x) = 2x − 1 und
g2 (x) = 3 − x.
Bestimmen Sie die Werte f1 (0), f1 (1), . . . f1 (5) und f2 (g1 (x), g2 (x)) für x = 1 . . . 3.
Lösung zu 1.6
f1 (0) = 1
f1 (1) = 2 + f1 (0) = 2 + 1 = 3
f1 (2) = 2 + f1 (1) = 2 + 3 = 5
f1 (3) = 2 + f1 (2) = 2 + 5 = 7
f1 (4) = 2 + f1 (3) = 2 + 7 = 9
f1 (5) = 2 + f1 (4) = 2 + 9 = 11
Für f2 (g1 (x), g2 (x)) = f2 (2x − 1, 3 − x) ergibt sich für
x = 1 : f2 (2 ∗ 1 − 1, 3 − 1) = f2 (1, 2) = f1 (1) + 2f1 (2) = 3 + 2 ∗ 5 = 13
x = 2 : f2 (2 ∗ 2 − 1, 3 − 2) = f2 (3, 1) = f1 (3) + 2f1 (1) = 7 + 2 ∗ 3 = 13
x = 3 : f2 (2 ∗ 3 − 1, 3 − 3) = f2 (5, 0) = f1 (5) + 2f1 (0) = 11 + 2 ∗ 1 = 13
2. 5
2
URM-Programmierung
Aufgabe 2.1
a) Schreiben Sie ein URM-Programm, das testet, ob die Eingabe gleich 0 ist, dh. bei Eingabe einer 0 soll 1 (für
true) ausgegeben werden, bei allen anderen Eingaben soll 0 (für false) ausgegeben werden.
Genauer: Das Programm soll die Funktion [P ] : N0 → N0
[P ](x) =
0 falls x > 0
1 falls x = 0
berechnen.
Beachten Sie, dass nicht nur der Befehlsteil, sondern auch Eingabe- und Ausgabevereinbarung angegeben
werden.
b) Berechnen Sie für Ihr Programm formal (mit Hilfe der iterierten Zustandstransformation) den Wert [P ](2).
Lösung zu 2.1
a) Das Programm P = in (r1 ); b; out (r2 ) mit b =
1 : r2 ← 0
2 : if r1 = 0 goto 4
3 : goto 5
4 : r2 ← r2 + 1
5:
berechnet die Funktion [P ] : N0 → N0
[P ](x) =
0 falls x > 0
1 falls x = 0
b) Wir müssen [P ](2) = [ out (r2 )] ◦ [b] ◦ [ in (r1 )](2) bestimmen.
Wir berechnen also zunächst aus der Eingabevereinbarung [ in (r1 )] und dem Eingabewert 2 den Anfangszustand z0 , wenden daruf die iterierte Zustandstransformation [b] an und abschließend auf den erreichten Endzustand zs die Ausgabevereinbarung [ out (r2 )].
Der Anfangszustand ist z0 = [ in (r1 )](2) = (1, 2, 0, . . .)
oder genauer: z0 (0) = 1, z0 (1) = 2, z0 (j) = 0 für j ≥ 2.
In Worten: der Befehlszähler (Register 0) wird auf 1 gesetzt, Register 1 erhält den Eingabewert 2 und alle
anderen Register den Wert 0. Auf z0 wenden wir nun die iterierte Zustandstransformation an:
δ(b)(1, 2, 0, . . .) =
[r2 ← 0] (1, 2, 0, . . .) = (2, 2, 0, . . .)
δ(b)(2, 2, 0, . . .) = [ if r1 = 0 goto 4] (2, 2, 0, . . .) = (3, 2, 0, . . .)
δ(b)(3, 2, 0, . . .) =
[ goto 5 ] (3, 2, 0, . . .) = (5, 2, 0, . . .)
=
z3
Wir haben also [b](z0 ) = z3 = (5, 2, 0, . . .).
Auf den Endzustand z3 wird jetzt die Ausgabevereinbarung angewendet und wir erhalten
[ out (r2 )](z3 ) = [ out (r2 )](5, 2, 0, . . .) = 0
Insgesamt haben wir also
[P ](2) = [ out (r2 )] ◦ [b] ◦ [ in (r1 )](2)
= [ out (r2 )] ◦ [b](1, 2, 0, . . .)
= [ out (r2 )](5, 2, 0, . . .)
=0
2. 6
Aufgabe 2.2
a) Schreiben Sie ein URM-Programm, das zwei Zahlen auf Gleichheit testet: Bei Gleichheit soll 1, bei Ungleichheit soll 0 ausgegeben werden.
b) Berechnen Sie [P ](2, 1) und [P ](0, 0) für Ihr Programm aus a).
Lösung zu 2.2
a)
P = in (r1 , r2 ); b; out (r3 ) mit b =
1: r3 ← 0
2: if r1 = 0 goto 7
3: if r2 = 0 goto 10
4: r1 ← r1 −̇1
5: r2 ← r2 −̇1
6: goto 2
7: if r2 = 0 goto 9
8: goto 10
9: r3 ← r3 + 1
Erläuterung:
In der Schleife 2 - 6 werden beide Register parallel heruntergezählt, bis mindestens eines bei 0 angelangt ist. In
den Anweisungen 7 und 8 werden die verschiedenen möglichen Fälle getestet: Anweisung 9 wird nur erreicht,
falls r1 = 0 und r2 = 0, in diesem Fall erhält Register 3 den Wert 1. In allen anderen Fällen (r1 6= 0 ∧ r2 = 0
oder r1 = 0 ∧ r2 6= 0) wird Anweisung 9 übersprungen und Register 3 behält den Wert 0.
b) Um [P ](2, 1) zu berechnen, bestimmt man zunächst den Wert der Eingabefunktion [ in (r1 , r2 )], wendet auf
den dadurch gegebenen Zustand z0 die iterierte Zustandstransformation [b] an und auf den dadurch erreichten
Endzustand zs die Ausgabefunktion [ out (r3 )]. Wir bilden also
[P ](2, 1) = [ out (r3 )] ◦ [b] ◦ [ in (r1 , r2 )](2, 1) = [ out (r3 )] ◦ [b](z0 )
und erhalten z0 = [ in (r1 , r2 )] = (1, 2, 1, 0, . . .) , oder genauer: z0 (0) = 1, z0 (1) = 2, z0 (2) = 1, z0 (j) = 0
für j ≥ 3.
Auf diesen Zustand z0 wird nun wiederholt die Einzelschrittfunktion angewendet:
δ(b)(1, 2, 1, 0, . . .) =
[r3 ← 0] (1, 2, 1, 0, . . .) = (2, 2, 1, 0, . . .)
δ(b)(2, 2, 1, 0, . . .) = [ if r1 = 0 goto 7] (2, 2, 1, 0, . . .) = (3, 2, 1, 0, . . .)
δ(b)(3, 2, 1, 0, . . .) = [ if r2 = 0 goto 8] (3, 2, 1, 0, . . .) = (4, 2, 1, 0, . . .)
δ(b)(4, 2, 1, 0, . . .) =
[r1 ← r1 −̇1] (4, 2, 1, 0, . . .) = (5, 1, 1, 0, . . .)
δ(b)(5, 1, 1, 0, . . .) =
[r2 ← r2 −̇1] (5, 1, 1, 0, . . .) = (6, 1, 0, 0, . . .)
δ(b)(6, 1, 1, 0, . . .) =
[ goto 2] (6, 1, 0, 0, . . .) = (2, 1, 0, 0, . . .)
δ(b)(2, 1, 0, 0, . . .) = [ if r1 = 0 goto 7] (2, 1, 0, 0, . . .) = (3, 1, 0, 0, . . .)
δ(b)(3, 1, 1, 0, . . .) = [ if r2 = 0 goto 8] (3, 1, 0, 0, . . .) = (8, 1, 0, 0, . . .)
δ(b)(8, 1, 0, 0, . . .) =
[ goto 10] (8, 1, 0, 0, . . .) = (10, 1, 0, 0, . . .)
wir haben also zs = (10, 1, 0, 0, . . .).
Nun noch die Ausgabefunktion [ out (r3 )] und wir erhalten [P ](2, 1) = [ out (r3 )](10, 1, 0, 0, . . .) = 0.
Eingabe der Werte 2 und 1 in die Register r1 bzw. r2 liefert die Ausgabe 0 (= Inhalt des Registers r3 im
Endzustand).
Der Ausgabewert des Programms für die Eingabe (0, 0) berechnet sich aus
[P ](0, 0) = [ out (r3 )] ◦ [b] ◦ [ in (r1 , r2 )](0, 0) = [ out (r3 )] ◦ [b](1, 0, 0, 0, . . .) mit
δ(b)(1, 0, 0, 0, . . .) =
[r3 ← 0] (1, 0, 0, 0, . . .) = (2, 0, 0, 0, . . .)
δ(b)(2, 0, 0, 0, . . .) = [ if r1 = 0 goto 7] (2, 0, 0, 0, . . .) = (7, 0, 0, 0, . . .)
δ(b)(7, 0, 0, 0, . . .) = [ if r2 = 0 goto 9] (7, 0, 0, 0, . . .) = (9, 0, 0, 0, . . .)
δ(b)(9, 0, 0, 0, . . .) =
[r3 ← r3 + 1] (9, 0, 0, 0, . . .) = (10, 0, 0, 1, 0 . . .)
und also [P ](0, 0) = [ out (r3 )](10, 0, 0, 1, 0 . . .) = 1.
2. 7
Aufgabe 2.3
Schreiben Sie ein URM-Programm, das den Abstand f (x, y) = |x − y| berechnet.
Informell ausgedrückt: Der Abstand ist größere minus kleinere “.
”
Aber Achtung! Es ist hier nicht sinnvoll, zuerst das Maximum und Minimum zu bestimmen, um dann die Differenz
zu berechnen.
Lösung zu 2.3
Idee: beide Register werden parallel heruntergezählt. Wenn eines von beiden (das kleinere) auf 0 angelangt ist,
enthält das andere gerade den Abstand. (Zeilen1 bis 5)
Da man aber die Ausgabe nicht von einer Bedingung abhängig machen kann ( wenn r1 = 0 dann Ausgabe r2 “oder
”
umgekehrt), muss man ein Ausgaberegister definieren, auf das der Inhalt des Ergebnisses kopiert wird. (Zeilen 6 9, wenn r1 die kleinere Zahl enthielt und Zeile 10 - 13, wenn r2 kleiner war.)
P = in (r1 , r2 ); b; out (r3 ) mit b =
1 : if r1 = 0 goto 6
2 : if r2 = 0 goto 10
3 : r1 ← r1 −̇1
4 : r2 ← r2 −̇1
5 : goto 1
6 : if r2 = 0 goto 14
7 : r2 ← r2 −̇1
8 : r3 ← r3 + 1
9 : goto 6
10: if r2 = 0 goto 14
11: r1 ← r1 −̇1
12: r3 ← r3 + 1
13: goto 10
3. 8
3
Hoare-Kalkül
Aufgabe 3.1
Beweisen Sie mit den Regeln des Hoare’schen Kalküls, dass die Variable a nach Ausführung der Anweisung
a := 5
immer (dh. bei leerer Vorbedingung) den Wert 5 hat.
Lösung zu 3.1
Wir wollen zeigen, dass die Formel
{
(1)
} a := 5 {a = 5}
gültig ist. Dazu verwenden wir Axiom 2 (Wertzuweisung)
{}
{p[u/t]} u := t
{p}
des Hoare’schen Kalküls. Da es sich um ein Axiom handelt, brauchen wir keine Voraussetzungen zu überprüfen
(erkennbar daran, dass die Prämisse leer ist). Die Konklusion ist also richtig für jede Nachbedingung {p}, wenn
die Vorbedingung dadurch aus p hervorgeht, dass man jedes Vorkommen der Variable u (bei uns also a) durch
den Ausdruck t (bei uns also 5) ersetzt. Unsere Nachbedingung ist {a = 5}. Um die Vorbedingung zu erhalten,
müssen wir im Ausdruck {a = 5} jedes Vorkommen der Variable a durch den Ausdruck 5 ersetzen. Wir erhalten
als Vorbedingung {5 = 5} und können aufgrund des Axioms schließen, dass die Korrektheitsformel
{5 = 5} a := 5
(2)
{a = 5}
gilt.
In Worten sagt uns Formel (2) folgendes:
Wenn vor Ausführung der Anweisung a := 5 die Bedingung {5 = 5} wahr ist, dann ist nach der Wertzuweisung
die Aussage {a = 5} richtig.
Oder umgekehrt:
Um zu garantieren, dass nach der Wertzuweisung a := 5 richtig ist, muss vor der Ausführung {5 = 5} erfüllt sein.
Die Aussage {5 = 5} ist aber immer wahr! Formal schreibt sich das so: {} ⇒ {5 = 5}
Wir können also Regel 6 (Konsequenzregel) anwenden und erhalten
{} ⇒ {5 = 5}, {5 = 5} a := 5 {a = 5}
{} a := 5 {a = 5}
Beide Prämissen sind erfüllt, also gilt die Konklusion und (1) ist bewiesen.
Aufgabe 3.2
Beweisen Sie, dass nach Ausführung der Anweisung
if x ≥ y then a := x − y else a := y − x
die Variable a auf jeden Fall (also bei leerer Vorbedingung) einen Wert ≥ 0 hat.
Lösung zu 3.2
Die Behauptung enthät zwei Teilaussagen:
• Nach der Anweisung if x ≥ y then a := x − y else a := y − x
ist a ≥ 0, also soll die Nachbedingung {a ≥ 0} gelten und
• das gilt immer, also unter leerer Vorbedingung: {
}
3. 9
Wir haben also die Gültigkeit der Formel
(3)
{
}
if x ≥ y then a := x − y else a := y − x
{a ≥ 0}
zu zeigen.
Dazu wollen wir Regel 4 (Selektionsregel) anwenden:
{p ∧ B}S1 {q}, {p ∧ ¬B}S2 {q}
{p} if B then S1 else S2 end {q}
In unserem Fall ist
p: { }
B: x≥y
q : {a ≥ 0}
S1 : a := x − y
S2 : a := y − x.
und
Um eine Regel, die kein Axiom ist, anwenden zu können, muss man nachweisen, dass die Prämissen der Regel
erfüllt sind, hier also, dass die beiden Formeln
{p ∧ B}S1 {q} und {p ∧ ¬B}S2 {q} gelten.
Wir setzen unsere Ausdrücke für p, B, S1 , S2 und q ein und erhalten als Zwischenziel:
zeige die Gültigkeit von
(4)
{{ } ∧ (x ≥ y)}
a := x − y
{a ≥ 0}
und
(5)
{{ } ∧ ¬(x ≥ y)} a := y − x {a ≥ 0}
Dies wird mit Axiom 2 erreicht: Danach gilt nämlich
{x − y ≥ 0} a := x − y {a ≥ 0} und wegen (x ≥ y) =⇒ (x − y ≥ 0)
{x ≥ y} a := x − y {a ≥ 0} also ist (4) eine korrekte Formel.
und Regel 6 folgt
Ebenso gilt nach Axiom 2:
{y − x ≥ 0} a := y − x {a ≥ 0} und wegen (x < y) =⇒ (y − x > 0) =⇒ (y − x ≥ 0)
folgt
{x < y} a := y − x {a ≥ 0} also ist auch (5) richtig.
und Regel 6
Aufgabe 3.3
Betrachten Sie das Programm:
x := a
y := b
z := 0
w h i l e ( x > 0 and y > 0 ) do
x = x−1
y = y−1
en d w h ile
a) Zeigen Sie, dass (z + x = a) ∧ (z + y = b) ∧ (a ≥ 0) ∧ (b ≥ 0) eine Invariante für die while-Schleife ist.
b) Beweisen Sie damit, dass das Programm unter der Vorbedingung (a ≥ 0) ∧ (b ≥ 0) korrekt das Minimum von
a und b berechnet, dass also die Nachbedingung
((z = a) ∧ (a ≤ b)) ∨ ((z = b) ∧ (b ≤ a)) gilt.
3. 10
Lösung zu 3.3
a) Behauptung: I : (z + x = a) ∧ (z + y = b) ∧ (x ≥ 0) ∧ (y ≥ 0) ist eine Invariante für die whileSchleife. Es muß also gezeigt werden, dass {I ∧ B}S{I} gilt mit I wie oben, B : (x > 0 ∧ y > 0) und
S : x := x − 1; y := y − 1; z := z + 1.
Wir schließen rückwärts: Nach Axiom 2 gilt
{(z + 1 + x = a) ∧ (z + 1 + y = b) ∧ (x ≥ 0) ∧ (y ≥ 0)}z := z + 1
{(z + x = a) ∧ (z + y = b) ∧ (x ≥ 0) ∧ (y ≥ 0)}
außerdem (nocheinmal Axiom 2 )
{(z + 1 + x = a) ∧ (z + y = b) ∧ (x ≥ 0) ∧ (y − 1 ≥ 0)}y := y − 1
{(z + 1 + x = a) ∧ (z + 1 + y = b) ∧ (x ≥ 0) ∧ (y ≥ 0)}
und noch einmal:
{(z + x = a) ∧ (z + y = b) ∧ (x − 1 ≥ 0) ∧ (y − 1 ≥ 0)}x := x − 1
{(z + 1 + x = a) ∧ (z + y = b) ∧ (x ≥ 0) ∧ (y − 1 ≥ 0)}
also nach Regel 3:
{(z + x = a) ∧ (z + y = b) ∧ (x − 1 ≥ 0) ∧ (y − 1 ≥ 0)}x := x − 1; y := y − 1; z := z + 1
{(z + x = a) ∧ (z + y = b) ∧ (x ≥ 0) ∧ (y ≥ 0)}
Nun gilt aber {I ∧ B} = {x + z = a ∧ y + z = b ∧ x ≥ 0 ∧ y ≥ 0 ∧ x > 0 ∧ y > 0} =⇒
{z + x = a ∧ y + z = b ∧ x − 1 ≥ 0 ∧ y − 1 ≥ 0} und deshalb nach Regel 6 die Behauptung.
b) Wir haben eine Schleifeninvariante I gefunden, damit läßt sich Regel 5 anwenden und es gilt:
{I} while . . . {I ∧ ¬B} also
(z + x = a) ∧ (z + y = b) ∧ (x ≥ 0) ∧ (y ≥ 0) while . . .
{x + z = a ∧ y + z = b ∧ x ≥ 0 ∧ y ≥ 0 ∧ (x ≤ 0 ∨ y ≤ 0)}
Es gilt aber (x + z = a ∧ y + z = b ∧ x ≥ 0 ∧ y ≥ 0 ∧ (x ≤ 0 ∨ y ≤ 0)) =⇒
(x + z = a ∧ y + z = b ∧ (x = 0 ∨ y = 0)) =⇒ (z = a ∧ a ≤ b) ∨ (z = b ∧ b ≤ a)
und es läßt sich wieder Regel 6 anwenden. Man hat also
{I} while . . . {(z = a ∧ a ≤ b) ∨ (z = b ∧ b ≤ a)}
Nun bleibt noch zu zeigen: {a ≥ 0 ∧ b ≥ 0}x := a; y := b; z := 0{I}.
Dies erreicht man aber leicht durch Regel 2, Regel 3 und Regel 6 (vorwärts hingeschrieben, aber rückwärts zu
lesen):
{a ≥ 0 ∧ b ≥ 0} =⇒ {a = a ∧ b = b ∧ a ≥ 0 ∧ b ≥ 0}
{a = a ∧ b = b ∧ a ≥ 0 ∧ b ≥ 0}x := a{x = a ∧ b = b ∧ x ≥ 0 ∧ b ≥ 0}
{x = a ∧ b = b ∧ x ≥ 0 ∧ b ≥ 0}y := b{x = a ∧ y = b ∧ x ≥ 0 ∧ y ≥ 0}
{x = a ∧ y = b ∧ x ≥ 0 ∧ y ≥ 0}z := 0{(z + x = a) ∧ (z + y = b) ∧ (x ≥ 0) ∧ (y ≥ 0)}.
Aufgabe 3.4
Beweisen Sie mit Hilfe des Hoarekalküls, dass die Sequenz
tmp : = a ;
a := b ;
b : = tmp ;
tatsächlich die Inhalte von a und b vertauscht. Fügen Sie entsprechende Zusicherungen in den Programmcode ein.
Lösung zu 3.4
Wir bezeichnen die ursprünglichen Inhalte von a bzw. b mit x bzw. y. Dann müssen wir zeigen, dass unter der
Vorbedingung {a = x∧ b = y } nach Terminierung des Programmstücks gilt: { a = y∧ b = x}
Wir arbeiten von hinten nach vorne:
Wir wenden Axiom 2 auf die Anweisung
wahre Korrektheitsformel
{ a = y∧ tmp = x}
b := tmp
b := tmp
und die Nachbedingung { a = y∧ b = x}an und erhalten die
{ a = y∧ b = x}
Jetzt kennen wir die Nachbedingung, die nach der Anweisung
2 an und erhalten
{ b = y∧ tmp = x}
a := b
a := b
gelten soll. Wir wenden also wieder Axiom
{ a = y∧ tmp = x}
als wahre Korrektheitsformel. Nun noch einmal Axiom 2 anwenden (auf die Anweisung
dingung { b = y∧ tmp = x} ) ergibt die wahre Formel
tmp := a
und die Nachbe-
3. 11
{ b = y∧ a = x}
tmp := a
{ b = y∧ tmp = x}
Wir können also folgende Zusicherungen in den Programmtext einfügen:
{ a = x and b
tmp : = a
{tmp = x and
a := b
{tmp = x and
b : = tmp
{b = x and a
= y }
b = y }
a = y}
= y }
Anwendung der Sequenzregel (zweimal) liefert dann die Behauptung
{a = x∧ b = y } Programmcode { a = y∧ b = x}
Aufgabe 3.5
Ergänzen Sie das unten abgebildete Flußdiagramm um Zusicherungen, die beweisen, dass hierdurch 2a berechnet
wird, falls a ≥ 0 eingegeben wird.
Tip:
Schleifeninvariante ist {z + 2x = 2a ∧ x ≥ 0}.
Start
Eingabe x
z=0
x>0
nein
Ausgabe z
ja
z = z+2
Ende
x = x−1
Abbildung 1: Flussdiagramm zu Aufgabe 3.5
Lösung zu 3.5
Das Flussdiagramm mit Zusicherungen sehen Sie in Abbildung 2.
3. 12
Eingabe x
x = a and x >= 0
z=0
x = a and x >= 0 and z = 0 =>
x>0
nein
z + 2x = 2a and x >= 0
Ausgabe z
ja
z + 2x = 2a and x >= 0 and x !> 0 => z + 2x = 2a and x = 0 => z = 2a
z + 2x = 2a and x > 0 =>
z+2 + 2(x−1) = 2a and x−1 > −1
z = z+2
z + 2(x−1) = 2a and x−1 >= 0
x = x−1
z + 2x = 2a and x >= 0
Abbildung 2: Lösung zu Aufgabe 3.5
4. 13
4
Komplexität
Aufgabe 4.1 (KomplBohne)
Bestimmen Sie die best-case-, worst-case- und average-case-Komplexität des Bohnenproblems aus der Vorlesung.
Welches ist der charakterisierende Parameter? Wann tritt der beste, wann der schlechteste Fall ein?
Betrachten Sie Zwei Bohnen ziehen, Bohnen weglegen, Bohne in die Spielurne (zurück-)legen als jeweils einen
Arbeitsschritt.
Lösung zu 4.1
Characterisierender Parameter für das Urnenproblem ist die Anzahl n der Bohnen, die sich zu Beginn in der
Spielurne befinden. In einer Wiederholungsanweiseng werden
- zwei Bohnen gezogen
- deren Farben miteinander verglichen und
- auf jeden Fall eine Bohne wieder zurückgelegt,
sodass sich die Anzahl n jedesmal um 1 verringert. Die Schleife wird daher genau (n − 1)-mal ausgeführt. Die
Komplexität ist also (unabhängig von der Verteilung der schwarzen und weißen Bohnen) in jedem Fall O(n).
Aufgabe 4.2
Bestimmen Sie die genaue Anzahl der Elementaranweisungen, die bei Ablauf des des Programms aus Aufgabe 3.3
ausgeführt werden.
Lösung zu 4.2
Es werden vor der Schleife 3 Zuweisungen ausgeführt, in der Schleife wird jeweils einmal der logische Ausdruck
ausgewertet, 2 Subtraktionen, 1 Addition und 3 Zuweisungen ausgeführt. Wenn jeder dieser Elementarschritte 1
Kosteneinheit verursacht und m das Minimum von a und b ist, dann sind die Gesamtkosten genau 7m + 3 =
7min(a, b) + 3 Kosteneinheiten.
Aufgabe 4.3
a) Folgender Algorithmus bestimmt das Maximum von n Zahlen:
Modul Maximum ( n )
i := 1
input (x)
max : = x
w h i l e ( i < n ) do
input ( x)
i f ( x > max )
max : = x
endif
i : = i +1
en d w h ile
o u t p u t ( max )
Modulende
Bestimmen Sie die best-case- und die worst-case-Komplexität des Verfahrens. Was ist der charakterisierende
Parameter? Wann tritt der beste Fall, wann der schlechteste Fall ein?
b) Eine kleine Änderung am Algorithmus läßt uns nun nicht das Maximum, sondern die Summe der n eingegebenen Zahlen berechnen:
Modul Summe ( n )
i := 1
input (x)
sum : = x
w h i l e ( i < n ) do
input ( x)
sum : = sum + x
i : = i +1
en d w h ile
o u t p u t ( max )
Modulende
Wie beeinflußt diese Änderung die best-case- und worst-case-Komplexität des Verfahrens?
4. 14
Lösung zu 4.3
a) Der Aufwand hängt ab von der Anzahl der eingegebenen Zahlen, charakterisierender Parameter ist also n. Wir
zählen die Elementaroperationen, die ausgeführt werden (Ein- und Ausgabeoperationen lassen wir unberücksichtigt, sie sind nicht ausschlaggebend für die Qualität des Algorithmus’):
• vor der while-Schleife: 2 Wertzuweisungen
• Auswertung der Schleifenbedingung i < n:
die Schleife wird genau (n − 1)-mal ausgeführt, das erfordert n Vergleiche (Auswertung der Bedingung i
< n).
• innerhalb der Schleife: n − 1 - mal
1 Vergleich (Auswertung der Bedingung x > max), 1 Addition und 1 oder 2 Wertzuweisungen.
Der Gesamtaufwand für die Schleife beträgt also (2n − 1) Vergleiche +(n − 1) Additionen +(n − 1 + k)
Wertzuweisungen mit k ∈ {0, 1, . . . n − 1}.
Insgesamt ergibt sich im besten Fall (wenn die Anweisung max := x kein einziges mal ausgeführt wird, also
k = 0 ist,) 2n − 1 Vergleiche, n − 1 Additionen und n + 1 Wertzuweisungen.
Im schlechtesten Fall (die Anweisung max := x wird bei jedem Schleifendurchlauf ausgeführt, also k =
n − 1,) kommt man auf 2n − 1 Vergleiche, n − 1 Additionen und 2n Wertzuweisungen.
Der beste Fall tritt ein, wenn die größte Zahl als erste eingegeben wird, der schlechteste Fall tritt ein, wenn jede
eingegebene Zahl größer ist als das bisherige Maximum, dh. wenn die n Zahlen in aufsteigend sortierter Reihenfolge eintreffen. In jedem Fall (also auch im Durchschnitt) liegt der Aufwand in O(n), wenn man konstante
Kosten für die Einzeloperationen ansetzt.
b) Wir haben nach wie vor 2 Wertzuweisungen vor der Schleife und n Vergleiche für die Auswertung der Schleifenbedingung.
Nur innerhalb der Schleife vereinfacht sich die Analyse: Man hat in jedem Fall 2 Additionen und 2 Wertzuweisungen.
Insgesamt ergibt sich ein Aufwand von n Vergleichen, 2(n− 1) Additionen und 2(n− 1)+ 2 Wertzuweisungen.
Dieser Aufwand ist bei fester(!) Anzahl n konstant, hängt also nicht von der Größe oder Verteilung oder Sortierung der eingegebenen Werte ab! Die best-case- ,worst-case- und damit auch average-case- Komplexitäten
sind gleich (!) und liegen alle in O(n).
Achtung!
Die Frage ist nicht, für welches n der Aufwand seinen kleinsten oder größten Wert annimmt. Die Aussage die
”
best-case Komplexität wird für n = 0 (oder n = 1) erreicht “ ist falsch!
Aufgabe 4.4
a) Wie oft wird in dem folgenden Programmstück die Anweisung S ausgeführt? Was ist der charakterisierende
Parameter?
i := 0
w h i l e ( i < n ) do
j := 0
w h i l e ( j < i ) do
S;
j : = j +1
en d w h ile
i := i + 1
en d w h ile
b) Welche Laufzeitkomplexität hat das folgende Programmstück? Welche Parameter bestimmen die Laufzeitkomplexität?
i f ( n < a ) t h en
i := 0
w h i l e ( i < a ) do
S;
i : = i +1
en d w h ile
else
i := 0
while ( i < n )
j := 0
while ( j < n )
S;
j : = j +1
4. 15
en d w h ile
i : = i +1
en d w h ile
endif
Lösung zu 4.4
a) Die Anweisung S wird in jedem Durchgang der inneren Schleife genau einmal ausgeführt. Diese innere Schleife wird i-mal durchlaufen, wobei i der Zähler für die äußere Schleife ist. Im ersten Durchgang der äußeren
Schleife wird S also einmal, im zweiten Durchgang der äußeren Schleife wird S zweimal ausgeführt und so
fort.
Die äußere Schleife wird aber genau n-mal durchlaufen, nämlich für die Werte i = 0, i = 1, . . . i = n − 1. So
wird S insgesamt
P(
0 + 1 + 2 + 3 + . . . + (n − 1) = i=0 n − 1) = n(n−1)
-mal ausgeführt.
2
Die Komplexität der beiden ineinander geschachtelten Schleifen ist also O(n2 ).
b) Die Komplexität wird im wesentlichen von der Anzahl der Schleifendurchläufe bestimmt, wir zählen also
wieder, wie oft die Anweisung S erreicht wird.
Im Fall n < a wird S genau a-mal ausgeführt, nämlich so oft, wie die erste Schleife durchlaufen wird.
Im Fall n ≥ a haben wir wieder zwei ineinander geschachtelte Schleifen, wobei aber nun die innere Schleife
genau wie die äußere immer n-mal durchlaufen wird. S wird in diesem Fall also n2 - mal erreicht.
Insgesamt ergibt sich für die Anzahl der Ausführungen von S: anz(S) = max(a, n2 )
Die Komplexität des Programms hängt also von den beiden Parametern a und n ab und liegt für alle drei Fälle
(worst / average / best case) in O(max(a, n2 )).
Aufgabe 4.5
Ein Programm zum Sortieren von n Datensätzen habe eine Laufzeit von t(n) = 2n2 + 7n (gemessen in msec).
a) Wie lange benötigt das Programm zum Sortieren von 1000 Datensätzen?
b) Wieviele Datensätze können maximal in 1 Stunde sortiert werden?
Lösung zu 4.5
a) Die Laufzeit zum Sortieren von n = 1000 Datensätzen ist
t(1000) = 2 ∗ 10002 + 7 ∗ 1000[msec] = 2007000[msec] = 2007[sec] = 33.45[min]
Das Programm benötigt also ungefähr eine halbe Stunde.
b) Wir fragen nun, für welches n die Laufzeit t(n) höchstens 1 Stunde beträgt:
t(n) ≤ 1[h] = 60[min] = 3600[sec] = 3600000[msec] ⇔
2n2 + 7n ≤ 3600000
Wir lösen die quadratische (Un-)Gleichung und erhalten n ≤ 1338.
In einer Stunde können also höchstens 1338 Datensätze sortiert werden.
Aufgabe 4.6
Beweisen Sie:
a) 11n = O(n)
n
= O(1)
b) n−1
c)
d)
e)
f)
g)
h)
2
4
max(n2 , 10 (n+1)
n−2 ) = O(n )
17n − 5 = O(n)
2n
3n−1 = O(1)
2.5n + 4 = O(n)
2n+5
= O(1)
n
1 3
n ) = O(n2 )
min(n2 + 2.4n, 10
4. 16
Lösung zu 4.6
a) Mit n0 = 1 und c = 11 folgt für alle n ≥ n0 : 11n ≤ cn.
n
≤ 2 ⇔ n ≤ 2(n − 1) ⇔ n ≤ 2n − 2 ⇔ −n ≤ −2 ⇔ n ≥ 2 gilt mit n0 = 2, c = 2 die
b) Wegen n−1
Behauptung.
2
) = max(n2 , 10(n + 1)2 n2 ) = 10(n4 + 2n3 + n2 ) ≤ 10(n4 + 2n4 + n4 ) = 40n4 für
c) Es ist max(n2 , 10(n+1)
n−2
alle n ∈ N. Also kann man n0 = 1 und c = 40 wählen und es folgt die Behauptung.
d) Wir müssen zeigen, dass es ein c ≥ 0 und ein n0 ≥ 0 gibt, sodass für alle n ≥ n0 gilt: cf (n) ≥ g(n) mit
f (n) = n und g(n) = 17n − 5. Wir wählen c = 17 und n0 = 0.
2n
e) Hier müssen wir ein c und ein n0 finden, sodass für alle n ≥ n0 gilt: 3n−1
≤ c. Dies erreicht man mit c = 1
und n0 = 1.
f) Gesucht sind ein c ≥ 0 und ein n0 ≥ 0, sodass für alle n ≥ n0 gilt:
g(n) ≤ cf (n) für f (n) = n und g(n) = 2.5n + 4.
Eine erste grobe Abschätzung liefert 2.5n + 4 < 2.5n + 4n < 7n für alle n ≥ 1.
c = 7 und n0 = 1 erfüllen also die Bedingung.
Man kann aber auch etwas knapper abschätzen:
Wegen 2.5n + 4 ≤ 3n ⇔ 4 ≤ 0.5n ⇔ n ≥ 8 könnte man auch c = 3 und n0 = 8 wählen.
Es gibt weitere (genauer: unendlich viele) Zahlenpaare c, n0 , die die Ungleichung ∀n ≥ n0 : 2.5n + 4 ≤ cn
erfüllen.
≤ c ∗ 1 erfüllt. Auch hier gibt es
g) Wir suchen nun ein Zahlenpaar c, n0 , das die Bedingung ∀n ≥ n0 : 2n+5
n
wieder verschiedene Möglichkeiten zur Abschätzung:
2n+5
= 2 + n5 ≤ 2 + 5 = 7 für n ≥ 1, man kann also c = 7, n0 = 1 wählen, oder
n
2n+5
= 2 + n5 ≤ 3 ⇔ n5 ≤ 1 ⇔ 5 ≤ n. Die Bedingung 2n+5
≤ c für alle n ≥ n0 ist also auch für c = 3 und
n
n
n0 = 5 erfüllt.
1 3
h) Wir untersuchen zunächst, welcher der beiden Ausdrücke n2 + 2.4n und 10
n das Minimum bildet. Dazu
1 3
2
müssen wir überlegen, in welchen Bereichen n + 2.4n kleiner bzw. größer ist als 10
n .
1
1 3
2
2
Dazu bestimmen wir die Nullstellen von 10 n − (n + 2.4n) = 10 n(n − 10n − 24) und erhalten
n1 = 0, n2 = 12, n3 = −2.
(Zur Erinnerung:
Die Nullstellen einer quadratischen Gleichung x2 + px + q berechnen sich nach der Formel x1,2 = − 2p ±
q
p2
4 − q .)
1 3
1 3
1 3
Für n > 12 ist 10
n − n2 − 2.4n positiv, also 10
n > n2 + 2.4n, also min(n2 + 2.4n, 10
n ) = n2 + 2.4n.
2
2
Für n > 12 ist aber auch n + 2.4n ≤ 2n , also können wir c = 2 und n0 = 12 wählen und erhalten
1 3
n ) = O(n2 ).
min(n2 + 2.4n, 10
Aufgabe 4.7
Bestimmen Sie die best-case- und die worst-case-Komplexität des Programms
z := 0
u := x
w h i l e u > 0 do
z := z + y
u := u − 1
en d w h ile
Was ist der charakterisierende Parameter?
Lösung zu 4.7
Die Laufzeit des Programms hängt vom Wert der Eingabe x ab, x ist also der charakterisierende Parameter.
Die Schleife wird genau x-mal durchlaufen, in jedem Schleifendurchlauf werden 4 Elementaroperationen ausgeführt (1 Addition, 1 Subtraktion, 2 Wertzuweisungen), also entsteht insgesamt ein Aufwand von 4x Einheiten
für den Schleifenrumpf und x + 1 Einheiten für die Auswertung der Schleifenbedingung. Mit den beiden Zuweisungen vor der Schleife hat das Programm eine Laufzeit von 3 + 5x = O(x).
Diese Laufzeit ist bei festem x immer gleich, also sind best-case-, worst-case- und average-case-Komplexität alle
gleich O(x).
5. 17
5
Abstrakte Datentypen
Aufgabe 5.1
Erweitern Sie den abstrakten Datentyp folge um
a)
b)
c)
d)
die Operation length, die die Anzahl der Elemente (Länge) der Folge bestimmt
die Operation isin, die überprüft, ob eine Folge ein gegebenes Element enthält
die Operation position, die die Positionsnummer eines Elementes in der Folge liefert
die Operation insert, die eine neue Folge bestimmt, indem ein neues Element elem an einer bestimmten Stelle
pos in die alte Folge eingefügt wird
e) die Operation delete, die eine neue Folge bestimmt, indem das Element an der Stelle pos aus der Eingangsfolge
entfernt wird
f) die Operation get, die das Element an der pos-ten Position liefert
Lösung zu 5.1
a) length : M ∗ → N
length(f ) =
0
falls isemptyf olge(f )
1 + length(rest(f )) sonst
b) isin : M ∗ × M → B

falls isemptyf olge(f )
 falsch
wahr
falls a = f irst(f )
isin(f, a) =

isin(rest(f ), a) sonst
c) position : M ∗ × M → N0

falls ¬isin(f, a)
 0
position(f, a) =
1
falls a = f irst(f )

1 + position(rest(f ), a) sonst
d) insert : M ∗ × M × N0 → M ∗

⊥
falls pos > length(f ) + 1 oder pos = 0



concat(makef olge(elem), f )
falls pos = 1
insert(f, elem, pos) =
concat(makef olge(f irst(f )),



insert(rest(f ), elem, pos − 1)) sonst
e) delete : M ∗ × N → M ∗

⊥
falls pos > length(f ) oder pos = 0



rest(f )
falls pos = 1
delete(f, pos) =
concat(makef olge(f irst(f )),



delete(rest(f ), pos − 1)
sonst
f) get : M ∗ × N0 → M

falls pos > length(f ) oder pos = 0
 ⊥
f irst(f )
falls pos = 1
get(f, pos) =

get(rest(f ), pos − 1) sonst
Aufgabe 5.2
Betrachten wir den Datentyp folge auf der Menge M der natürlichen Zahlen (einschließlich 0): M = N.
a) Definieren Sie eine Operation sum, die die Summe der Folgenelemente berechnet.
Beispiel: sum(< 1, 3, 2, 4 >) = 1 + 3 + 2 + 4 = 10
b) Definieren Sie eine Operation add, die aus zwei (gleichlangen!) Folgen eine neue Folge bestimmt, indem die
Folgenglieder komponentenweise addiert werden.
Beispiel: add(< 1, 3, 5, 7 >, < 4, 2, 6, 0 >) =< 5, 5, 11, 7 >
5. 18
Lösung zu 5.2
a) sum : N∗ → N
sum(f ) =
0
falls isemptyf olge(f )
f irst(f ) + sum(rest(f )) sonst
b) add : N∗ × N∗ → N






add(f1 , f2 ) =





⊥
falls length(f1 ) 6= length(f2)
emptyf olge()
falls length(f1 ) = length(f2) = 0
concat(
makef olge(f irst(f1) + f irst(f2 )),
add(rest(f1 ), rest(f2 ))
)
sonst
Aufgabe 5.3
Betrachten wir den Datentyp folge auf der Menge M der natürlichen Zahlen (einschließlich 0): M = N.
a) Definieren Sie eine Operation max, die das Größte der Folgenelemente bestimmt.
Beispiel: max(< 1, 3, 2, 4 >) = 4
b) Definieren Sie eine Operation vmax, die aus zwei (gleichlangen!) Folgen eine neue Folge bestimmt, indem die
Folgenglieder komponentenweise miteinander verglichen werden und das jeweils größere in die neue Folge
übernommen wird.
Beispiel: vmax(< 1, 3, 5, 7 >, < 4, 2, 6, 0 >) =< 4, 3, 6, 7 >
Lösung zu 5.3
a) max : N∗ → N

 ⊥
f irst(f )
max(f ) =

maximum(f irst(f ), max(rest(f )))
b) vmax : N∗ × N∗ → N∗








vmax(f1 , f2 ) =







falls isemptyf olge(f )
falls length(f ) = 1
sonst
⊥
emptyf olge()
makef olge(maximum(f irst(f1), f irst(f2 ))),
concat(
makef olge(maximum(f irst(f1), f irst(f2 ))),
vmax(rest(f1 ), rest(f2 )))
falls length(f1 ) 6= length(f2)
falls length(f1 ) = length(f2) = 0
falls length(f1 ) = length(f2) = 1
sonst
Dabei ist maximum : N × N → N die auf den natürlichen Zahlen bekannte Funktion
maximim(x, y) =
x
y
falls x ≥ y
sonst
Aufgabe 5.4
Definieren Sie eine Operation minimum(f), die das kleinste Element einer Folge f natürlicher Zahlen bestimmt.
Schreiben Sie ein Modul (wie die Module spiegeln, auswerten, ersetzen aus der Vorlesung) zur Implementierung
dieser Operation.
Lösung zu 5.4
minimum : N∗ → N

falls isemptyf olge(f )
 ⊥
f irst(f )
falls f irst(f ) ≤ minimum(rest(f ))
minimum(f ) =

minimum(rest(f )) sonst
5. 19
Modul minimum(f )
wenn nicht isemptyfolge(folge) dann
minimum := first(f)
sonst
minimum := ⊥
end wenn
solange nicht isemptyfolge(f)
wenn first(f) < minimum dann
minimum := first(f)
end wenn
f := rest(f)
end solange
Modulende
Aufgabe 5.5
Im Skript zur Vorlesung finden Sie folgende
Definition 1 Sei M eine total geordnete Menge. Ein Baum t ∈ M △ heißt (binärer) Suchbaum über M , falls für
jeden Knoten k in t gilt: Alle Knoten im linken Teilbaum von k sind kleiner als die Wurzel von k und alle Knoten
im rechten Teilbaum von k sind größer als die Wurzel.
△
Wir bezeichnen die Menge alle Suchbäume über M mit M<
.
In einem binären Suchbaum sind die Knoteneinträge also paarweise verschieden. Außerdem gilt: die inorder-Folge
eines binären Suchbaums liefert die Einträge aufsteigend sortiert.
a) Prüfen Sie, ob die beiden Bäume aus Abb. 3 binäre Suchbäume (über der Menge der natürlichen Zahlen M = N
mit der üblichen kleiner-Relation) sind.
b) Beweisen oder widerlegen Sie die Aussage:
Wenn l und r zwei binäre Suchbäume sind und root(l) < a < root(r), dann ist auch < l, a, r > ein Suchbaum.
c) Definieren Sie eine Operation istSuchbaum(t), die einen Baum t darauf prüft, ob er ein binärer Suchbaum ist.
d) Definieren Sie eine Operation insert(t, a), die einen neuen Wert a in einen Suchbaum t einfügt (so dass die
Suchbaumeigenschaft erhalten bleibt).
e) Implementieren Sie die Operation insert in einem Modul.
f) Bestimmen Sie die best-case- und die worst-case-Komplexität Ihrer Implementierung. Was ist der charakterisierende Parameter? Wann tritt der beste, wann der schlechteste Fall ein?
45
5
7
3
1
7
4
(a)
6
80
12
2
53
27
(b)
Abbildung 3: Bäume zu Aufgabe 5.5
Lösung zu 5.5
a) Bei dem Baum aus Abbildung 3(a) verletzt der Eintrag 2 die Suchbaumeigenschaft, der Baum aus (b) ist
dagegen ein Suchbaum.
b) Die Aussage ist falsch, denn es läßt sich leicht ein Gegenbeispiel konstruieren:
l =< 3, 5, 7 > und r =< 1, 13, 14 > sind zwei Suchbäume und ihre Wurzeleinträge sind kleiner bzw. größer
als (z.B.) 11, aber < l, 11, r > ist kein Suchbaum.
c) Wie wir gesehen haben, genügt es nicht, die Wurzeln der beiden Teilbäume mit der Wurzel des Gesamtbaums
zu vergleichen, sondern man muß den größten Wert des linken Teilbaums und den kleinsten Wert des rechten
5. 20
Teilbaums mit dem Wurzelwert des Gesamtbaums vergleichen. Dazu definieren wir uns zwei Hilfsoperationen
tmin : M △ → N und tmax : M △ → N:
tmin : M △ → N

⊥
falls isemptytree(t)




root(t)
falls
lef ttree(t) = righttree(t) = ε



min(tmin(lef ttree(t)), root(t))
falls lef ttree(t) 6= ε ∧ righttree(t) = ε
tmin(t) =
min(tmin(righttree(t)), root(t))
falls righttree(t) 6= ε ∧ lef ttree(t) = ε




min(



tmin(lef ttree(t)), root(t), tmin(righttree(t)) ) sonst
und tmax : N△ → N durch

⊥




root(t)



max(tmax(lef ttree(t)), root(t))
tmax(t) =
max(tmax(righttree(t)), root(t))




max(



tmax(lef ttree(t)), root(t), tmax(righttree(t))
falls isemptytree(t)
falls lef ttree(t) = righttree(t) = ε
falls lef ttree(t) 6= ε ∧ righttree(t) = ε
falls righttree(t) 6= ε ∧ lef ttree(t) = ε
) sonst
Hierbei bezeichnen min bzw. max die bekannten Funktionen, die die kleinste bzw. größte von mehreren natürlichen Zahlen bestimmen.
Dann können wir istSuchbaum : M △ → B so definieren:

⊥
falls t = ε




wahr
falls
lef ttree(t) = ε ∧ righttree(t) = ε




wahr
falls
righttree(t)
= ε ∧ lef ttree(t) 6= ε




∧
istSuchbaum(lef
ttree(t)) ∧ (max(lef ttree(t) < root(t))



wahr
falls lef ttree(t) = ε ∧ righttree(t) 6= ε
istSuchbaum(t) =
∧ istSuchbaum(righttree(t)) ∧ (min(righttree(t) > root(t))




wahr
falls
lef
ttree(t) 6= ε ∧ righttree(t) 6= ε




∧
istSuchbaum(righttree(t)) ∧ istSuchbaum(lef ttree(t))




∧
(max(lef ttree(t) < root(t) < min(righttree(t))



f alsch sonst
d) Idee: Wenn der Baum t leer ist, erzeugen wir einen Baum mit dem (einzigen) Eintrag a. Wenn root(t) = a ist,
dann lassen wir den Baum t unverändert, (denn dann ist kein Einfügen mehr notwendig, der Wert a ist ja schon
im Baum enthalten). Ansonsten entscheiden wir wie bei contains, ob a im linken oder im rechten Teilbaum
von t eingefügt werden muß.
insert : M △ × M → M △

maketree(ε, a, ε)
falls t = ε



maketree(insert(lef ttree(t), a), root(t), righttree(t)) falls a < root(t)
insert(t, a) =
maketree(lef ttree(t), root(t), insert(righttree(t), a)) falls a > root(t)



t
falls a = root(t)
e) Modul insert(t, a)
wenn ¬ isemptytree(t) dann
wenn a < root(t) dann
t := maketree(insert(lefttree(t), a), root(t), righttree(t))
sonst
wenn a > root(t) dann
t := maketree(lefttree(t), root(t), insert(righttree(t), a))
end wenn
end wenn
sonst
t := maketree(ε, a, ε)
end wenn
insert := t
Modulende
f) Einfügen eines neuen Wertes geschieht immer als Blatt, nie als innerer Knoten. Es muß also bei jedem Einfügen
ein Pfad im Baum von der Wurzel bis zum Blatt verfolgt werden. Die Kosten sind dann proportional zur Länge
des Pfades.
5. 21
Der Aufwand für eine Einfüge-Operation hängt also nicht nur von der Anzahl n der Knoten, sondern auch von
der Gestalt des Baumes und damit von der Reihenfolge ab, in der die n Werte eingefügt wurden.
Es genügt also nicht, eine einzelne insert-Operation zu betrachten, sondern wir müssen alle vorangegangenen
Einfügungen berücksichtigen. Anders ausgedrückt: Wenn wir nach günstigen und ungünstigen Fällen suchen,
müssen wir nach guten bzw. schlechten Einfüge-folgen suchen.
Der beste Fall tritt ein, wenn die Pfade im Baum möglichst kurz sind. Gute Folgen sind also so gemischt, dass
der entstehende Baum möglichst ausbalanciert“ ist, die Pfadlänge ist dann für alle Pfade in O(log n).
”
Der Gesamtaufwand für alle Einfügeoperationen liegt in O(log 1) + O(log 2) + . . . + O(log n) = O(n log n).
Der zu erwartende Aufwand für eine Einfügeoperation ist dann in O(log n).
Ungünstig ist, wenn der Baum einen extrem langen und ansonsten nur sehr kurze Pfade enthält, im Extremfall
entartet er zur Liste. Dies ist der schlechteste Fall. Er tritt ein, wenn die Einfügefolge bereits sortiert ist.
Die Kosten für alle Einfügeoperationen sind dann nämlich in O(1) + O(2) + . . . + O(n) = O(n2 ) und die
Kosten pro einzelner Einfügeoperation liegen demnach in O(n).
Aufgabe 5.6
Entwickeln Sie einen Algorithmus (in Form eines Moduls oder eines Block-Strukturdiagramms), der aus einer
Folge, die natürliche Zahlen in beliebiger Reihenfolge enthält, eine sortierte Folge erzeugt.
Tip: Dazu gibt es viele Möglichkeiten, z.B.
• Verwenden Sie zwei stacks als Hilfsmittel, von denen der erste nur Zahlen enthält, die kleiner sind als alle
Werte im zweiten. Außerdem sollen die Zahlen im ersten stack von unten nach oben aufsteigend sortiert
sein, die im zweiten umgekehrt
oder...
• definieren Sie zum Datentyp f olge eine Operation delete(f, a), die ein Element aus einer Folge entfernt
und benutzen Sie diese zusammen mit minimum aus Aufgabe 5.4
oder...
• verwenden Sie die Ergebnisse aus Aufgabe 5.5.
Lösung zu 5.6
• Sortieren durch Einfügen
Die beiden stacks zusammengenommen (den ersten von unten nach oben gelesen, den zweiten von oben
nach unten) enthalten zu jedem Zeitpunkt eine sortierte Teilfolge von f . Es wird sukzessive das nächste Element der Folge f entnommen und durch umschaufeln“ der beiden stacks die richtige Stelle zum Einfügen
”
gesucht.
Modul SortierenDurchEinfuegen(f)
s1 := emptystack()
s2 := emptystack()
while not isemptyf olge(f ) do
a := f irst(f )
f := rest(f )
while not isemptystack(s1) and top(s1) > a do
push(s2, top(s1))
pop(s1)
endwhile
while not isemptystack(s2) and top(s2) < a do
push(s1, top(s2))
pop(s2)
endwhile
push(a1, a)
endwhile
while not isemptystack(s1) do
push(s2, top(s1))
pop(s1)
endwhile
while not isemptystack(s2) do
f := concat(f, makef olge(top(s2)))
5. 22
pop(s2)
endwhile
return f
modulende
• Sortieren durch Auswaehlen
Man entnimmt der Folge f das kleinste Element und fügt es an eine neue Folge hinten an. Dazu benötigt
man neben der Minimumsuche eine Operation zum Entfernen eines Elementes aus einer Folge, etwa:
delete : M ∗ × M → M ∗

falls ¬contains(f, a)
 f
delete(f, a) =
rest(f )
falls a = f irst(f )

concat(makef olge(f irst(f )), delete(rest(f ), a)) sonst
Damit kann man dann programmieren:
Modul SortierenDurchAuswaehlen(f)
g := emptyf olge()
while not isemptyf olge(f ) do
a := minimum(f )
f := delete(f, a)
g := concat(g, makef olge(a))
endwhile
return g
Modulende
• Baumsortieren
In Aufgabe 5.5 war schon bemerkt worden, dass die inorder-Folge eines binären Suchbaums die Knoten in
sortierter Reihenfolge liefert. (Man kann auch beweisen, dass dies immer so ist.) Diese Beobachtung führt
dann zu folgender Lösung:
Modul BaumSortieren(f)
t := emptytree()
while not isemptyf olge(f ) do
t := insert(t, f irst(f ))
f := rest(f )
endwhile
BaumSortieren := inorder(t)
Modulende
6. 23
6
Formale Sprachen, BNF, EBNF
Aufgabe 6.1
Betrachten Sie die Grammatik G = < {a, b}, {S, A, B}, P, S > mit den Produktionen P (in BNF):
S ::= AbB
A ::= ε | aaA
B ::= ε | bbB | S
Gehören aaaabbb, baaabbb und bbbaab zu L(G)? Geben Sie ggf. eine Ableitung an.
Lösung zu 6.1
S ⊢ AbB ⊢ aaAbB ⊢ aaaaAbB ⊢ aaaabB ⊢ aaaabbbB ⊢ aaaabbb ist eine Ableitung.
baaabbb ist sicherlich nicht in L(G), denn man überlegt sich schnell (exakt: mit vollständiger Induktion über die
Länge der Ableitung), dass alle Wörter, die aus S abgeleitet werden können, eine gerade Anzahl von a’s enthalten.
S ⊢ AbB ⊢ bB ⊢ bS ⊢ bAbB ⊢ bbB ⊢ bbS ⊢ bbAbB ⊢ bbbB ⊢ bbbS ⊢ bbbAbB ⊢ bbbaaAbB ⊢ bbbaabB ⊢
bbbaab ist eine Ableitung.
Aufgabe 6.2
a) Geben Sie eine Grammatik an, die die Sprache L = {an bm cn | n, m ∈ N0 } erzeugt.
b) Von welchem Typ ist Ihre Grammatik?
c) Geben Sie jeweils eine Ableitung für die Wörter ac, b, und aabbbcc an.
Lösung zu 6.2
a) G =< {a, b, c}, {S, T }, P, S} mit P = {S → aSc, S → bT, S → b, S → ǫ, T → bT, T → b} erzeugt die
gewünschte Sprache.
b) G ist kontextfrei.
c) S ⊢ aSc ⊢ ac
S⊢b
S ⊢ aSc ⊢ aaScc ⊢ aabT cc ⊢ aabbT cc ⊢ aabbbcc
Aufgabe 6.3
In vielen Programmiersprachen dürfen Bezeichner (d.s. die vom Programmierer wählbaren Namen für Programme,
Prozeduren, Variablen usf.) aus einer beliebigen Folge von Buchstaben und Ziffern bestehen, aber sie müssen mit
einem Buchstaben beginnen.
a)
b)
c)
d)
e)
Geben Sie eine Grammatik für Bezeichner an.
Leiten Sie den Bezeichner Name1a ab.
Geben Sie eine BNF für Bezeichner an.
Geben Sie eine EBNF für Bezeichner an.
Geben Sie ein Syntaxdiagramm für Bezeichner an.
6. 24
Lösung zu 6.3
a) G =< {a, b, . . . z, A, B, . . . Z, 0, 1 . . . 9}, {Start, Buchstabe, Zeichenfolge , Ziffer }, P, Start > mit
P = { Start
→ Buchstabe Zeichenfolge
Buchstabe
→a
Buchstabe
→b
..
.
→Z
→ Buchstabe Zeichenfolge
→ Ziffer Zeichenfolge
→ε
→0
→1
Buchstabe
Zeichenfolge
Zeichenfolge
Zeichenfolge
Ziffer
Ziffer
..
.
b) Start
Ziffer
→9 }
⊢ Buchstabe Zeichenfolge
⊢ N Zeichenfolge
⊢ N Buchstabe Zeichenfolge
⊢ N a Zeichenfolge
⊢ N a Buchstabe Zeichenfolge
⊢ N a m Zeichenfolge
⊢ N a m Buchstabe Zeichenfolge
⊢ N a m e Zeichenfolge
⊢ N a m e Ziffer Zeichenfolge
⊢ N a m e 1 Zeichenfolge
⊢ N a m e 1 Buchstabe Zeichenfolge
⊢ N a m e 1 a Zeichenfolge
⊢ N a m e 1 a ε = Name1a
c) BNF:
< Bezeichner >
< Buchstabe >
::=
::=
< Buchstabe > | < Buchstabe >< Zeichenfolge >
a | b | ... | z | A | B | ... | Z
< Zeichenfolge >
::=
< Buchstabe >
| < Ziffer >
|
|
< Ziffer >
::=
< Buchstabe >< Zeichenfolge >
< Ziffer >< Zeichenfolge >
0
| 1 |
...
| 9
d) EBNF:
< Bezeichner > ::= < Buchstabe > {< Buchstabe > | < Ziffer >}
< Buchstabe > ::= a | b | . . . | z | A | B | . . . | Z
< Ziffer > ::= 0 | 1 | . . . | 9
e) Syntaxdiagramm: siehe Abb. 4
Buchstabe
Bezeichner
Buchstabe
Ziffer
Abbildung 4: Syntaxdiagramm für Bezeichner
6. 25
Aufgabe 6.4
Erweitern Sie das Syntaxdiagramm für Ausdrücke aus der Vorlesung um einzelne Bezeichner und Methodenaufrufe.
Geben Sie ein entsprechendes Syntaxdiagramm für logische Ausdrücke an.
Lösung zu 6.4
Teildiagramm für < Bezeichner > wie in Aufgabe 6.3.
Teildiagramm für < Zahl > wie in Folien.
Ausdruck
Zahlkonst
(
Ausdruck
)
Ausdruck
+
Ausdruck
Ausdruck
−
Ausdruck
Ausdruck
*
Ausdruck
Ausdruck
/
Ausdruck
Methodenaufruf
Bezeichner
Methodenaufruf
Bezeichner
(
Ausdruck
)
,
Zahlkonst
Zahl
Gleitzahl
Bezeichner
true
false
logAusdruck
(
logAusdruck
)
(
logAusdruck
logAusdruck
)
(
logAusdruck
logAusdruck
)
=
Ausdruck
Ausdruck
<
<
...
Methodenaufruf
6. 26
Aufgabe 6.5
Bei der Darstellung von Modulen haben wir bisher intuitiv gewisse Regeln eingehalten, z.B. haben wir Verzweigungen mit endif und Schleifen mit endwhile abgeschlossen. Fassen Sie die Regeln unserer Modulsprache“ in
”
Syntaxdiagrammen zusammen.
Lösung zu 6.5
Modul
Modul
Bezeichner
Anweisung
Modulende
Anweisung
Wertzuweisung
Verzweigung
Schleife
Wertzuweisung
logAusdruck
Bezeichner
:=
Ausdruck
Verzweigung
if
logAusdruck
then
Anweisung
else
Anweisung
Schleife
while
logAusdruck
do
Anweisung
endwhile
endif
6. 27
Aufgabe 6.6
In Java gelten folgende Syntaxregeln für die Darstellung von Gleitkommazahlen:
Gleitkommazahlen bestehen aus einem optionalen Vorzeichen (+ oder -), einer Ziffernfolge (ohne führende Nullen
oder = 0) für den Vorkommaanteil und einem Nachkommaanteil oder einer Exponentangabe (oder beidem). Der
Nachkommaanteil besteht aus einem Punkt und einer nichtleeren Ziffernfolge, die Exponentangabe besteht aus
einem e oder E, gefolgt von einem optionalen Vorzeichen und mindestens einer, maximal zwei Ziffern.
Beispiel:
+3.14
3.
2.0e-7
0
3498E3
2.5e
sind gültige Darstellungen,
sind keine gültigen Darstellungen.
a) Geben Sie ein Syntaxdiagramm für die Darstellung von Gleitkommazahlen an.
b) Geben Sie eine EBNF für die Darstellung von Gleitkommazahlen an.
Lösung zu 6.6
a) In Abbildung 5 ist das Syntaxdiagramm für eine Gleitkommazahl angegeben.
+
Gleitzahl
Ziffer
−
.
Ziffer0
e
+
E
−
Ziffer
Ziffer
Ziffer
Ziffer
Abbildung 5: Syntaxdiagramm zu Aufgabe 6.6
b)
< Gleitzahl
< Vorzeichen
< Vorkommateil
< Gleitkommateil
< Nachkommateil
< Expoteil
< exp
>
>
>
>
>
>
>
::=
::=
::=
::=
::=
:==
::=
[< Vorzeichen >] < Vorkommateil >< Gleitkommateil >
+ | < GanzZahl >
< Nachkommateil > [< Expoteil >] | [< Nachkommateil >] < Expoteil >
. < Ziffer > {< Ziffer >}
< exp > [< Vorzeichen >] < Ziffer > {< Ziffer >}
e | E
Aufgabe 6.7
Geben Sie eine EBNF für Telefonbucheinträge an. Ein Eintrag besteht aus einem (Nach-)Namen, beliebig vielen
Vornamen, einer mindestens 3-, maximal 5-stelligen Vorwahl, die mit 0 beginnt, einem Schrägstrich und einer
mindestens 3-stelligen Rufnummer, die aber nicht mit 0 beginnen darf. Optional dürfen zu einem Namen maximal
zwei weitere, durch Kommas abgetrennte Telefonnummern angegeben werden.
Lösung zu 6.7
< Eintrag
< Name
< Vorname
< Buchstabe
< Telnr
< Vorwahl
< Rufnr
< Zahl
< ZifferOhne0
< Ziffer
>
>
>
>
>
>
>
>
>
>
::=
::=
::=
::=
::=
::=
::=
::=
::=
::=
< Name > [< Vorname >] < T elnr > [, < T elnr >] [, < T elnr >]
< Buchstabe >< Name > | < Buchstabe >
< Name > [< Name >]
A | B | . . . |z
< Vorwahl > / < Rufnr >
0 < Ziffer >< Ziffer > [< Ziffer >][< Ziffer >]
< ZifferOhne0 >< Ziffer >< Zahl >
< Ziffer > {< Ziffer >}
1 | 2 | . . . |9
0 | < ZifferOhne0 >
6. 28
Aufgabe 6.8
Geben Sie eine EBNF für die Signaturen des Buchbestandes der Bibliothek an. Eine solche Signatur besteht aus
1-3 Großbuchstaben, einer maximal 4-stelligen Ziffernfolge ohne führende Nullen, einer optionalen Angabe über
die Auflage und einer ebenfalls optionalen Angabe über die Anzahl der Exemplare. Die Auflage wird als Ziffernfolge (ohne führende Nullen) in runden Klammern angegeben, die Exemplaranzahl durch ein +-Zeichen und eine
Ziffernfolge (ohne führende Nullen).
Beispiel:
TVI 1067 +7
TYD 27 (2)
TVA 16 (2) +10
und
TZU 87
sind korrekte Signaturen.
Lösung zu 6.8
< Signatur >
< Auflage >
< Anz >
< Buchstabe >
< Ziffer >
< ZifferOhne0 >
::=
::=
::=
::=
::=
::=
< Buchstabe > [< Buchstabe >] [< Buchstabe >]
< ZifferOhne0 > [< Ziffer >] [< Ziffer >] [< Ziffer >]
[< Auflage >] [< Anz >]
( < ZifferOhne0 > {< Ziffer >} )
+ < ZifferOhne0 > {< Ziffer >}
a|b| . . . |z|A| . . . Z
0 | < ZifferOhne0 >
1| . . . |9
7. 29
7
Zahldarstellung
Aufgabe 7.1
Vervollständigen Sie folgende Tabelle:
dezimal
dual
oktal
hexadezimal
Zweierkomplement
18
0101 1101
207
A6
Lösung zu 7.1
dezimal
18
93
135
166
dual
0001
0101
1000
1010
0010
1101
0111
0110
oktal
22
135
207
246
hexadezimal
12
5D
87
A6
Zweierkomplement
1110 1110
1010 0011
0111 1001
0101 1010
hexadezimal
Zweierkomplement
Aufgabe 7.2
Vervollständigen Sie folgende Tabelle:
dezimal
dual
oktal
23
0111 1001
315
4C
Lösung zu 7.2
dezimal
23
121
205
76
dual
0001
0111
1100
0100
0111
1001
1101
1100
oktal
27
171
315
114
hexadezimal
17
79
CD
4C
Zweierkomplement
1110 1001
1000 0111
0011 0011
1011 0100
Aufgabe 7.3
Stellen Sie die Zahlen x = 2304, y = -4096 und z = 4096.001953125 in IEEE-Darstellung mit 32 bit dar.
Lösung zu 7.3
Die Dualdarstellung von 2304 ist 1001 0000 00002 = 1,0012 ∗ 211 .
Die Mantisse ist also 001 0000 0000 0000 0000 0000, der Exponent ist 11+127 = 138 = 1000 10102
und das Vorzeichen ist 0.
Insgesamt: 0100 0101 0001 0000 0000 0000 0000 0000
Die Dualdarstellung von 4096.001953125 ist
1 0000 0000 0000, 0000 0000 12 = 1, 0000 0000 0000 0000 0000 12 ∗ 212 .
Mantisse = 0000 0000 0000 0000 0000 1000,
Exponent = 12 + 127 = 139 = 1000 10112 und Vorzeichen = 0.
Insgesamt: 0100 0101 1000 0000 0000 0000 0000 0100
7. 30
Aufgabe 7.4
Warum hat der Dezimalbruch 0.1 im dualen keine endliche Darstellung? (siehe Skript: 0.110 = 0.000112 )
Lösung zu 7.4
Wir nehmen an, es gebe eine endliche Darstellung
dh. es gebe eine natürliche Zahl n und
Pn der 0.1 im Dualsystem,
Pn
1
Koeffizienten k1 , . . . kn ∈ {0, 1}, sodass 10
= i=1 ki 2−i = 21n i=1 ki 2n−i .
Pn
n
Dann müßte i=1 ki 2n−i = 210 sein. Dies ist aber unmöglich, weil die rechte Seite niemals eine ganze Zahl sein
kann (10 enthält den Primfaktor 5, der sich in keiner Zweierpotenz herauskürzen läßt). 1
Aufgabe 7.5
Stellen Sie die Dezimalzahlen 12.625 und -24.3125 im 32-bit-IEEE-Format dar.
Lösung zu 7.5
12.625 = 23 + 22 + 2−1 + 2−3 = 1100,1012 = 1,1001012 ∗ 23
Das Vorzeichen ist 0, die Mantisse ist 100 1010 0000 0000 0000 0000 und der Exponent ist 3 + 127 =
13010 = 1000 00102 .
Also wird 12.625 dargestellt als 0100 0001 0100 1010 0000 0000 0000 0000.
−24.3125 = 24 + 23 + 2−2 + 2−4 = -11000,01012 = -1,100001012 ∗ 24
Hier ist das Vorzeichen 1, die Mantisse ist 100 0010 1000 0000 0000 0000 und der Exponent ist 4 +
127 = 13110 = 1000 00112 .
Insgesamt: −24.3125 ≡ 1100 0001 1100 0010 1000 0000 0000 0000.
Aufgabe 7.6
Übertragen Sie 0100 1001 0111 0100 0010 0100 0000 0000 aus der 32-bit IEEE-Darstellung in Dezimalschreibweise.
Lösung zu 7.6
Wir zerlegen die Zahl in ihre Bestandteile:
V = 0, E = 1001 00102 = 14610, M = 111 0100 0010 0100 0000 0000.
Der Wert beträgt also (−1)V ∗ (1.M ) ∗ (2E−127 ) = 1.111 0100 0010 0100 0000 0000 ∗ 219 =
1111 0100 0010 0100 00002 = 1.000.00010
1 Dieses
Argument läßt sich verallgemeinern:
Die rationalen Zahlen, die sich in einem b-adischen System (ein Zahlsystem zur Basis b) mit endlich vielen Nachkommastelen darstellen lassen,
sind genau diejenigen, deren Nenner (nach weitestmöglichem Kürzen) keine anderen Primfaktoren enthält als b.
Herunterladen