BuK-Übung01 G2

Aus ProgrammingWiki

Wechseln zu: Navigation, Suche

Inhaltsverzeichnis

Indirekter Beweis

Aufgabe

Zeigen Sie indirekt, dass x eine gerade Zahl ist, wenn x² gerade ist.

Lösung

Ausgang: ist eine gerade Zahl
Ziel: ist eine gerade Zahl
d.h.:
ist eine ungerade Zahl
ist eine ungerade Zahl

Der indirekte Beweis startet mit der Annahme und führt zu einem Widerspruch des Ausgangs .






Idealisierter Rechner

Aufgabe

Entwickeln Sie einen Interpreter für den in der Vorlesung angegebenen idealisierten Computer. Verwenden Sie AtoCC.

Lösung

Die Grammatik für den gewünschten Interpreter wird im Folgenden dargestellt.

P -> K
K ->  inst K | EPSILON
inst -> read nr
inst -> readn nr const
inst -> add nr nr nr
inst -> sub nr nr nr
inst -> mul nr nr nr
inst -> div nr nr nr
inst -> sqr nr nr
inst -> zero? nr
inst -> le nr nr nr
inst -> goto nr
inst -> out nr
inst -> out text
inst -> stop

Unter [1] kann der aus dieser Grammatik generierte Interpreter getestet werden. Bei der Implementation der S-Ausdrücke gibt es einige interessante Überlegungen.

Die erste besteht in der Angabe der Zeilennummern innerhalb der zu interpretierenden Quelltexte. Dabei gibt es zwei Möglichkeiten. Entweder die jeweilige Zeilennummer wird vom Programmierer an den Anfang jeder Zeile geschrieben oder die Zeilennummern werden nicht mitgeschrieben. Beide Möglichkeiten haben Vor- und Nachteile.

Schreibt man die Zeilennummern mit, so können Sprunganweisungen leichter implementiert werden, dass der Programmierer stets sieht, in welcher Zeile der Befehl steht, zu dem gesprungen werden soll. Andererseits ist es kompliziert, neue Quelltextzeilen einzufügen, da dadurch die Nummerierung ab der Einfügestelle angepasst werden müssen.

Lässt man die Zeilennummern weg, so muss der Programmierer die Zeilen per Hand abzählen, um die gewünschten Sprünge zu realisieren. Dafür können neue Quelltextzeilen einfacher zwischen bereits bestehenden Zeilen eingefügt werden.

Da das Einfügen neuer Zeilen in der Programmierung sehr oft vorkommt, verzichten wir auf die explizite Angabe von Zeilennummern. Dadurch kann ein Programmierer indirekt dazu "gezwungen" werden, nicht willkürlich hin und her zu springen, sondern Sprünge immer in einem kleinen Abstand innerhalb des Quelltextes vorzunehmen.

Eine weitere Überlegung kommt bei der Behandlung von Sprüngen zum Tragen. Um die S-Ausdrücke möglichst einfach zu halten ist man geneigt, sofort beim Auftreten eines bestimmten Tokens dieses auch zu behandeln - also den entsprechenden Befehl auszuführen. Die Interpretation des Quelltextes erfolgt also bereits während des Parsens. Dadurch können Sprünge aber nur vorwärts durchgeführt werden. Wir haben uns für eine andere Möglichkeit entschieden. Die S-Ausdrücke dienen dabei dafür, eine Liste mit auszuführenden Befehlen zu erstellen. Wenn das Parsen beendet ist, steht somit eine Befehlsliste zur Abarbeitung zur Verfügung. Dadurch können Sprünge sowohl vorwärts als auch rückwärts durchgeführt werden. Daraus ergibt sich die Möglichkeit der Implementation von Schleifen.

Aufgabe

Entwerfen und testen Sie ein Programm, dass die folgende Funktion berechnet:

Lösung

Bei der Lösung der Aufgabe sind wir innerhalb der Gruppe auf unterschiedliche Meinungen getroffen. Die Meinungen reichen von: "Eine Endlosschleife zeigt, dass ein Wert nicht definiert ist" bis "Man kann kein Programm schreiben dessen Ausgabe bei bestimmten Parametern nicht definiert ist". Für die erste Meinung spricht das Argument, dass der Benutzer nicht weiß, wann das Programm terminiert und somit davon "ausgeht", dass das Ergebnis nicht definiert ist. Heißt "davon ausgehen" aber auch das die Ausgabe wirklich nicht definiert ist?

In der Mathematik ist z.B. die Division durch 0 nicht definiert. Innerhalb eines Computers aber sehr wohl. Tritt eine Division durch 0 auf, so wird ein bestimmtest Flag im Prozessor gesetzt. Durch dieses Flag ist es zum Beispiel innerhalb von Java möglich, eine ArithmeticException mit der Meldung "/ by zero" zu werfen. Das Verhalten der Division einer Ganzahl durch 0 ist in Java also sehr wohl definiert und besteht darin, eine Ausnahme zu werfen. Bei der Division einer Gleitkommazahl durch 0 ist in Java nicht einmal die Exception vorhanden sondern ein "echtes" Ergebnis: "Infinity" - also unendlich. Dieser Ansatz geht der zweiten Meinung voraus (kein Programm mit nicht definiertem Verhalten möglich). Selbst eine Endlosschleife kann ein definiertes Verhalten sein. Denn die Aussage "für n>=4 läuft das Programm endlos weiter" ist ein definiertes Verhalten. Obwohl das Verhalten definiert ist, ist die Lösung aber nicht definiert, da eine Endlosschleife kein Element der Menge der natürlichen Zahlen ist. Die gegebene Funktion ist aber eine Abbildung einer natürlichen Zahl auf eine natürliche Zahl.

Uunter [2] ein Beispielprogramm für den idealisierten Computer, welches mittels einer Endlosschleife realisiert ist.

Persönliche Werkzeuge