Lazarus/Prozeduren, Funktionen und Bibliotheken: Unterschied zwischen den Versionen

Aus ZUM-Unterrichten
main>Peterdauscher
(formatiert)
Markierung: 2017-Quelltext-Bearbeitung
 
(16 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
{{Lazarus-Buch}}
== Prozeduren ==
== Prozeduren ==
=== Einfache Prozeduren ===
=== Einfache Prozeduren ===


Wenn man Programme schreibt und immer mehr erweitert, so besteht die Gefahr, dass sie nicht nur immer größer sondern auch immer unübersichtlicher werden. Deshalb ist es sinnvoll, bestimmte, immer wiederkehrende Folgen von Befehlen mit einer bestimmten Bedeutung in einer Art selbst gebautem Befehl zusammenzufassen. Solche Befehle heißen auch '''Prozedur''' (engl.: '''procedure'''). Manche Leser werden den Sketch "Dinner for one" [https://de.wikipedia.org/wiki/Dinner_for_One] kennen, bei dem Butler James immer wieder fragt: "Same procedure as last year, Miss Sophie" und Miss Sophie jedes Mal antwortet "Same procedure as ''every'' year, James" . James und Miss Sophie meinen genau dasselbe wie wir: einen fest geregelten Ablauf von Dingen.
Wenn man Programme schreibt und immer mehr erweitert, so besteht die Gefahr, dass sie nicht nur immer größer sondern auch immer unübersichtlicher werden. Deshalb ist es sinnvoll, bestimmte, immer wiederkehrende Folgen von Befehlen mit einer bestimmten Bedeutung in einer Art selbst gebautem Befehl zusammenzufassen. Solche Befehle heißen auch '''Prozedur''' (engl.: '''procedure'''). Manche Leser werden den Sketch "Dinner for one" [https://de.wikipedia.org/wiki/Dinner_for_One] kennen, bei dem Butler James immer wieder fragt: "Same procedure as last year, Miss Sophie" und Miss Sophie jedes Mal antwortet "Same procedure as ''every'' year, James" . James und Miss Sophie meinen genau dasselbe wie wir: einen fest geregelten Ablauf von Dingen.
==== Beispiel einer einfachen Prozedur ====


Ein sehr sehr einfaches Beispiel für eine Prozedur könnte ein Hinweis sein, der angezeigt werden soll, begleitet von einem hörbaren Signal. Das Programm benötigt lediglich einen Button mit dem Namen <tt>Button1</tt>.
Ein sehr sehr einfaches Beispiel für eine Prozedur könnte ein Hinweis sein, der angezeigt werden soll, begleitet von einem hörbaren Signal. Das Programm benötigt lediglich einen Button mit dem Namen <tt>Button1</tt>.


{{kasten_blau|<source  line highlight="30-34,38" lang="pascal">
<source  line highlight="30-34,38" lang="pascal">
unit hinweis_geben;
unit hinweis_geben;


Zeile 54: Zeile 49:
end.
end.


</source>}}
</source>




Man sieht, dass nach der Definition des eigenen Befehls (der Prozedur) "Hinweis" vollkommen genügt, diesen Befehl aufzurufen.
Man sieht, dass es nach der Definition des eigenen Befehls (der Prozedur) "Hinweis" vollkommen genügt, diesen Befehl aufzurufen.


=== Prozeduren mit Wertparametern ===
=== Prozeduren mit Wertparametern ===
Zeile 64: Zeile 59:




{{kasten_blau|<source line start="30" highlight="1,11" lang="pascal">
<source line start="30" highlight="1,9" lang="pascal">
procedure Hinweis(nachricht: string);
procedure Hinweis(nachricht: string);
begin
begin
Zeile 72: Zeile 67:


procedure TForm1.Button1Click(Sender: TObject);
procedure TForm1.Button1Click(Sender: TObject);
var alter : integer;
begin
begin
Hinweis('Eine frei gewählte Nachricht');
Hinweis('Eine frei gewählte Nachricht');
end;
end;
</source>}}
</source>


Unterscheiden tun sich die gelb markierten Zeilen: Bei der Definition der Prozedur "Hinweis" in Zeile 30 ist hinter dem Namen der Prozedur noch in Klammern eine Variable angegeben, die in diesem Fall den Namen <tt>nachricht </tt> trägt und vom Typ <tt>string</tt> ist.
Unterscheiden tun sich die gelb markierten Zeilen: Bei der Definition der Prozedur "Hinweis" in Zeile 30 ist hinter dem Namen der Prozedur noch in Klammern eine Variable angegeben, die in diesem Fall den Namen <tt>nachricht </tt> trägt und vom Typ <tt>string</tt> ist.
Zeile 85: Zeile 78:
'''Wichtige Anmerkung:'''
'''Wichtige Anmerkung:'''
Die Variable <tt>nachricht</tt> ist eine neue, eigenständige Variable. Beim Aufruf der Prozedur Hinweis wird ihr ein entsprechender Zeichenkettenwert zugewiesen. Wird dieser im Lauf der Prozedur verändert, so wirkt sich das auf das aufrufende Programm nicht aus.
Die Variable <tt>nachricht</tt> ist eine neue, eigenständige Variable. Beim Aufruf der Prozedur Hinweis wird ihr ein entsprechender Zeichenkettenwert zugewiesen. Wird dieser im Lauf der Prozedur verändert, so wirkt sich das auf das aufrufende Programm nicht aus.


=== Prozeduren mit Referenzparametern ===
=== Prozeduren mit Referenzparametern ===


Nun kann es sein, dass es der Zweck einer Prozedur sein soll, den Wert einer Variable im aufrufenden Programm aber tatsächlich zu ändern. Als Beispiel betrachten wir den (sehr sehr einfachen) Fall, bei dem der Wert einer Integer-Variable verdoppelt werden soll. Das Programm benötigt den Button <tt>Button1</tt> und das Edit-Feld <tt>Edit1</tt>. Der Vorspann mit Variablen usw. ist hier einfach einmal weggelassen.
Nun kann es sein, dass es der Zweck einer Prozedur sein soll, den Wert einer Variable im aufrufenden Programm aber tatsächlich zu ändern. Als Beispiel betrachten wir den (sehr sehr einfachen) Fall, bei dem der Wert einer Integer-Variable verdoppelt werden soll. Das Programm benötigt den Button <tt>Button1</tt> und das Edit-Feld <tt>Edit1</tt>. Der Vorspann mit Variablen usw. ist hier einfach einmal weggelassen; aber es ist klar, dass dort <tt> zahlenwert : integer;</tt> deklariert werden muss.
 


{{kasten_blau|<source line start="30" highlight="1,10" lang="pascal">
<source line start="30" highlight="1,10" lang="pascal">
procedure verdopple (zahl : integer);
procedure verdopple (zahl : integer);
begin
begin
Zeile 99: Zeile 90:


procedure TForm1.Button1Click(Sender: TObject);
procedure TForm1.Button1Click(Sender: TObject);
var zahlenwert : integer;
begin
begin
zahlenwert:=StrToInt(Edit1.Text);
zahlenwert:=StrToInt(Edit1.Text);
Zeile 105: Zeile 95:
Edit1.Text:=IntToStr(zahlenwert);
Edit1.Text:=IntToStr(zahlenwert);
end;
end;
</source>}}
</source>


Beim Ausprobieren merkt man: Das Beispiel funktioniert offensichtlich nicht. Der Inhalt des Edit-Feldes bleibt beim Drücken des Knopfes genau gleich.  
Beim Ausprobieren merkt man: Das Beispiel funktioniert offensichtlich nicht. Der Inhalt des Edit-Feldes bleibt beim Drücken des Knopfes genau gleich.  
Zeile 113: Zeile 103:
<tt>zahl:=zahl*2</tt> wird jetzt in Wirklichkeit die Variable <tt>zahlenwert</tt> verdoppelt.
<tt>zahl:=zahl*2</tt> wird jetzt in Wirklichkeit die Variable <tt>zahlenwert</tt> verdoppelt.


{{kasten_blau|<source line start="30" highlight="1,10" lang="pascal">
<source line start="30" highlight="1,9" lang="pascal">
procedure verdopple (var zahl : integer);
procedure verdopple (var zahl : integer);
begin
begin
Zeile 120: Zeile 110:


procedure TForm1.Button1Click(Sender: TObject);
procedure TForm1.Button1Click(Sender: TObject);
var zahlenwert : integer;
begin
begin
zahlenwert:=StrToInt(Edit1.Text);
zahlenwert:=StrToInt(Edit1.Text);
Zeile 126: Zeile 115:
Edit1.Text:=IntToStr(zahlenwert);
Edit1.Text:=IntToStr(zahlenwert);
end;
end;
</source>}}
</source>


Durch diese kleine Änderung funktioniert jetzt das Programm tadellos.
Durch diese kleine Änderung funktioniert jetzt das Programm tadellos.


== Funktionen ==
== Funktionen ==
Zeile 135: Zeile 123:
Im Grunde würden Prozeduren mit Wert- und Referenzparametern vollkommen ausreichern, um immer wiederkehrende Abläufe in selbstdefinierte Befehle zu verpacken (Informatiker sprechen gerne auch von "'''verkapseln'''").
Im Grunde würden Prozeduren mit Wert- und Referenzparametern vollkommen ausreichern, um immer wiederkehrende Abläufe in selbstdefinierte Befehle zu verpacken (Informatiker sprechen gerne auch von "'''verkapseln'''").


So könnte man zum Beispiel eine Prozedur zum Berechnen des Quadrats von integer-Zahlen schreiben. Das Beispielprogramm benötigt die Komponenten <tt>Button1, Edit1, Edit2</tt>:
So könnte man zum Beispiel eine Prozedur zum Berechnen des Quadrats von integer-Zahlen schreiben. Das Beispielprogramm benötigt die Komponenten <tt>Button1, Edit1, Edit2</tt> und natürlich auch die Integer-Variablen <tt>zahlenwert</tt> und <tt>zahlenwertquadriert</tt>.




{{kasten_blau|<source line start="30" highlight="1,11" lang="pascal">
<source line start="30" highlight="1,9" lang="pascal">
procedure quadrat(zahl : integer; var ergebnis: integer);
procedure quadrat(zahl : integer; var ergebnis: integer);
begin
begin
Zeile 145: Zeile 133:


procedure TForm1.Button1Click(Sender: TObject);
procedure TForm1.Button1Click(Sender: TObject);
var zahlenwert : integer;
    zahlenwertquadriert : integer;
begin
begin
zahlenwert:=StrToInt(Edit1.Text);
zahlenwert:=StrToInt(Edit1.Text);
Zeile 152: Zeile 138:
Edit2.Text:=IntToStr(zahlenwertquadriert);
Edit2.Text:=IntToStr(zahlenwertquadriert);
end;                             
end;                             
</source>}}
</source>


Aber gerade im mathematischen Bereich ist das eher unüblich: außerdem muss man immer überlegen, welcher der beiden Parameter nun die eigentliche Zahl und welche das spätere Quadrat werden soll. Eleganter ist daher die folgende Schreibweise:
Aber gerade im mathematischen Bereich ist das eher unüblich: außerdem muss man immer überlegen, welcher der beiden Parameter nun die eigentliche Zahl und welche das spätere Quadrat werden soll. Eleganter ist daher die folgende Schreibweise:


{{kasten_blau|<source line start="30" highlight="1,11" lang="pascal">
<source line start="30" highlight="1,9" lang="pascal">
function quadrat(zahl : integer) : integer;
function quadrat(zahl : integer) : integer;
begin
begin
Zeile 163: Zeile 149:


procedure TForm1.Button1Click(Sender: TObject);
procedure TForm1.Button1Click(Sender: TObject);
var zahlenwert : integer;
    zahlenwertquadriert : integer;
begin
begin
zahlenwert:=StrToInt(Edit1.Text);
zahlenwert:=StrToInt(Edit1.Text);
Zeile 170: Zeile 154:
Edit2.Text:=IntToStr(zahlenwertquadriert);
Edit2.Text:=IntToStr(zahlenwertquadriert);
end;                             
end;                             
</source>}}
</source>


Beim Aufruf der Funktion erhält sie durch die Berechnung einen Funktionswert. Dies geschieht in Zeile 32.
In Zeile 38 wird dieser Funktionswert der Variablen "zahlenwertquadriert" zugewiesen. Eine solche Zuweisung über ein ":=" funktioniert nur bei Funktionen, nicht bei Prozeduren.
Anmerkung:
Alternativ kann man die Zeile 32 auch so schreiben:
<source line start="32" highlight="32" lang="pascal">
result:=zahl*zahl;
</source>
Der Variablenname "result" ist genau für diesen Zweck reserviert; man sollte ihn also nicht für andere Dinge verwenden.


== Bibliotheken ==
== Bibliotheken ==
Zeile 179: Zeile 174:
Eine solche Bibliothek haben wir im Kapitel [[../Computer-Mathematik/]] bereits kennen gelernt: die <tt>Unit Math</tt>, in der viele praktische mathematische Befehle definiert sind.
Eine solche Bibliothek haben wir im Kapitel [[../Computer-Mathematik/]] bereits kennen gelernt: die <tt>Unit Math</tt>, in der viele praktische mathematische Befehle definiert sind.


Eine weitere Unit soll uns das Leben in den nächsten Kapiteln erleichtern: <tt>LazIOStuff</tt> Diese ist allerdings nicht Bestandteil der derzeitigen Lazarus-Entwicklungsumgebung, sondern kann kostenlos aus dem Internet heruntergeladen werden:
{{Aufgabe|1=
 
#Schreibe eine Prozedur, bei der Fläche und Umfang eines Rechtecks über Referenzparameter zurückgegeben werden. Länge und Breite sollen über Wertparameter in die Prozedur importiert werden. Teste die Prozedur in einem Programm.
[http://sourceforge.net/projects/laziostuff/files/laziostuff.pas/download laziostuff.pas].  
#Schreibe zwei Funktionen, die für ein Rechteck mit gegebener Länge und Breite die Fläche bzw. den Umfang ausrechnen und teste sie in einem Programm.
 
#Vergleiche die letzten beiden Aufgaben: Nenne Vor- und Nachteile der beiden Lösungen für das gleiche Problem.
 
#Informiere Dich im Internet (oder Mathematikbuch) über den Höhensatz und den Kathetensatz. Kannst Du eine Reihe von sinnvollen Prozeduren bzw. Funktionen schreiben?
Im Gegensatz zur Unit <tt>Math</tt> muss man die Datei <tt>laziostuff.pas</tt> in den Ordner kopieren, in dem sich auch das eigene Projekt befindet. Ansonsten funktionieren die Programme, die sie benutzen, einfach nicht. Der Compiler beschwert sich, dass die aufgerufenen Befehle nicht existieren.
#Die Betragsfunktion in der Mathematik ist folgendermaßen definiert: Wenn eine Variable x einen Wert>=0 hat, so ist ihr Betrag genauso groß wie ihr Wert x. Hat sie dagegen einen negativen Wert, so ist der Betrag gerade -x. Konstruiere eine sinnvolle Funktion <tt>betrag(x)</tt>.}}
 
== Aufgaben ==
#Ein Programm
 


{{Lazarus-Buch}}
{{Lazarus-Buch}}

Aktuelle Version vom 10. August 2019, 06:18 Uhr

Prozeduren

Einfache Prozeduren

Wenn man Programme schreibt und immer mehr erweitert, so besteht die Gefahr, dass sie nicht nur immer größer sondern auch immer unübersichtlicher werden. Deshalb ist es sinnvoll, bestimmte, immer wiederkehrende Folgen von Befehlen mit einer bestimmten Bedeutung in einer Art selbst gebautem Befehl zusammenzufassen. Solche Befehle heißen auch Prozedur (engl.: procedure). Manche Leser werden den Sketch "Dinner for one" [1] kennen, bei dem Butler James immer wieder fragt: "Same procedure as last year, Miss Sophie" und Miss Sophie jedes Mal antwortet "Same procedure as every year, James" . James und Miss Sophie meinen genau dasselbe wie wir: einen fest geregelten Ablauf von Dingen.

Ein sehr sehr einfaches Beispiel für eine Prozedur könnte ein Hinweis sein, der angezeigt werden soll, begleitet von einem hörbaren Signal. Das Programm benötigt lediglich einen Button mit dem Namen Button1.

unit hinweis_geben;

{$mode objfpc}{$H+}
interface
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls;

type
  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure Hinweis;
begin
  Beep;
  ShowMessage('Sie haben den Knopf gedrückt');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Hinweis;
end;

end.


Man sieht, dass es nach der Definition des eigenen Befehls (der Prozedur) "Hinweis" vollkommen genügt, diesen Befehl aufzurufen.

Prozeduren mit Wertparametern

Die oben gezeigte Prozedur tut immer genau das gleiche: Sie gibt das akustische Signal und den Hinweis "Sie haben den Knopf gedrückt". Häufig jedoch kommt es vor, das eine Prozedur zwar immer ähnliche, aber eben doch leicht verschiedene Dinge tun soll. So wäre es z.B. praktisch, wenn man den Hinweistext selbst immer wieder neu bestimmen könnte. Das funktioniert auch, wenn man der Prozedur einen so genannten Paramter mit auf den Weg gibt. Wir betrachten wiederum ein Beispiel:


procedure Hinweis(nachricht: string);
begin
  Beep;
  ShowMessage(nachricht);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Hinweis('Eine frei gewählte Nachricht');
end;

Unterscheiden tun sich die gelb markierten Zeilen: Bei der Definition der Prozedur "Hinweis" in Zeile 30 ist hinter dem Namen der Prozedur noch in Klammern eine Variable angegeben, die in diesem Fall den Namen nachricht trägt und vom Typ string ist. Wird nun in Zeile 40 der neue Befehl Hinweis aufgerufen, und zwar mit der Zeichenkette 'Eine frei gewählte Nachricht' in Klammern, so wird die Variable nachricht mit diesem Wert belegt. Wird nun innerhalb der Prozedur wiederum der Befehl ShowMessage mit nachricht als Parameter aufgerufen, so erscheint tatsächlich die Meldung mit dem richtigen Text auf dem Bildschirm.

Wichtige Anmerkung: Die Variable nachricht ist eine neue, eigenständige Variable. Beim Aufruf der Prozedur Hinweis wird ihr ein entsprechender Zeichenkettenwert zugewiesen. Wird dieser im Lauf der Prozedur verändert, so wirkt sich das auf das aufrufende Programm nicht aus.

Prozeduren mit Referenzparametern

Nun kann es sein, dass es der Zweck einer Prozedur sein soll, den Wert einer Variable im aufrufenden Programm aber tatsächlich zu ändern. Als Beispiel betrachten wir den (sehr sehr einfachen) Fall, bei dem der Wert einer Integer-Variable verdoppelt werden soll. Das Programm benötigt den Button Button1 und das Edit-Feld Edit1. Der Vorspann mit Variablen usw. ist hier einfach einmal weggelassen; aber es ist klar, dass dort zahlenwert : integer; deklariert werden muss.

procedure verdopple (zahl : integer);
begin
zahl:=zahl*2;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
zahlenwert:=StrToInt(Edit1.Text);
verdopple(zahlenwert);
Edit1.Text:=IntToStr(zahlenwert);
end;

Beim Ausprobieren merkt man: Das Beispiel funktioniert offensichtlich nicht. Der Inhalt des Edit-Feldes bleibt beim Drücken des Knopfes genau gleich.

Wir müssen das Programm leicht abändern, damit es funktioniert. Wir fügen in Zeile 30 vor der Variable zahl das Schlüsselwort var ein. Das ist eigentlich ein wenig missverständlich, denn es soll bedeuten: zahl ist keine eigenständige Variable sondern nur noch eine Art Spitzname für die Variable im Funktionsaufruf (man sagt auch: Referenz auf die Variable), in diesem Fall zahlenwert. Mit zahl:=zahl*2 wird jetzt in Wirklichkeit die Variable zahlenwert verdoppelt.

procedure verdopple (var zahl : integer);
begin
zahl:=zahl*2;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
zahlenwert:=StrToInt(Edit1.Text);
verdopple(zahlenwert);
Edit1.Text:=IntToStr(zahlenwert);
end;

Durch diese kleine Änderung funktioniert jetzt das Programm tadellos.

Funktionen

Im Grunde würden Prozeduren mit Wert- und Referenzparametern vollkommen ausreichern, um immer wiederkehrende Abläufe in selbstdefinierte Befehle zu verpacken (Informatiker sprechen gerne auch von "verkapseln").

So könnte man zum Beispiel eine Prozedur zum Berechnen des Quadrats von integer-Zahlen schreiben. Das Beispielprogramm benötigt die Komponenten Button1, Edit1, Edit2 und natürlich auch die Integer-Variablen zahlenwert und zahlenwertquadriert.


procedure quadrat(zahl : integer; var ergebnis: integer);
begin
ergebnis:=zahl*zahl;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
zahlenwert:=StrToInt(Edit1.Text);
quadrat(zahlenwert,zahlenwertquadriert);
Edit2.Text:=IntToStr(zahlenwertquadriert);
end;

Aber gerade im mathematischen Bereich ist das eher unüblich: außerdem muss man immer überlegen, welcher der beiden Parameter nun die eigentliche Zahl und welche das spätere Quadrat werden soll. Eleganter ist daher die folgende Schreibweise:

function quadrat(zahl : integer) : integer;
begin
quadrat:=zahl*zahl;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
zahlenwert:=StrToInt(Edit1.Text);
zahlenwertquadriert:=quadrat(zahlenwert);
Edit2.Text:=IntToStr(zahlenwertquadriert);
end;

Beim Aufruf der Funktion erhält sie durch die Berechnung einen Funktionswert. Dies geschieht in Zeile 32.

In Zeile 38 wird dieser Funktionswert der Variablen "zahlenwertquadriert" zugewiesen. Eine solche Zuweisung über ein ":=" funktioniert nur bei Funktionen, nicht bei Prozeduren.

Anmerkung: Alternativ kann man die Zeile 32 auch so schreiben:

result:=zahl*zahl;

Der Variablenname "result" ist genau für diesen Zweck reserviert; man sollte ihn also nicht für andere Dinge verwenden.

Bibliotheken

Das Ausgliedern von immer gleichen Routinen in Prozeduren und Funktionen als eigene Befehle macht auch größere Programme übersichtlicher. Allerdings hilft bei sehr großen Programmen (mit mehreren Tausenden Zeilen) das auch nicht mehr so sonderlich viel. Deshalb kann man in diesem Fall Teile der Prozeduren und Funktionen in eigene Dateien ausladen, so genannte Bibliotheken, die in der Sprache Pascal auch als Units bezeichnet werden.

Ein weiterer Vorteil von Bibliotheken ist, dass mehrere andere Programme die darin definierten Befehle benutzten Befehle verwenden können, ohne dass man die entsprechenden Funktionen und Prozeduren in das eigene Programm hineinkopieren muss. Vielmehr genügt es, in der Zeile uses ... den Namen der benutzten Unit anzugeben. Eine solche Bibliothek haben wir im Kapitel Computer-Mathematik bereits kennen gelernt: die Unit Math, in der viele praktische mathematische Befehle definiert sind.


Aufgabe
  1. Schreibe eine Prozedur, bei der Fläche und Umfang eines Rechtecks über Referenzparameter zurückgegeben werden. Länge und Breite sollen über Wertparameter in die Prozedur importiert werden. Teste die Prozedur in einem Programm.
  2. Schreibe zwei Funktionen, die für ein Rechteck mit gegebener Länge und Breite die Fläche bzw. den Umfang ausrechnen und teste sie in einem Programm.
  3. Vergleiche die letzten beiden Aufgaben: Nenne Vor- und Nachteile der beiden Lösungen für das gleiche Problem.
  4. Informiere Dich im Internet (oder Mathematikbuch) über den Höhensatz und den Kathetensatz. Kannst Du eine Reihe von sinnvollen Prozeduren bzw. Funktionen schreiben?
  5. Die Betragsfunktion in der Mathematik ist folgendermaßen definiert: Wenn eine Variable x einen Wert>=0 hat, so ist ihr Betrag genauso groß wie ihr Wert x. Hat sie dagegen einen negativen Wert, so ist der Betrag gerade -x. Konstruiere eine sinnvolle Funktion betrag(x).