Praktische Informatik I – Der Imperative Kern Rekursive Funktionen

Werbung
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
Stefan Edelkamp (IAI)
PI 1 – Imperativer Kern
November 21, 2013
2 / 15
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 der Vollständigen Induktion Beweise vereinfacht Beweise.
Es ist dem Domino-Prinzip verwandt – man stößt einen Stein an und
nach und nach fallen alle.
Neben den Menge der natü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 der rekursiven Funktionen gewidmet.
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
Stefan Edelkamp (IAI)
PI 1 – Imperativer Kern
November 21, 2013
4 / 15
Die Vertauschungszahl
Die Fakultät einer Zahl n ist die Anzahl von linearen Anordnungen n
sich unterscheidender Objekte
Die Definition n! = 1 · . . . · n = n · (n − 1)! mit 0! = 1 führt zu einem
rekursiven Aufrufverhalten.
Programm 1: Die Fakultätsfunktion.
public class Factorial
{
/∗∗
∗ Computes number of permutations of n objects
∗
∗ @param n integer number
∗ @return n!
∗/
public long f(long n) {
return (n==0) ? 1 : n∗f(n−1);
}
}
Übersetzen
Sie
und starten
Sie es mitNovember
dem 21,
Aufruf
Stefan Edelkamp
(IAI)das Programm
PI 1 1
– Imperativer
Kern
2013
65 / 15
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
6 / 15
Die Vermehrung von Kaninchen
Fibonacci-Zahlen sind durch f (n) = f (n − 1) + f (n − 2) mit f (0) = 0
und f (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 class Fibonacci
{
public int f(int n) {
return (n<=1) ? n : f(n−1) + f(n−2);
}
}
Das erste Programm ist durch Mehrfachaufrufe ineffizient (siehe
Übung)
Fibonacci-Zahlen sind zentral für die Analyse komplexer Strukturen
Stefan Edelkamp (IAI)
PI 1 – Imperativer Kern
November 21, 2013
8 / 15
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
Die Ackermann-Funktion ist eine schnell wachsene Funktion:
Für x = 0 ist a(x, y ) = y + 1, für y = 0 ist a(x, y ) = a(x − 1, 1) und
sonst ist a(x, y ) = a(x − 1, a(x, y − 1)).
Alan Turings Pionierarbeit On computable numbers with an application
to the Entscheidungsproblem belegt, wie eng Zahlen mit dem
Berechenbarkeitsbegriff zusammenhängen.
Mit der Hilfe der Ackermann-Funktion konnten die Grenzen von
Computerberechnungsmodellen aufgezeigt werden.
Programm 3: Die Ackermann-Funktion.
public class Ackermann
{
public int a(int n, int m) {
return (n == 0) ? m+1 : (m == 0) ? a(n−1,1) : a(n−1,a(n,m−1));
}
}
Stefan Edelkamp (IAI)
PI 1 – Imperativer Kern
November 21, 2013
10 / 15
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 Funktion u wurde von Stanislaw Marcin
Ulam beschrieben: Für x = 1 ist u(x) = 1, für x > 1 und x gerade ist
u(x) = u(bx/2c), ansonsten ist u(x) = 3x + 1.
Der Wert der Ulam-Funktion ist (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 class Ulam
{
public int u(int n) {
System.out.print("u("+n+"),");
return n == 1 ? 1 : n%2 == 0 ? u(n/2) : u(3∗n+1);
}
}
Stefan Edelkamp (IAI)
PI 1 – Imperativer Kern
November 21, 2013
12 / 15
Peano Axiome
Durch die folgende Axiomatisierung der natürlichen Zahlen nach den
Peano-Axiomen sind viele mathematische Funktionsdefinition inhärent
rekursiv
0 ist eine natürliche Zahl.
jede natürliche Zahl n hat eine natürliche Zahl n0 als Nachfolger.
0 ist kein Nachfolger einer natürlichen Zahl.
natürliche Zahlen mit gleichem Nachfolger sind gleich.
enthält X die 0 und mit jeder natürlichen Zahl n auch deren
Nachfolger n0 , so bilden die natürlichen Zahlen eine Teilmenge
von X .
Stefan Edelkamp (IAI)
PI 1 – Imperativer Kern
November 21, 2013
13 / 15
Geschlossene Formen
Manchmal lassen sich rekursive Funktionen in geschlossener Form
ausdrücken oder abschätzen.
Das hilft bei der Bestimmung des Funktionswachstums
So kann man überprüfen, dass n! ≥ (n/2)n/2 gilt.
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
Mehrfachberechnungen vermeiden.
Stefan Edelkamp (IAI)
PI 1 – Imperativer Kern
November 21, 2013
14 / 15
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
Herunterladen