Praktische Informatik I – Der Imperative Kern Rekursive Funktionen
Prof. Dr. Stefan Edelkamp
Institut für Künstliche Intelligenz
Technologie-Zentrum für Informatik und Informationstechnik (TZI) Am Fallturm 1, 28359 Bremen
+49-(0)421-218-64007 www.tzi.de/~edelkamp
Stefan Edelkamp (IAI) PI 1 – Imperativer Kern November 21, 2013 1 / 15
Outline
1 Rekursive Funktionen: Einzeiler, die es in sich haben
2 Fakultät
3 Fibonacci-Zahlen
4 Ackermann-Zahlen
5 Ulam-Zahlen
Zielstellung
In dieser Lerneinheit sollen Sie lernen, dass Programme bei der Ausführung mathematischer Funktionen helfen, indem sie rekursive Definitionen direkt umsetzen und dass die Anzahl der rekursiven Aufrufe die Effizienz des Programmes bestimmt.
Das Prinzip derVollständigen InduktionBeweise vereinfacht Beweise.
Es ist demDomino-Prinzipverwandt – man stößt einen Stein an und nach und nach fallen alle.
Neben den Menge dernatürlichen Zahlen– die aus der Zahl 1 und einer Menge von Nachfolgern besteht, lassen sich viele interessante mathematischen Funktionen elegant rekursiv formulieren.
Tatsächlich ist ein großer Teil der theoretischen Informatik dem Studium derrekursiven Funktionengewidmet.
Stefan Edelkamp (IAI) PI 1 – Imperativer Kern November 21, 2013 3 / 15
Outline
1 Rekursive Funktionen: Einzeiler, die es in sich haben
2 Fakultät
3 Fibonacci-Zahlen
4 Ackermann-Zahlen
5 Ulam-Zahlen
Die Vertauschungszahl
DieFakultäteiner Zahlnist die Anzahl von linearen Anordnungenn sich unterscheidender Objekte
Die Definitionn! =1·. . .·n=n·(n−1)!mit 0! =1 führt zu einem rekursiven Aufrufverhalten.
Programm 1:Die Fakultätsfunktion.
public classFactorial {
/∗∗
∗Computes number of permutations of n objects
∗
∗@param n integer number
∗@return n!
∗/
public longf(longn) { return(n==0) ? 1 :n∗f(n−1);
} }
Übersetzen Sie das Programm 1 und starten Sie es mit dem Aufruf 6
(Die Ausgabe sollte 6! = 720 lauten). Nutzen Sie weitere Werte an Stelle von 6. Die Zahlen wachsen schnell. Wann kommt es zu einem Überlauf? Wechseln Sie den Datentyp von int nach long und starten Sie das Programm erneut.
Der Computer verwendet zur Verarbeitung von Unterprogrammen und so auch zur Auflösung von Rekursionen Rücksprungadressen.
Funktionsparameter und lokale Variablen werden gebunden, die jeweiligen Bearbeitungsfenster auf einem Stapel gelegt. Die Rekursion für die Fakultätsfunktion ist jedoch einfach und kann im
Übersetzungsprozess in die Maschinensprache eliminiert werden (Stichwort: Endrekursion).
Stefan Edelkamp (IAI) PI 1 – Imperativer Kern November 21, 2013 5 / 15
Outline
1 Rekursive Funktionen: Einzeiler, die es in sich haben
2 Fakultät
3 Fibonacci-Zahlen
4 Ackermann-Zahlen
5 Ulam-Zahlen
Die Vermehrung von Kaninchen
Fibonacci-Zahlensind durchf(n) =f(n−1) +f(n−2)mitf(0) =0 undf(1) =1 festgelegt.
Fibonaccis Aufgabe zu der Vermehrung von Kaninchen:
Kaninchen bringen jeden Monat ein neues Paar auf die Welt zu bringen, und sie gebären erstmals im zweiten Monat nach ihrer Geburt. Weil das erste Paar schon im ersten Monat Nachwuchs bekommt, kann man es verdoppeln, so dass nach einem Monat 2 Paare da sind. Von diesen vermehrt sich das erste im zweiten Monat wieder und so gibt es im zweiten Monat 3 Paare. Von denen werden in einem Monat 2 wieder trächtig, so dass im dritten Monat 2
Kaninchenpaare geboren werden; und so sind es dann in diesem Monat 5 Paare. Von denen werden im selben Monat 3 trächtig, usw.
Stefan Edelkamp (IAI) PI 1 – Imperativer Kern November 21, 2013 7 / 15
Programm 2:Fibonaccis Funktion.
public classFibonacci {
public intf(intn) {
return(n<=1) ?n:f(n−1) +f(n−2);
} }
Das erste Programm ist durch Mehrfachaufrufeineffizient(siehe Übung)
Fibonacci-Zahlen sind zentral für die Analysekomplexer Strukturen
Outline
1 Rekursive Funktionen: Einzeiler, die es in sich haben
2 Fakultät
3 Fibonacci-Zahlen
4 Ackermann-Zahlen
5 Ulam-Zahlen
Stefan Edelkamp (IAI) PI 1 – Imperativer Kern November 21, 2013 9 / 15
Nicht zu zähmende Riesen
DieAckermann-Funktionist eine schnell wachsene Funktion:
Fürx =0 ista(x,y) =y +1, füry =0 ista(x,y) =a(x−1,1)und sonst ista(x,y) =a(x−1,a(x,y−1)).
Alan Turings PionierarbeitOn computable numbers with an application to the Entscheidungsproblembelegt, wie eng Zahlen mit dem
Berechenbarkeitsbegriff zusammenhängen.
Mit der Hilfe der Ackermann-Funktion konnten dieGrenzen von Computerberechnungsmodellenaufgezeigt werden.
Programm 3: Die Ackermann-Funktion.
public classAckermann {
public inta(intn,intm) {
return(n== 0) ?m+1 : (m== 0) ?a(n−1,1) :a(n−1,a(n,m−1));
}
Outline
1 Rekursive Funktionen: Einzeiler, die es in sich haben
2 Fakultät
3 Fibonacci-Zahlen
4 Ackermann-Zahlen
5 Ulam-Zahlen
Stefan Edelkamp (IAI) PI 1 – Imperativer Kern November 21, 2013 11 / 15
Kein Ende in Sicht?
Die folgende interessante Funktionu wurde von Stanislaw Marcin Ulam beschrieben: Fürx =1 istu(x) =1, fürx >1 undx gerade ist u(x) =u(bx/2c), ansonsten istu(x) =3x+1.
Der Wert derUlam-Funktionist (soweit bekannt) immer 1.
Die Eingabe von 6 im Programm 4 ergibt
u(6),u(3),u(10),u(5),u(16),u(8),u(4),u(2),u(1), 1
Programm 4:Die Ulam-Funktion.
public classUlam {
public intu(intn) {
System.out.print("u("+n+"),");
returnn== 1 ? 1 :n%2 == 0 ?u(n/2) :u(3∗n+1);
}
Peano Axiome
Durch die folgendeAxiomatisierung der natürlichen Zahlennach den Peano-Axiomensind viele mathematische Funktionsdefinitioninhärent rekursiv
0 ist eine natürliche Zahl.
jede natürliche Zahlnhat eine natürliche Zahln0 als Nachfolger.
0 ist kein Nachfolger einer natürlichen Zahl.
natürliche Zahlen mit gleichem Nachfolger sind gleich.
enthältX die 0 und mit jeder natürlichen Zahlnauch deren Nachfolgern0, so bilden die natürlichen Zahlen eine Teilmenge vonX.
Stefan Edelkamp (IAI) PI 1 – Imperativer Kern November 21, 2013 13 / 15
Geschlossene Formen
Manchmal lassen sich rekursive Funktionen ingeschlossener Form ausdrücken oder abschätzen.
Das hilft bei der Bestimmung desFunktionswachstums So kann man überprüfen, dassn!≥(n/2)n/2gilt.
Merke:
Rekursive Funktionen erhalten in ihrem Rumpf mindestens einmal den eigenen Bezeichner.
Ein Aufruf endet nur dann nach einer endlichen Anzahl von Schritten, wenn die Abbruchbedingung erfüllt ist.
Durch Speichern von Zwischenergebnissen kann man
Diskussion
Wächst jede rekursiv definierte Zahl schnell?
Welches Problem ergibt sich bei Programmen mit mehr als einem rekursiven Aufruf? Wie kann man es angehen?
Kann jedes rekursive Programm in ein iteratives Programm umgewandelt werden?
Stefan Edelkamp (IAI) PI 1 – Imperativer Kern November 21, 2013 15 / 15