Grundlagen der Informatik I “Programmierung”
Grundlagen der Informatik I “Programmierung” Grundlagen der Informatik I “Programmierung”
1.2.2.3 Diskussion Bei der deskriptiven Problembeschreibung gab es keinen Aufwand für die Programmierung, d.h. Problembeschreibung ist gleichzeitig die Problemlösung. Für funktionale Programme muß man die deskriptive Beschreibung (Regeln 1 bis 3 aus 1.2.1.1) erst in ein Programm umsetzen und diese Umsetzung auch begründen (beweisen) können. Der Aufwand ist also höher. Wozu dann das Ganze, wenn man zusätzlich keine Fragen (ggt(?,n)=t) stellen, sondern nur Funktionen (ggt(m,n)=?) beschreiben kann? Im wesentlichen liegt der Unterschied in der Effizienz. In funktionalen Programmen beschreibt man direkt das Verfahren und überläßt die Lösungssuche nicht einer allgemeinen Suchstrategie. Das Opfer, das zugunsten einer verbesserten Effizienz gebracht werden muß, ist die Programmentwicklung und wesentlicher noch die Rechtfertigung oder Verifikation des Programms. In unserem Fall ist die Rechtfertigung noch einfach: Die Implikationen der Regeln werden in die beiden Fallunterscheidungen überführt. Die Zulässigkeit dieser Transformation kann bewiesen werden. Der Programmieraufwand für funktionale Programme auf der Basis einer deskriptiven Problembeschreibung ist relativ gering, wie Sie im Vergleich zu den nächsten Sprachen sehen werden. Da sie konzeptuell sehr einfach und daher leicht erlernbar sind, werden sie an anderen Universitäten als erste Programmiersprachen in dem Grundstudium eingeführt. Daß sie noch nicht allgemein verwendet werden, liegt ebenso wie bei deskriptiven Sprachen an der Effizienz. In diesen Sprachen steht keine Möglichkeit zur Verfügung einen Wert zu verändern. Bei der Auswertung von Formeln benötigen die neuen Werte auch neue Plätze im Speicher. Das ist besonders kritisch bei komplexen Werten wie Matrizen, bei denen sich nur eine Teilinformation ändert (Wertänderung eines Elements der Matrix). Hier wird stets eine vollständig neue Version des komplexen Wertes aufgebaut, statt nur in der alten Version die Teilinformation zu ändern. Der Effekt ist, daß viel Zeit und Platz benötigt wird beim fortwährenden Umbau von Werten (Matrizen, die sich nur in einem Wert voneinander unterscheiden). Eine Vermeidung dieses Aufwands kann man durch Kenntnis des “Platzes” der Teilinformation erreichen, um dort nur die Teilinformation aber nicht die anderen Teilkomponenten zu ändern. Wir kommen damit zu einem Speicherbegriff, der Plätze bereitstellt, in denen Werte abgespeichert und dort auch abgeändert werden können. Diese Abänderungvorschriften nennt man Anweisungen. Sie bilden die Basis der imperativen Programmiersprachen. Ist die notwendige Kenntnis der Speicherstruktur beschränkt auf das Wissen, daß z.B. nur ganze Zahlen, reelle Zahlen, Texte usw. gespeichert werden können, so spricht man von höheren oder problemorientierten Programmiersprachen (Pascal, Modula, Ada, Fortran, Cobol, Eiffel, disziplinert verwendetes C usw.). Ist jedoch auch das Wissen über die interne Darstellung der Werteklassen als Bitmuster (Codierung der Werte in eine Folge von Nullen und Einsen) notwendig, so spricht man von maschinennahen Sprachen (Familie der Assembler, aber z.T. auch C). Jede dieser Programmiersprachen basiert auf einem ihr eigenen abstrakten “Maschinenmodell”, das erklärt, wie die Programme durchgeführt werden. Für die höheren Programmiersprachen ist dieses Modell konzeptionell einfach, für die maschinennahen Sprachen durch seine Menge von Details unübersichtlich. 1.2.3 Problemorientierte imperative Sprachen Im Gegensatz zu den funktionalen Sprachen, deren Interpretation auf dem bekannten Mechanismus der Funktionsauswertung aufsetzt, müssen wir für die Programmiersprachen zuerst das Grundkonzept einer abstrakten Maschine erklären, damit die Anweisungen an diese Maschine verständlich sind. In ihrer einfachsten Form besteht eine abstrakte Maschine (für Programmiersprachen) aus einer Tabelle, die links die Variablennamen (Namen von Plätzen) und rechts Werte (die momentan gespeicherten Werte der Variablen) hat. Diese Tabelle wird Speicher genannt. Neben dem Speicher gibt es noch den Befehlszähler, der angibt, welcher Befehl im Programm als nächster durchgeführt wird. Die wichtigsten Befehle sind die Vorschrift, den Wert einer Variablen zu ändern (Wertzuweisung) und die Befehle, die angeben, welcher Befehl als nächstes ausgeführt werden soll (Kontrollanweisungen). Bei den letzteren sind die Fallunterscheidung und die Schleife die wichtigsten Befehle.
1.2.3.1 Imperatives Programm Nun entwickeln wir den ggt weiter in Richtung eines Programms in einer imperativen, höheren Programmiersprache (Notation von Pascal). Wenn wir die funktionale Version nochmals anschauen, so sehen wir, daß durch die Rekursion immer wieder die beiden Fallunterscheidungen, jedoch mit veränderten Werten, durchgeführt werden. Geben wir dem ersten Argument den Speicherplatz m, dem zweiten Argument den Speicherplatz n und dem Resultat den Speicherplatz t, so sieht der Speicher vor der Ausführung folgendermaßen aus: Speicher m 12 n 15 t ? noch kein Wert bekannt Die Ausführung der Funktion besteht dann in der Ausführung der Fallunterscheidungen, aber statt des rekursiven Aufrufs mit den veränderten Argumenten werden die entsprechenden Speicherplätze überschrieben: m:=m-n bedeutet, der Wert des Speicherplatzes von m wird mit dem Wert vom m-n überschrieben: if m>n then m:=m-n else if mn 3 then m:=m-n 4 else if mn 3 then m:=m-n 4 else if m
- Seite 1 und 2: Grundlagen der Informatik I “Prog
- Seite 3 und 4: Inhaltsverzeichnis 1 Einführung 1
- Seite 5 und 6: 3.7.1 Zusicherungen . . . . . . . .
- Seite 7 und 8: Abbildungsverzeichnis 2.1 Syntax de
- Seite 9: 4.9 Verifikationsregeln und Prädik
- Seite 12 und 13: edeutet wiederum, exakte Prognosen
- Seite 14 und 15: Stoff betrifft, so werden Sie eine
- Seite 16 und 17: ilden die Grundlage zum Erwerb des
- Seite 18 und 19: Komplexität 1. A.. V. Aho, E. Hopc
- Seite 20 und 21: ser Zweig der Informatik beschäfti
- 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 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 und 72: Wichtig ist, daß die Auswahl des W
- Seite 73 und 74: Wir geben hier eine Funktion an, di
- Seite 75: wichtigste formale Sprache zur Besc
1.2.3.1 Imperatives Programm<br />
Nun entwickeln wir den ggt weiter in Richtung eines Programms in einer imperativen, höheren Programmiersprache<br />
(Notation von Pascal). Wenn wir die funktionale Version nochmals anschauen, so sehen wir, daß durch<br />
die Rekursion immer wie<strong>der</strong> die beiden Fallunterscheidungen, jedoch mit verän<strong>der</strong>ten Werten, durchgeführt<br />
werden. Geben wir dem ersten Argument den Speicherplatz m, dem zweiten Argument den Speicherplatz n<br />
und dem Resultat den Speicherplatz t, so sieht <strong>der</strong> Speicher vor <strong>der</strong> Ausführung folgen<strong>der</strong>maßen aus:<br />
Speicher<br />
m 12<br />
n 15<br />
t ? noch kein Wert bekannt<br />
Die Ausführung <strong>der</strong> Funktion besteht dann in <strong>der</strong> Ausführung <strong>der</strong> Fallunterscheidungen, aber statt des rekursiven<br />
Aufrufs mit den verän<strong>der</strong>ten Argumenten werden die entsprechenden Speicherplätze überschrieben:<br />
m:=m-n bedeutet, <strong>der</strong> Wert des Speicherplatzes von m wird mit dem Wert vom m-n überschrieben:<br />
if m>n<br />
then m:=m-n<br />
else if mn<br />
3 then m:=m-n<br />
4 else if mn<br />
3 then m:=m-n<br />
4 else if m