In der Mathematik ordnet eine Funktion einem Argument einen Funktionswert zu.
Beispiel: Die Funktion
successor : ℕ → ℕ
ordnet einer beliebigen natürlichen Zahl n die nächstgrößere natürliche Zahl n+1 zu:
successor(n) = n+1
Hierbei ist n das Argument und n+1 der zugehörige Funktionswert.
Die Funktion
max : ℕ × ℕ → ℕ
ordnet einem beliebigen Paar von natürlichen Zahlen (a, b) die größere dieser beiden Zahlen zu.
max(a, b) = |
|
Hierbei ist das Paar (a, b) das Argument und das Maximum von a und b der zugehörige Funktionswert.
In Programmiersprachen wird der Begriff der Funktion in ähnlicher Weise benutzt.
Auch eine Java-Funktion kann einem Argument einen Funktionswert zuordnen. In der Funktionsdefinition wird dabei zunächst allgemein angegeben, wie der Funktionswert aus dem Argument zu berechnen ist. Beim Funktionsaufruf erhält die Funktion dann einen konkreten Argumentwert, führt die Berechnung durch und gibt den entsprechenden Funktionswert zurück.
Beispiel: Die Definition der Funktion successor aus dem obigen Beispiel lässt sich in Java wie folgt realisieren:
Der Name der Funktion ist successor, als Argument erhält die Funktion eine int-Zahl n, und mit der Anweisung return wird der berechnete Funktionswert zurückgegeben. Der Typ des Rückgabewertes wird ganz am Anfang, vor dem Funktionsnamen angegeben, er ist hier ebenfalls int. Der Berechnungsteil der Funktion wird zwischen geschweifte Klammern eingeschlossen.
Ein Aufruf der Funktion sieht beispielsweise wie folgt aus:
k=successor(17);
Als Argumentwert wird hier für n der Wert 17 eingesetzt; als Ergebnis des Funktionsaufrufs wird der Wert 18 zurückgegeben und der Variablen k zugewiesen.
Beispiel: Die Definition der Funktion max lässt sich in Java wie folgt realisieren:
Diese Funktionsdefinition orientiert sich genau an der mathematischen Definition der Maximumfunktion.
Ein möglicher Aufruf der Funktion ist beispielsweise
x=max(z, 0);
Hierbei wird der Wert der Variablen z, sofern dieser positiv ist, und ansonsten der Wert 0 zurückgegeben und der Variablen x zugewiesen.
Variablen dienen zur Speicherung von Werten, z.B. von Zwischenergebnissen von Berechnungen. Fallen Zwischenergebnisse bei einer Berechnung in einer Funktionsdefinition an, so werden diese zweckmäßigerweise in lokalen Variablen gespeichert. Lokale Variablen werden innerhalb der Funktionsdefinition deklariert. Sie haben nur innerhalb der Funktionsdefinition Gültigkeit, von außerhalb sind sie nicht zugänglich.
Beispiel: Die Funktion exp2(n) ordnet einer nichtnegativen ganzen Zahl n als Funktionswert die Zweierpotenz 2n zu. Mit folgender Funktion lässt sich die Berechnung durchführen:
Hierbei sind i und f lokale Variablen, diese sind nur innerhalb der Funktionsdefinition gültig.
Im Gegensatz zu lokalen Variablen stehen globale Variablen. Globale Variablen werden außerhalb der Funktionsdefinition deklariert. Sie haben außerhalb und innerhalb der Funktionsdefinition Gültigkeit. In Java sind die Attribute der Klasse, in der die Funktion definiert ist, globale Variablen.
Beispiel: In folgendem Programmstück wird eine globale String-Variable trennsymbol deklariert und mit dem Wert ";" belegt. Die nachfolgende Funktion verkette fügt zwei Zeichenreihen unter Einschluss des Trennsymbols zusammen.
Ein Aufruf der Funktion, etwa mit s=verkette("alpha", "beta");, liefert als Funktionswert das Ergebnis "alpha;beta"; dieser wird hier der Variablen s zugewiesen.
Normalerweise haben innerhalb einer Funktion sowohl die dort deklarierten lokalen Variablen als auch die außerhalb der Funktion deklarierten globalen Variablen Gültigkeit. Ein Problem tritt auf, wenn eine globale Variable und eine lokale Variable denselben Namen haben. Wenn also z.B. beide Variablen x heißen und wenn dann innerhalb der Funktion auf x zugegriffen wird, dann ist zunächst unklar, welches x gemeint ist. Daher gilt die Regel, dass innerhalb der Funktion die lokale Variable Vorrang hat. Die Konsequenz ist, dass innerhalb der Funktion die globale Variable gleichen Namens nicht ohne Weiteres erreichbar ist. Man sagt, die lokale Variable verdeckt die globale Variable.
Bemerkung: In Java lässt sich auf globale Variablen, die ja Attribute der Klasse sind, durch Voranstellen des Schlüsselworts this dennoch zugreifen, auch wenn sie durch lokale Variablen verdeckt sind (bzw. durch Voranstellen des Namens der Klasse bei Klassenattributen).
Beispiel: Beim Aufruf der im Folgenden definierten Version der Funktion verkette, etwa mit verkette("alpha", "beta");, wird das Ergebnis "alpha+beta" zurückgegeben.
Es werden zwei Variablen deklariert, eine globale Variable trennsymbol und eine lokale Variable mit demselben Namen. Die globale Variable trennsymbol erhält den Wert ";", die lokale Variable trennsymbol erhält den Wert "+". Innerhalb der Funktion hat die lokale Variable trennsymbol Vorrang. Immer, wenn innerhalb der Funktion auf die Variable trennsymbol zugegriffen wird, ist die lokale Variable trennsymbol gemeint, und diese hat den Wert "+".
In Programmiersprachen gibt es auch Funktionen, die zur Berechnung des Funktionswertes keinen Argumentwert benötigen.
Beispiel: Die folgende Funktion berechnet die eulersche Zahl e. Um die Berechnung durchzuführen, wird kein Argument benötigt. Es wird jedoch ein Wert vom Typ double zurückgegeben, die Zahl e = 2,718.
Die Berechnung wird nach der Formel
e = n = 0, ..., 1 / n!
durchgeführt. Da nicht unendlich viele Summanden berechnet werden können, wird nur solange gerechnet, wie die Summanden größer als 10-14 sind, dann wird die Berechnung abgebrochen, da eine ausreichende Genauigkeit erreicht ist.
Die Funktion wird beispielsweise wie folgt aufgerufen:
double E = e();
Der zurückgegebene Funktionswert wird der Variablen E zugewiesen.
Im Bereich der Programmiersprachen wird bei Funktionen statt des Begriffs "Argument" meist der Begriff "Parameter" verwendet. Funktionen können einen oder mehrere oder auch gar keinen Parameter haben. Beispielsweise hat die Funktion successor(n) einen Parameter, die Funktion max(a, b) hat zwei Parameter, und die Funktion e() hat keinen Parameter.
In der Funktionsdefinition werden die Parameter als formale Parameter bezeichnet, beim Funktionsaufruf werden die Parameter als aktuelle Parameter bezeichnet.
Beispiel: Die folgende Funktion exp berechnet an für eine double-Zahl a und eine nichtnegative int-Zahl n.
In dieser Funktionsdefinition sind a und n die formalen Parameter.
Formale Parameter spielen im Prinzip dieselbe Rolle wie lokale Variablen. Ebenso wie lokale Variablen haben sie nur innerhalb der Funktionsdefinition Gültigkeit, und bei Namenskonflikten mit globalen Variablen haben sie Vorrang.
Der Unterschied zu gewöhnlichen lokalen Variablen besteht darin, dass die formalen Parameter beim Aufruf der Funktion mit den Werten der aktuellen Parameter initialisiert werden. Dabei kommt es auf die Reihenfolge der Parameter an: Der erste formale Parameter erhält den Wert des ersten aktuellen Parameters, der zweite formale Parameter erhält den Wert des zweiten aktuellen Parameters usw. Dieser Vorgang wird als Parameterübergabe bezeichnet.
Beispiel: Beim Aufruf der Funktion exp, etwa durch
erhält der formale Parameter a den Wert 2 und der formale Parmeter n den Wert 10. Der Funktionsaufruf ergibt also hier den Wert 210 = 1024.
Die aktuellen Parameter müssen also immer Werte sein bzw. Ausdrücke, die Werte ergeben. Die formalen Parameter müssen dagegen immer Variablen sein.
Die Situation ist genau wie bei einer Wertzuweisung, bei der auf der linken Seite des Wertzuweisungszeichens immer eine Variable stehen muss und auf der rechten Seite immer ein Ausdruck, der einen Wert ergibt. Tatsächlich handelt es sich bei der Parameterübergabe um eine Wertzuweisung – beim Aufruf der Funktion erhalten die formalen Parameter die Werte der entsprechenden aktuellen Parameter.
Eigentlich erwartet man von einer Funktion, dass sie beim Aufruf den Funktionswert berechnet und sonst nichts tut. Tatsächlich jedoch können in der Funktionsdefiniton noch weitere Anweisungen enthalten sein, die mit der eigentlichen Berechnung des Funktionswerts nichts zu tun haben.
Beispiel: In der Funktion zur Berechnung von e gibt eine Ausgabeanweisung in jeder Iteration die erreichte Annäherung an den schließlich berechneten Funktionswert aus.
Normalerweise sollten Funktionen frei von Seiteneffekten sein. Der Grund ist, dass man nicht erwartet, dass außer der Berechnung des Funktionswertes noch andere Dinge geschehen.
Es gibt jedoch eine bestimmte Art von Funktionen, für die dies nicht gilt. Dies sind Funktionen ohne Rückgabewert.
Funktionen, die keinen Funktionswert berechnen, sind eigentlich sinnlos. Nur wenn sie Seiteneffekte haben, können sie überhaupt etwas bewirken. Tatsächlich spielen Funktionen, die nur Seiteneffekte haben und keinen Funktionswert zurückgeben, eine bedeutende Rolle. Als Typ des nicht vorhandenen Rückgabewertes wird bei einer solchen Funktion das Wort void eingesetzt (engl.: void – leer, nichtig).
Beispiel: Die folgende Funktion weist der globalen Variablen trennsymbol einen neuen Wert zu.
Die Funktion gibt keinen Funktionswert zurück. Als Seiteneffekt verändert sie jedoch den Wert der globalen Variablen trennsymbol. Nach Aufruf etwa von
neuesTrennsymbol("/");
hat die globale Variable trennsymbol den neuen Wert "/".
Funktionen ohne Rückgabewert werden wie Anweisungen aufgerufen (etwa: neuesTrennsymbol("/");); dagegen werden Funktionen, die einen Rückgabewert erzeugen, in der Regel innerhalb von Ausdrücken aufgerufen (etwa: x=2*max(a, b)+1;).
Aufgabe 1: Schreiben Sie eine Funktion square(x), die das Quadrat einer Zahl x berechnet.
Aufgabe 2: Setzen Sie folgende mathematische Funktionsdefinition in eine Java-Funktion um.
abs(x) = |
|
Weiter mit: [Funktionen (Fortsetzung)] [Literatur] oder [up]