22.08.2013 Aufrufe

Grundlagen der Informatik I “Programmierung”

Grundlagen der Informatik I “Programmierung”

Grundlagen der Informatik I “Programmierung”

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

• Die Variante einer rekursiven Routine muß ausdrücken, daß die Routine nur endlich oft aufgerufen<br />

werden kann. Wie bei den Schleifen benötigt man hierzu einen Integer-Ausdruck, <strong>der</strong> stets größer gleich<br />

Null ist und bei jedem rekursiven Aufruf mindestens um eins kleiner wird. An<strong>der</strong>s als bei <strong>der</strong> Schleife<br />

muß diese aber durch einen Ausdruck beschrieben werden, <strong>der</strong> nichts über die inneren Eigenschaften <strong>der</strong><br />

Routine sagt, son<strong>der</strong>n nur von den äußeren Merkmalen abhängt – also den formalen Parametern, dem<br />

untersuchten Objekt und ggf. dem Resultat. Wir müssen die Variante also im Extremfall durch einen<br />

Integer-Ausdruck Var(yr,actual) beschreiben, um alle möglichen Abhängigkeiten zu berücksichtigen.<br />

In unserem Beispiel fak berechnung ist die Variante ein sehr einfacher Ausdruck, nämlich <strong>der</strong> Parameter<br />

n selbst. Aufgrund <strong>der</strong> Vorbedingung n>0 ist die Variante stets größer gleich Null. Bei jedem rekursiven<br />

Aufruf wird sie geringer, da fak berechnung(n-1) <strong>der</strong> einzige rekursive Aufruf ist. In den meisten<br />

rekursiven Routinen ist die Variante zum Glück ähnlich einfach und offensichtlich wie hier.<br />

Eine Komplikation, welche das Aufstellen einer formalen Verifikationsregel erheblich erschwert, ist die Tatsache,<br />

daß eine Routine beliebig viele rekursive Aufrufe haben darf und diese beliebig tief in an<strong>der</strong>en Programmkonstrukten<br />

eingebaut sein dürfen. Da Rekursion aber als eine Art Gegenstück zu Schleifen anzusehen<br />

ist, macht es wenig Sinn, rekursive Aufrufe innerhalb einer Schleife zu plazieren. Auch würde ein Korrektheitsbeweis<br />

dadurch nahezu unmöglich. Daher darf man davon ausgehen, daß rekursive Aufrufe – wie in unserem<br />

Beispiel – nur innerhalb von bedingten Anweisungen o<strong>der</strong> Fallunterscheidungen vorkommen. Somit kann man<br />

zu jedem rekursiven Aufruf eine Bedingung angeben, die besagt, wann dieser Aufruf überhaupt ausgeführt<br />

werden soll. Die Existenz einer solchen Bedingung ist wichtig für einen Terminierungsbeweis, da ohne diese<br />

Bedingung die Routine sich unendlich oft aufrufen würde.<br />

Die in Abbildung 4.15 angegebene Verifikations-“regel” für rekursive Routinen beschreibt eine Beweismethodik,<br />

welche das oben Gesagte etwas stärker präzisiert und sich an <strong>der</strong> Schleifenregel (Abbildung 4.11)<br />

orientiert.<br />

Es sei r eine Routine mit formalen Argumenten yr und abstrakten Vor- und Nachbedingungen<br />

prer bzw. postr. Der Anweisungsteil Br enthalte insgesamt m rekursive Aufrufe <strong>der</strong> Form<br />

entityi.r(Ai(yr)) , wobei jeweils entityi ein Objekt und Ai(yr) Ausdrücke für aktuelle Argumente<br />

beschreibt. Bedi(yr) beschreibe die Bedingung für den i-ten rekursiven Aufruf.<br />

Die Routine r ist genau dann total korrekt, wenn gilt<br />

Partielle Korrektheit: Unter <strong>der</strong> Annahme, daß alle rekursiven Aufrufe die Spezifikation von r<br />

erfüllen, kann mithilfe <strong>der</strong> Verifikationsregeln 38 gezeigt werden<br />

{ prer(yr)} Br { postr(yr)}<br />

Terminierung: Es gibt einen Integer-Ausdruck Var, <strong>der</strong> nur von den Argumenten yr und dem<br />

aktuellen Objekt abhängt und für den gezeigt werden kann<br />

prer(yr) ⇒ Var(yr,Current)≥0<br />

und für jeden rekursiven Aufruf entityi.r(Ai(yr))<br />

prer(yr) ∧ Bedi(yr) ⇒ prer(Ai(yr)) ∧ Var(Ai(yr),entityi)

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!