Rekursion mit VBA

Lies diesen Artikel und viele weitere mit einem kostenlosen, einwöchigen Testzugang.

Manche Abläufe erfordern den Einsatz von Schleifen mit einer bestimmten Anzahl von Durchläufen oder einer vordefinierten Abbruchbedingung. In speziellen Fällen reichen Schleifen jedoch nicht aus, um zum Ziel zu kommen: Dann müssen rekursiv definierte Funktionen her. Dies sind solche Funktionen, die sich selbst aufrufen. Der vorliegende Artikel erklärt, wie solche Funktionen arbeiten und liefert einige Beispiele.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1307_RekursionMitVBA.mdb.

Beispiel Fakultät

Bei der rekursiven Programmierung ruft sich eine Funktion selbst auf. Für einen einfachen Einstieg nehmen wir ein Beispiel, dass vielerorts zum Einsatz kommt: Die Berechnung der Fakultät einer Zahl. Die Fakultät einer Zahl n wird so definiert:

n! = n x (n-1) x ... x 2 x 1

Das bedeutet, dass man alle ganzen Zahlen miteinander multipliziert, die kleiner oder gleich der Zahl n sind. Ein Sonderfall ist die Fakultät von 0 – hierfür ist nämlich der Wert 1 definiert.

Um den Schritt zur Rekursion zu machen, definieren wir die Fakultät etwas anders:

n! = n x (n-1)!

Die Fakultät ist hier als das Produkt der Zahl selbst mit der Fakultät der nächstkleineren Zahl definiert. Und diese Fakultät entspricht natürlich wiederum die Zahl multipliziert mit der Fakultät der nächstkleineren Zahl. Es gibt hier auch eine Ausnahme: Wenn n den Wert 1 annimmt, ist die Fakultät von n gleich 1.

Fakultät per VBA

Wenn wir die Fakultät mit einer Funktion berechnen möchten, die sich selbst aufruft, müssen wir dieser zunächst einmal die Zahl übergeben, für welche die Fakultät berechnet werden soll. Der Funktionskopf sieht also beispielsweise so aus:

Public Function Fakultaet(lngZahl                        As Long) As Long

Beim ersten Aufruf soll die Funktion die Fakultät für die Zahl lngZahl ermitteln. Diese entspricht aber wiederum dem Produkt der Zahl und der Fakultät der Zahl minus Eins.

Innerhalb der Funktion rufen wir die Funktion also erneut auf – mit der um Eins verminderten Zahl. Das Ergebnis multiplizieren wir dann mit der Zahl selbst.

Die Anweisung sieht also so aus:

Fakultaet = lngZahl * Fakultaet(lngZahl - 1)

Insgesamt erhielten wir nun eine Funktion wie die Folgende:

Public Function Fakultaet(lngZahl                        As Long) As Long
     Fakultaet = lngZahl *                  Fakultaet(lngZahl - 1)
End Function

Wenn Sie die Funktion nun etwa aus dem Direktfenster mit dem Befehl Debug.Print Fakultaet(4) aufrufen, sollte das Ergebnis eigentlich 24 lauten (1 x 2 x 3 x 4). Allerdings zeigt Access nach kurzer Zeit eine Fehlermeldung an, die wie in Bild 1 aussieht. Was ist hier passiert Ganz einfach: Wir haben der Funktion nicht mitgeteilt, wann sie anhalten soll. In diesem Fall berechnet sie nacheinander die Fakultät für 4, 3, 2, 1, 0, -1, -2 und so weiter.

Fehler bei rekursiver Funktion ohne Abbruchbedingung

Bild 1: Fehler bei rekursiver Funktion ohne Abbruchbedingung

Der Fehler wird schließlich dadurch ausgelöst, dass die Funktion die Zwischenergebnisse jeweils im Arbeitsspeicher unterbringen muss – und mit wachsender Anzahl Aufrufe ist der Speicher irgendwann einmal voll.

Also bauen wir die Funktion wie in Listing 1 auf. Die Funktion prüft bei jedem Aufruf zunächst, ob der Wert der mit lngZahl gelieferten Zahl gleich Eins ist. Ist dies der Fall, ist auch die Fakultät Eins – die Funktion braucht also kein weiteres Mal aufgerufen zu werden. Der Ablauf zur Berechnung der Fakultät von 4 sieht also so aus:

Public Function Fakultaet(lngZahl As Long) As Double
     If lngZahl = 1 Then
         Fakultaet = 1
     Else
         Fakultaet = lngZahl * Fakultaet(lngZahl - 1)
     End If
End Function

Listing 1: Rekursive Berechnung der Fakultät einer Zahl

  • Erster Aufruf mit lngZahl = 4
  • Zweiter Aufruf mit lngZahl = 3
  • Dritter Aufruf mit lngZahl = 2
  • Vierter Aufruf mit lngZahl = 1: Fakultaet liefert 1 zurück, der vierte Aufruf ist beendet.
  • Im dritten Aufruf wird der Funktionswert Fakultaet auf 2 x 1 = 2 eingestellt, der dritte Aufruf ist beendet.
  • Im zweiten Aufruf wird der Funktionswert Fakultaet auf 3 x 2 = 6 eingestellt, der zweite Aufruf ist beendet.
  • Im ersten Aufruf wird der Funktionswert Fakultaet auf 4 x 6 = 24 eingestellt, der erste Aufruf ist beendet und gibt als Ergebnis 24 zurück.

Hier wird auch gleich deutlich, dass eine rekursiv definierte Funktion immer Aktionen vor dem Aufruf der nächsten Ebnee ausführen kann, aber auch Aktionen nach diesem Aufruf. In diesem Fall tritt die Zuweisung des Ergebnisses immer erst nach dem Aufruf der nächsten Ebene und deren Abarbeitung auf.

Iteration statt Rekursion

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

Testzugang

eine Woche kostenlosen Zugriff auf diesen und mehr als 1.000 weitere Artikel

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar