Einführung in Mathematica Carsten Rezny Institut für Angewandte Mathematik Universität Bonn Pure Funktionen Das vorige Beispiel verwendet eine neue Schreibweise. Das erste Argument von Map oder Apply ist eine sogenannte pure Funktion (pure function) d.h. die Funktion selbst wird als Argument übergeben. Einstellige Funktionen kann man einfach durch ihren Namen angeben. Für mehrstellige Funktionen oder komplexere Ausdrücke gibt es den Funktionsoperator &. Der Operator & markiert einen vorangehenden Ausdruck als anonyme Funktion. Als Platzhalter für Funktionsargumente dienen # # # usw. Die anonyme Funktion kann natürlich gleich mit Argument verwendet werden. In[9]:= Out[9]= ð + &@5D 6 Auf diese Weise kann man auch benannte Funktionen definieren: In[93]:= p := ð ^ + ð ^ & In[9]:= p@3 D Out[9]= 5 Sinnvoll sind sie aber hauptsächlich im Zusammenhang mit Map Apply und Co. In[95]:= MapB & Range@0DF ð + Out[95]= : > 5 0 7 6 37 50 65 8 0 Mehr Listenverarbeitung Manchmal ist bei Map neben den Listenelementen auch deren Position in der Liste interessant. Dies bietet MapIndexed: In[96]:= Out[96]= MapIndexed@pp@ð ðd & 8 3 5 <D 8pp@ 8<D pp@3 8<D pp@5 83<D pp@ 8<D< Der Index des jeweiligen Elements wird dabei im zweiten Argument als einelementige Liste an die Funktion überreicht. Der Index selbst ist dann also #[[]]. Mit Nest wird eine Funktion iteriert. Zu der zu iterierenden Funktion wird ein Startwert und die Anzahl der Iterationen mitgegeben. In[97]:= Out[97]= NestAð & 5E 9 967 96 Wenn die Zwischenergebnisse interessant sind verwendet man NestList: In[98]:= Out[98]= NestListAð & 5E 8 6 56 65 536 9 967 96< Wenn statt der Anzahl der Iterationen ein Abbruchkriterium verwendet werden soll geht das mit NestWhile. In[99]:= NestWhileAð & ð > 0- &E Out[99]= 6 38
In[00]:= Out[00]= N@%D 0.00006035 Mit Select können Elemente einer Liste mit beliebigen Kriterien ausgewählt werden. In[0]:= Out[0]= In[0]:= Out[0]= liste = Sort RandomInteger@00 30D 8 9 0 6 8 5 33 35 5 6 7 8 5 56 56 59 67 68 69 70 7 78 80 8 87 88 00< Select@liste PrimeQD 87 59 67< Prozedurale Programmierung Neben der funktionalen Programmierung gibt es auch die Möglichkeit zur prozeduralen Programmierung wie sie aus Sprachen wie C Java oder Fortran bekannt ist. Sequenzen von Anweisungen Mathematica unterscheidet nicht zwischen Anweisungen und anderen Ausdrücken. Jede Anweisung kann als Teil eines Ausdrucks verwendet werden und jeder Ausdruck kann anstelle einer Anweisung stehen. In[03]:= Out[03]= + Ha = 7L 9 In[0]:= a Out[0]= 7 Die Zuweisung a=7 hat als Teil eines Ausdrucks den Wert 7. Wenn einem Ausdruck ein Semikolon folgt hat er statt seines normalen Wertes den Wert Null der nicht ausgegeben wird. Außerdem kann ein Semikolon als Trennzeichen zwischen Ausdrücken stehen. Eine solche mit Semikolons getrennte Folge von Ausdrücken hat den Wert des letzten Ausdrucks (sofern diesem kein Semikolon folgt). In[05]:= Out[05]= ; 3; Das ist insbesondere in den folgenden Kontrollstrukturen nützlich. Bei Bedarf kann eine Sequenz von Ausdrücken auch einfach in runde Klammern gesetzt werden: In[06]:= Out[06]= Hx = ; y = L + 3 5 Kommentare Kommentare ermöglichen es beliebigen Text an beliebigen Stellen in Ausdrücken unterzubringen z.b. für Dokumentationszwecke. Solche Kommentare werden in Mathematica mit (* und *) umschlossen. Sie werden wie Zwischenraum (Leerzeichen) behandelt. In[07]:= gg@x_ H* ein Argument *LD := Table@i 8i x H* i läuft von bis x *L<D Blöcke und Module Prozedurale Programmierung benötigt häufig lokale Variablen. Dafür stehen zwei Möglichkeiten zur Verfügung. Module erzeugt lexikalische lokale Variablen d.h. die Variablen existieren nur im Kontext des jeweiligen Module. (Das entspricht z.b. dem Verhalten von my in Perl.) Von dort aus aufgerufene Funktionen sehen diese lexikalischen Variablen nicht. In[08]:= a = 0; b = ;
In[09]:= Out[09]= 3 Module@8a = 5< a + bd 6 Intern werden die als lokal deklarierten Bezeichner durch temporäre Bezeichner ersetzt was bei undefinierten lokalen Variablen sichtbar wird. In[0]:= Out[0]= In[]:= Out[]= Module@8a< a + bd + a$76 f@x_d := a x Module@8a = 5< f@8dd 0 30 Im Unterschied dazu erzeugt Block dynamische lokale Variablen die auch für aufgerufene Funktionen sichtbar bleiben (analog zu local in Perl). In[3]:= Out[3]= In[]:= Out[]= In[5]:= Out[5]= Block@8a = 5< a + bd 6 Block@8a< a + bd Block@8a = 5< f@8dd 0 30 Kontrollstrukturen Ein weiteres wesentliches Element von prozeduraler Programmierung sind Kontrollstrukturen für Schleifen und bedingte Ausdrücke. Die einfachste Form einer Schleife ist Do: In[6]:= Do@k ^ 8k 0<D Do produziert von sich aus kein Resultat funktioniert ansonsten aber genau wie Table. In[7]:= Do@Print@k " " k ^ D 8k 0<D 3 9 6 5 5 6 36 7 9 8 6 9 8 0 00 Die For-Schleife ist analog zu dem in C oder Java vorhandenen for aufgebaut: In[8]:= For@k = k <= 0 k ++ Print@k " " k ^ DD
3 9 6 5 5 6 36 7 9 8 6 9 8 0 00 While wiederholt einen Ausdruck solange die gegebene Bedingung wahr ist. In[9]:= x = 0-5 ; While@x < x *= D; x 096 Out[9]= 35 If verhält sich in etwa wie der aus C oder Java bekannte ternäre Operator?: In[0]:= test@x_d := If@PrimeQ@xD "Primzahl" "keine Primzahl"D In[]:= test@8d Out[]= In[]:= Out[]= keine Primzahl test@7d Primzahl If kennt noch ein viertes Argument das ausgewertet wird wenn die Bedingung weder wahr noch falsch ist: In[3]:= kleiner@x_ y_d := If@x < y "kleiner" "nicht kleiner" "undefiniert"d In[]:= kleiner@ 3D Out[]= In[5]:= Out[5]= kleiner kleiner@5 zd kleiner Für eine Entscheidung unter mehreren Fällen gibt es Switch und Which. Ersteres ähnelt wieder stark seinem C-Pendant: In[6]:= wort@x_d := Switch@x "eins" "zwei" 3 "drei" _ "weiß nicht"d In[7]:= wort@3d Out[7]= In[8]:= Out[8]= drei wort@d weiß nicht Which verarbeitet eine Reihe von unabhängigen Test-Wert-Paaren. In[9]:= Out[9]= In[30]:= x = 0; y = ; z = ; Which@x "x" y "y" z "z"d y Clear@x y zd
Graphische Darstellung Mathematica verfügt über umfangreiche Möglichkeiten zur graphischen Darstellung. Ein einfacher Funktionsplot: In[3]:= PlotAx Sin@xD 8x 0 0<E 300 00 00 Out[3]= 5 0 5 0-00 -00-300 Mehrere Kurven in einem Plot: In[3]:= Plot@8x ^ x ^ 3< 8x - 5 5<D 0 0 Out[3]= - - -0 Es gibt sehr viele Plot-Optionen hier nur ein paar Beispiele: In[33]:= Plot@8x ^ x ^ 3< 8x - 5 5< PlotRange 8-5 5<D Out[33]= - - - - 5
6 In[3]:= PlotAExpA- x E 8x - 3 3< Filling AxisE.0 0.8 0.6 Out[3]= 0. 0. -3 - - 3 Auch Listen können geplottet werden: In[35]:= ListPlot@Prime@Range@50DD Filling AxisD 00 50 Out[35]= 00 50 0 0 30 0 50 Für Funktionen in zwei Variablen gibt es Plot3D: In[36]:= Plot3DASinAx + y E 8x - < 8y - <E.0 0.5 Out[36]= 0.0-0.5 -.0 0 - - - 0 -