Grundlagen der Informatik I “Programmierung”
Grundlagen der Informatik I “Programmierung” Grundlagen der Informatik I “Programmierung”
den Wert der zweiten Tabelle zu nehmen, weil es dadurch sehr leicht wird, Veränderungen der Einträge in einer gegebenen Tabelle zu beschreiben. Als Symbol für die Verschmelzung nimmt man das Zeichen ‘+’. Es ist also tab = tab1+tab2 genau dann, wenn gilt domain(tab) = domain(tab1)∪domain(tab2) und für alle arg ∈domain(tab): tab(arg) = if arg ∈domain(tab2) then tab2(arg) else tab1(arg) Beispiel 2.3.4 fak5 + [6↦→720] = [1↦→1, 2↦→2, 3↦→6, 4↦→24, 5↦→120, 6↦→720] fak5 + [6↦→720, 5↦→7] = [1↦→1, 2↦→2, 3↦→6, 4↦→24, 5↦→7, 6↦→720] Um aus einer Tabelle tab die Einträge für {arg1,..,argn} streichen, schreibt man tab / {arg1,..,argn}. Beispiel: fak5 / {1,4} = [2↦→2, 3↦→6, 5↦→120] Wir illustrieren diese Definitionen ausführlich an einem etwas komplexeren Beispiel Beispiel 2.3.5 Die Funktion sum: (IN→IN)→IN soll die Summe aller Werte einer Tabelle bestimmen. Wir verwenden hierzu eine rekursive Beschreibung, d.h. erlauben es, in der Beschreibung von sum wieder die Funktion sum zu verwenden – allerdings mit einem “kleineren” Argument. sum(t) = if t = [] then 0 else let n ∈domain(t) in t(n) + sum(t/{n}) Wir verfolgen die Berechnung von sum auf einer kleinen Tabelle [1↦→1, 2↦→2, 3↦→6]. Durch Einsetzen erhalten wir sum([1↦→1,2↦→2,3↦→6]) = if [1↦→1,2↦→2,3↦→6] = [] then 0 else let n ∈domain([1↦→1,2↦→2,3↦→6]) in [1↦→1,2↦→2,3↦→6](n) + sum([1↦→1,2↦→2,3↦→6]/{n}) Auswerten der Bedingung ergibt, da die Tabelle [1↦→1,2↦→2,3↦→6] nicht leer ist if falsch = [] then 0 else let n ∈domain([1↦→1,2↦→2,3↦→6]) in [1↦→1,2↦→2,3↦→6](n) + sum([1↦→1,2↦→2,3↦→6]/{n}) Folglich wird der else-Zweig ausgewertet: let n ∈ domain([1↦→1,2↦→2,3↦→6]) in t(n) + sum(t/{n}) Nach Ausrechnen der domain-Funktion: let n ∈ {1,2,3} in [1↦→1,2↦→2,3↦→6](n) + sum([1↦→1,2↦→2,3↦→6]/{n}) Wir wählen ein beliebiges n ∈{1,2,3}, z.B. n=2 und erhalten: [1↦→1,2↦→2,3↦→6](2) + sum([1↦→1,2↦→2,3↦→6]/{2}) Weiteres Auswerten ergibt: 2 + sum([1↦→1,3↦→6]/{2}) Nun beginnt das ganze von vorne mit der Summe der kleineren Tabelle sum([1↦→1,2↦→2,3↦→6]) = ... = 2 + let n ∈ {1,3} in [1↦→1,3↦→6](n) + sum([1↦→1,3↦→6]/{n}) = 2 + [1↦→1,3↦→6](3) + sum([1↦→1,3↦→6]/{3}) = 2 + 6 + sum([1↦→1]) = 2 + 6 + let n ∈ {1} in [1↦→1](n) + sum([1↦→1]/{n}) = 2 + 6 + [1↦→1](1) + sum([1↦→1]/{1}) = 2 + 6 + 1 + sum([]) = 2 + 6 + 1 + 0 = 9 Die Funktion sum war ein einfaches Beispiel für eine Funktion “höherer” Ordnung, d.h. eine Funktion, die andere Funktionen (Tabellen) als Eingabe nimmt. Zuweilen geht man noch ein wenig weiter und benutzt Funktionen, die auch Funktionen als Werte bestimmen. Ein bekanntes Beispiel hierfür ist das unbestimmte Integral.
Wir geben hier eine Funktion an, die für beliebige Funktionen auf natürlichen Zahlen die Funktionstabelle der Werte 0..n bestimmt. Beispiel 2.3.6 Map(f,n) = if n = 0 then [0↦→f(0)] else Map(f,n-1) + [n↦→f(n)] Dann gilt Map : (IN→IN)×IN→ (IN→IN) und es ist zum Beispiel Map(λn.n 2 , 5) = [0↦→0, 1↦→1, 2↦→4, 3↦→9, 4↦→16, 5↦→25] 2.3.5 Listen Bei der Erklärung der Semantik prädikatenlogischer Formeln haben wir neben dem Begriff der Tabelle auch Listen benutzt, also geordnete Aufzählungen von Werten, die (anders als bei Mengen) möglicherweise auch mehrfach vorkommen. Die Menge aller Listen mit Werten aus der Grundmenge A wird mit A ∗ bezeichnet. Wir begrenzen Listen durch spitze Klammern. bezeichnet die leere Liste, die Liste, die aus den Werten 1,2,3,4 und dann wieder 3 besteht. Die Funktion head:A ∗ →A bestimmt das erste Element einer Liste, falls die Liste nicht leer ist (ansonsten ist head undefiniert). So ist zum Beispiel head() = 1 Die Funktion tail:A ∗ →A ∗ bestimmt den Rest der Liste nach Entfernung des ersten Elementes. Zum Beispiel ist tail() = . Für die leere Liste ist tail() = definiert. Wir benötigen außerdem noch eine Operation, welche Listen zusammensetzt. Diese Funktion wird mit dem Infixsymbol & bezeichnet. So ist & = Aus diesen Grundoperatoren lassen sich eine Reihe weiterer nützlicher Funktionen bilden, die wir zuweilen verwenden werden. Beispiel 2.3.7 1. Die Funktion length:A ∗ →IN bestimmt die Länge einer Liste. Sie läßt sich rekursiv wie folgt beschreiben: length(l) = if l= then 0 else length(tail(l))+1 Damit berechnet sich z.B. die Länge der Liste wie folgt: length() = if = then 0 else length(tail())+1 = length(tail())+1 = length()+1 = (if = then 0 else length(tail())+1) + 1 = (length()+1) + 1 = (if = then 0 else length(tail())+1) + 1 + 1 = (length()+1) + 1 + 1 = (if = then 0 else length(tail())+1) + 1 + 1 + 1 = 0 + 1 + 1 + 1 = 3 2. Die in Abbildung 2.13 auf Seite 47 benutzte Funktion einelementig:A ∗ →IB ergibt sich durch einen Test auf die Länge 1: einelementig(l) = length(l)=1 Man beachte, daß bei der Definition dieser Funktion keine weitere if-Abfrage nötig war, da sie selbst einen Wahrheitswert als Ergebnis liefert. 3. Die (Infix-)Funktion cons:A×A ∗ →A ∗ hängt ein Element vor den Anfang einer Liste. Sie ist eigentlich nur eine Kurzschreibweise für einen Spezialfall der &-Operation: cons(a,l) = & l
- Seite 22 und 23: 5. Kompatibilität ist ein Maß daf
- Seite 24 und 25: ∀a ∈IN. teilt(a,a) ∧ teilt(a,
- Seite 26 und 27: durchgeführt werden, sofern man ni
- Seite 28 und 29: 1.2.2.3 Diskussion Bei der deskript
- Seite 30 und 31: Da 1215 ist wird die erste Anweisun
- Seite 32 und 33: Rahmen zu weit führen. Auffällig
- Seite 34 und 35: Durch das Konzept des Übersetzers
- Seite 36 und 37: und “örtlich” durch Zerlegung
- Seite 38 und 39: 1.3.4 Prozeduralisierung Das Beispi
- Seite 40 und 41: Man könnte das Objektkonzept von d
- Seite 43 und 44: Kapitel 2 Logik und formale Sprachb
- Seite 45 und 46: 2.1 Formale Sprachbeschreibungen Di
- Seite 47 und 48: möglichen Alternativen auf der rec
- Seite 49 und 50: Wenn wir eine Menge von Sprachen be
- Seite 51 und 52: Da wir im folgenden den Begriff der
- Seite 53 und 54: Für die Zuordnung zwischen der Obj
- Seite 55 und 56: Diese Form der Definition findet ih
- Seite 57 und 58: K1: Kommutativ-Gesetz E1 ∧E2 ≡
- Seite 59 und 60: Axiomenschemata: L1 A ∨ ¬A L2 (A
- Seite 61 und 62: In dem Kapitel über die Programmve
- Seite 63 und 64: 2. Es werden Quantoren eingeführt,
- Seite 65 und 66: s (T, state) = wahr s (F, state) =
- Seite 67 und 68: • x ist gebunden in p(t1, ..., tn
- Seite 69 und 70: Der Wert einer Aussage mit mehreren
- Seite 71: Wichtig ist, daß die Auswahl des W
- Seite 75: wichtigste formale Sprache zur Besc
- Seite 78 und 79: Wir wollen jedoch deutlich darauf h
- Seite 80 und 81: Buch, sondern sollten besser als ei
- Seite 82 und 83: Viel sinnvoller ist es, bei der Bes
- Seite 84 und 85: Entsprechend ihrer beabsichtigten B
- Seite 86 und 87: Klassen sind rein statische Beschre
- Seite 88 und 89: leeren Verweis (d.h. von machen Per
- Seite 90 und 91: haben wie z.B. “(jahr:INTEGER)”
- Seite 92 und 93: und diese erzeugten Objekte mit Ver
- Seite 94 und 95: Bei der Erzeugung von Objekten mitt
- Seite 96 und 97: über den Namen eines Attributs Wer
- Seite 98 und 99: • Die Veränderung und Auswertung
- Seite 100 und 101: 3.5 Copy- und Referenz-Semantik In
- Seite 102 und 103: 3.5.2 expanded: Klassen mit Copy-Se
- Seite 104 und 105: class LIST[X] creation new feature
- Seite 106 und 107: Dieses Problem wird durch das Konze
- Seite 108 und 109: 3.7.1 Zusicherungen Eiffel logische
- Seite 110 und 111: class ARRAY[X] creation make featur
- Seite 112 und 113: class ARRAY[X] creation make featur
- Seite 114 und 115: formulieren und zu überwachen. Eig
- Seite 116 und 117: 3.8.2 Export geerbter Features Norm
- Seite 118 und 119: Ist also p ein Personenobjekt und a
- Seite 120 und 121: Definition 3.8.5 (Konformität) Ein
den Wert <strong>der</strong> zweiten Tabelle zu nehmen, weil es dadurch sehr leicht wird, Verän<strong>der</strong>ungen <strong>der</strong> Einträge in<br />
einer gegebenen Tabelle zu beschreiben. Als Symbol für die Verschmelzung nimmt man das Zeichen ‘+’. Es<br />
ist also tab = tab1+tab2 genau dann, wenn gilt<br />
domain(tab) = domain(tab1)∪domain(tab2)<br />
und für alle arg ∈domain(tab):<br />
tab(arg) = if arg ∈domain(tab2) then tab2(arg) else tab1(arg)<br />
Beispiel 2.3.4<br />
fak5 + [6↦→720] = [1↦→1, 2↦→2, 3↦→6, 4↦→24, 5↦→120, 6↦→720]<br />
fak5 + [6↦→720, 5↦→7] = [1↦→1, 2↦→2, 3↦→6, 4↦→24, 5↦→7, 6↦→720]<br />
Um aus einer Tabelle tab die Einträge für {arg1,..,argn} streichen, schreibt man tab / {arg1,..,argn}.<br />
Beispiel: fak5 / {1,4} = [2↦→2, 3↦→6, 5↦→120]<br />
Wir illustrieren diese Definitionen ausführlich an einem etwas komplexeren Beispiel<br />
Beispiel 2.3.5<br />
Die Funktion sum: (IN→IN)→IN soll die Summe aller Werte einer Tabelle bestimmen. Wir verwenden<br />
hierzu eine rekursive Beschreibung, d.h. erlauben es, in <strong>der</strong> Beschreibung von sum wie<strong>der</strong> die Funktion<br />
sum zu verwenden – allerdings mit einem “kleineren” Argument.<br />
sum(t) = if t = []<br />
then 0<br />
else let n ∈domain(t) in t(n) + sum(t/{n})<br />
Wir verfolgen die Berechnung von sum auf einer kleinen Tabelle [1↦→1, 2↦→2, 3↦→6].<br />
Durch Einsetzen erhalten wir<br />
sum([1↦→1,2↦→2,3↦→6]) =<br />
if [1↦→1,2↦→2,3↦→6] = []<br />
then 0<br />
else let n ∈domain([1↦→1,2↦→2,3↦→6]) in [1↦→1,2↦→2,3↦→6](n) + sum([1↦→1,2↦→2,3↦→6]/{n})<br />
Auswerten <strong>der</strong> Bedingung ergibt, da die Tabelle [1↦→1,2↦→2,3↦→6] nicht leer ist<br />
if falsch = []<br />
then 0<br />
else let n ∈domain([1↦→1,2↦→2,3↦→6]) in [1↦→1,2↦→2,3↦→6](n) + sum([1↦→1,2↦→2,3↦→6]/{n})<br />
Folglich wird <strong>der</strong> else-Zweig ausgewertet:<br />
let n ∈ domain([1↦→1,2↦→2,3↦→6]) in t(n) + sum(t/{n})<br />
Nach Ausrechnen <strong>der</strong> domain-Funktion:<br />
let n ∈ {1,2,3} in [1↦→1,2↦→2,3↦→6](n) + sum([1↦→1,2↦→2,3↦→6]/{n})<br />
Wir wählen ein beliebiges n ∈{1,2,3}, z.B. n=2 und erhalten:<br />
[1↦→1,2↦→2,3↦→6](2) + sum([1↦→1,2↦→2,3↦→6]/{2})<br />
Weiteres Auswerten ergibt:<br />
2 + sum([1↦→1,3↦→6]/{2})<br />
Nun beginnt das ganze von vorne mit <strong>der</strong> Summe <strong>der</strong> kleineren Tabelle<br />
sum([1↦→1,2↦→2,3↦→6]) = ...<br />
= 2 + let n ∈ {1,3} in [1↦→1,3↦→6](n) + sum([1↦→1,3↦→6]/{n})<br />
= 2 + [1↦→1,3↦→6](3) + sum([1↦→1,3↦→6]/{3})<br />
= 2 + 6 + sum([1↦→1])<br />
= 2 + 6 + let n ∈ {1} in [1↦→1](n) + sum([1↦→1]/{n})<br />
= 2 + 6 + [1↦→1](1) + sum([1↦→1]/{1})<br />
= 2 + 6 + 1 + sum([])<br />
= 2 + 6 + 1 + 0<br />
= 9<br />
Die Funktion sum war ein einfaches Beispiel für eine Funktion “höherer” Ordnung, d.h. eine Funktion, die<br />
an<strong>der</strong>e Funktionen (Tabellen) als Eingabe nimmt. Zuweilen geht man noch ein wenig weiter und benutzt Funktionen,<br />
die auch Funktionen als Werte bestimmen. Ein bekanntes Beispiel hierfür ist das unbestimmte Integral.