.. |Main_Command| image:: S:/uniplot-obj/buttons/Main_Command.png :align: top .. highlightlang:: us .. _uniscript-in-beispielen: UniScript in Beispielen ======================= An einigen kleinen Beispielen soll Ihnen die Benutzung von UniScript gezeigt werden. Es ist empfehlenswert, wenn Sie dazu UniPlot starten und die Beispiele eingeben. Starten Sie also UniPlot und klicken Sie mit der Maus auf den Schalter mit dem Symbol eines Taschenrechners |Main_Command|. Es erscheint das Kommandofenster von UniScript mit einer Copyright-Meldung. Vergrößern Sie das Kommandofenster auf Vollbilddarstellung. .. image:: S:/uniplot-obj/images/UniScript-Vollbild.* Der Stern ``*`` ist der sogenannte Prompt. Er zeigt Ihnen, daß UniScript für Ihre Eingaben bereit ist. .. _uniscript-als-taschenrechner: UniScript als Taschenrechner ---------------------------- Geben Sie ein :: * 7 + 12 19.0000 * 5-7 -2.0000 * 3*5 15.0000 * 1/2 0.5000 * (2 + 5)*5 35.0000 * y = sin(0.5) * y 0.4794 * Sie können UniScript wie einen leistungsfähigen Taschenrechner verwenden. UniScript kann jedoch mehr, z. B. mit Matrizen rechnen. .. index:: Matrix .. index:: LAPACK .. index:: Gleichungssysteme .. _matrizenrechnung: Matrizenrechnung ---------------- Die Gleichung .. math:: \begin{pmatrix} 4 & 7 \\ 2 & 5 \end{pmatrix} \cdot \begin{pmatrix} x_{1} \\ x_{2} \end{pmatrix} = \begin{pmatrix} 1 \\ 4 \end{pmatrix} kann mit UniScript folgendermaßen gelöst werden: :: * a = [4,7;2,5] * a 4.0000 7.0000 2.0000 5.0000 * b = [1;4] * b 1.0000 4.0000 * x = a\b * x -3.8333 2.3333 * a * x 1.0000 4.0000 Matrizen werden in UniScript eingegeben, indem man die Spalten der Matrix durch ein Komma trennt und die Zeilen durch ein Semikolon. Die Zeile ``x = a\b`` löst das lineare Gleichungssystem. Das ``\``-Zeichen ist der sogenannte Links-Divisions-Operator. Dieser Operator ist speziell für das Lösen von Gleichungssystemen mit reellen und komplexen Elementen gedacht. UniScript verwendet dazu die sehr leistungsfähigen Berechnungsverfahren der LAPACK-Library, so daß auch große Gleichungssysteme schnell und stabil gelöst werden können. UniScript kann noch einige andere Matrizenoperationen ausführen, z. B. die Determinate berechnen, die Inverse oder die Eigenwerte. :: * det(a) 6.0000 * a^-1 0.8333 -1.1667 -0.3333 0.6667 * eig(a) 8.2749 + 0.0000i 0.7251 + 0.0000i .. index:: Komplexe Zahlen Die Eigenwerte wurden als komplexe Zahlen berechnet. Komplexe Zahlen werden eingegeben, indem man ein ``i`` hinter die Zahl schreibt. :: * (3 + 5i) * (2 + 7i) -29.0000 + 31.0000i Fast alle mathematischen UniScript-Funktionen können auch mit komplexen Zahlen rechnen, versuchen Sie z. B. ``sqrt(-1)``. .. index:: Kommandofenster .. _editieren-im-kommandofenster: Editieren im Kommandofenster ---------------------------- Sie können Ihre Kommandos mit den Pfeiltasten editieren. * Die :kbd:`Einfg`-Taste (Insert) schaltet zwischen Einfüge- und Überschreibmodus hin und her. * Die :kbd:`BACKSPACE`-Taste löscht das Zeichen vor dem Cursor, * die :kbd:`Entf`-Taste das Zeichen unter dem Cursor. * Mit den :kbd:`Pfeiltasten` nach oben und nach unten können Sie bereits abgeschickte Anweisungen zurückholen (sogenannte Command-History). * Mit der :kbd:`F7`-Taste erhalten Sie ein Listenfeld mit den 100 zuletzt eingegebenen Anweisungen. * Mit der :kbd:`F8`-Taste können Sie die Zeilen zurückholen, die mit den Buchstaben vor dem Cursor anfangen. * Mit der :kbd:`Esc`-Taste kann die Eingabezeile gelöscht werden. Außerdem kann mit der :kbd:`Esc`-Taste eine laufende Funktion abgebrochen werden. Siehe auch :ref:`ansichtkommando-fenster`. Das Kommandofenster wird hauptsächlich dazu verwendet, um Befehle auszuprobieren und sich die Werte von Variablen anzuschauen. In allen anderen Fällen wird ein Editor verwendet. .. index:: EdCreate .. index:: print .. index:: F1 .. _verwenden-eines-editors: Verwenden eines Editors ----------------------- Um einen Editor zu erzeugen, geben Sie im Kommandofenster den Befehl :ref:`EdCreate` ein und ordnen Sie die Fenster nebeneinander an. Geben Sie im Editor die folgenden Zeilen ein :: a = [4, 7; 2, 5] b = [1; 4] print "Die Determinante von", a print "ist", det(a) print "Die Lösung der Gleichung" print "a*x = b, mit a = ", a print "und b = ", b, "ist", a\b Speichern Sie Ihre Eingabe unter einem Namen, der mit :file:`.ic` endet. Die Endung ``".ic"`` steht für IsoCalc. UniScript hieß bis UniPlot 2.1 IsoCalc. Wählen Sie im Menü **UniScript** den Befehl **Laden/Ausführen**. UniScript führt Ihre im Editor eingegebenen Anweisungen aus. Die Ausgabe der :keyword:`print`-Anweisungen wird in das UniScript-Kommandofenster geschrieben. Gehen Sie mit dem Cursor auf einen Funktionsnamen und drücken Sie die F1-Taste. Wenn Sie den Cursor auf den :ref:`det`-Funktionsaufruf positionieren, bekommen Sie die folgende Hilfe-Seite. .. image:: S:/uniplot-obj/images/UniScript-dethelp.* Löschen Sie nun Ihre Editoreingaben (mit dem Befehl **alles markieren** im Menü **Bearbeiten** und anschließendem Drücken der DEL-Taste). .. _temperaturtabelle---1.-version: Temperaturtabelle - 1. Version ------------------------------ Es soll nun ein Programm geschrieben werden, das eine Temperaturtabelle ausgibt. In der ersten Spalte sollen die Celsius-Grade stehen und in der zweiten Spalte die Temperatur in Fahrenheit. Für die Umrechnung gilt die Formel ``C = 5 / 9 * (F - 32)``. :: 0 -17.8 20 -6.7 40 4.4 ... ... 260 126.7 280 137.8 300 148.9 Das Beispiel ist einem Buch über die Programmiersprache C entnommen [Kernighan, Brian W., und Ritchie, Dennis M.: *Programmieren in C*, Hanser, München, 1983]. Es zeigt Ihnen nicht nur die Ähnlichkeit von UniScript und C, sondern führt auch in wichtige Aspekte der Programmierung ein, die für UniScript ebenso gelten wie für C. Das Programm, das die Tabelle ausgibt, sieht so aus: :: /* Umwandlung von Fahrenheit in Celsius fuer f = 0, 20, ..., 300 */ def main() { lower = 0; /* untere Grenze der Temp.-Tabelle */ upper = 300; /* obere Grenze */ step = 20; /* Schrittweite */ fahr = lower; while (fahr <= upper) { celsius = (5.0 / 9.0) * (fahr - 32.0); printf("%4.0f %6.1f\n", fahr, celsius); fahr = fahr + step; } } Die ersten beiden Zeilen kommentieren das Programm :: /* Umwandlung von Fahrenheit in Celsius fuer f = 0, 20, ..., 300 */ Alle Zeilen, die zwischen ``/*`` und ``*/`` stehen, werden von UniScript ignoriert. Mit :: def main() { ... } wird ein Programm (eine Funktion) definiert. In C gibt es das Schlüsselwort :keyword:`def` nicht; es entfällt dort. In UniScript muss jedoch vor den Namen von Funktionen das Schlüsselwort :keyword:`def` stehen. ``main`` ist der Name der Funktion. In C steht der Name ``main`` für das Hauptprogramm. In UniScript ist ``main`` ein Name wie jeder andere. Hinter dem Funktionsnamen ``main`` stehen Klammern, die meist eine Liste von Parametern enthalten. In unserem Beispiel ist die Liste leer; die Klammern müssen aber dennoch hinter dem Funktionsnamen stehen, damit UniScript (und der Programmierer) besser erkennt, daß es sich bei ``main`` um einen Funktionsnamen handelt. Die geschweiften Klammern ``{`` und ``}`` umschließen die Anweisungen der Funktion ``main``. Sie haben die Bedeutung von ``begin`` und ``end`` in anderen Programmiersprachen. In C folgen hinter der ersten geschweiften Klammer die Deklarationen der Variablen. In UniScript sind Deklarationen von Variablen nicht erforderlich. Die erste Anweisung ist :: lower = 0; Sie weist der Variablen ``lower`` den Wert 0 zu und zwar als doppelt genaue Gleitkommakonstante. Im C-Programm wurde ``lower`` als ganze Zahl deklariert. UniScript kennt diesen Datentyp nicht. UniScript kennt lediglich drei Datentypen: * Doppelt genaue Gleitkommazahlen. * Komplexe Zahlen, bestehend aus zwei doppelt genauen Gleitkommazahlen. * Zeichenketten, bestehend aus beliebig vielen Zeichen. Von allen drei Datentypen können auch Vektoren und Matrizen gebildet werden, wie später gezeigt wird. Die Zeilen :: upper = 0; step = 20; fahr = lower; weisen den anderen in dieser Funktion verwendeten Variablen Anfangswerte zu. Es folgt eine sogenannte :keyword:`while`-Schleife: :: while (fahr <= upper) { ... fahr = fahr + step; } In der :keyword:`while`-Schleife wird zunächst die Bedingung ``fahr <= upper`` ausgewertet. Trifft sie zu, d.h. ``fahr`` ist kleiner oder gleich ``upper``, werden die Anweisungen innerhalb der :keyword:`while`-Schleife ausgeführt. Am Ende der :keyword:`while`-Schleife wird ``fahr`` um ``step`` (gleich 20) erhöht, was dazu führt, daß ``fahr`` irgendwann größer als ``upper`` wird, wodurch die :keyword:`while`-Schleife beendet wird. Ein paar Worte zur Formatierung von Funktionen: Man hätte alle Anweisungen der Funktion auch linksbündig schreiben können, das Programm ist jedoch besser lesbar, wenn die Anweisungen um eine Tabulatorposition nach rechts eingerückt werden. Anweisungen innerhalb von Schleifen oder :keyword:`if`-Anweisungen werden um eine weitere Tabulatorposition eingerückt. Die Tabulatorweite wird im Editor am besten so eingestellt, daß ein Tabulator 4 Leerzeichen entspricht. .. index:: printf Innerhalb der :keyword:`while`-Schleife befinden sich noch die beiden Anweisungen :: celsius = (5.0 / 9.0) * (fahr - 32.0); printf("%4.0f %6.1f\n", fahr, celsius); Die erste Anweisung führt die Umrechnung Fahrenheit in Celsius durch und die zweite Anweisung gibt die aktuellen Werte für ``fahr`` und ``celsius`` im UniScript-Kommandofenster aus. Für die Ausgabe wird die Funktion :ref:`printf` verwendet. Das Zeichen ``f`` am Ende des Funktionsnamens steht für *formatiert*. :ref:`printf` hat in diesem Beispiel drei Argumente. Das erste Argument ist ``"%4.0f %6.1f\n"``. Die Zeichenkette beschreibt, wie die anderen beiden Argumente ``fahr`` und ``celsius`` ausgegeben werden sollen. Die Zeichenkette enthält dazu die beiden Format-Elemente **%4.0f** und **%6.1f**. Format-Elemente beginnen mit einem Prozentzeichen. **%4.0f** bedeutet, daß der Parameter ``fahr`` mit insgesamt 4 Stellen ausgegeben wird und keine Nachkommastellen ausgegeben werden. Das **%f** bedeutet, daß die Zahl als Fließkommazahl ausgegeben wird. Entsprechend bewirkt **%6.1f**, daß ``celsius`` mit 6 Stellen ausgegeben wird, davon eine Stelle nach dem Komma. Die :ref:`printf`-Funktion verwendet als Dezimaltrennzeichen den Punkt ``.`` und kein Komma ``,`` wie im Deutschen üblich. Zeichen außerhalb von Format-Elementen werden direkt ausgegeben, wie das Leerzeichen zwischen den beiden Format-Elementen in der Beispiel-Funktion. Die beiden Zeichen ``\n`` bewirken, daß die nächsten Zeichen in einer neuen Zeile ausgegeben werden. In der Funktion ``main()`` werden 5 Variablen verwendet, nämlich: ``lower``, ``upper``, ``step``, ``fahr`` und ``celsius``. Diese Variablen werden erzeugt, wenn die Funktion aufgerufen wird und gelöscht, kurz bevor die Funktion beendet wird. Falls Sie es nicht bereits getan haben, geben Sie nun die Funktion in einem Editor ein; speichern Sie die Funktion z. B. unter dem Namen :file:`celsius.ic`. Führen Sie im Editor im Menü **UniScript** den Befehl **Speichern/Ausführen** aus. Sie können die Funktion ausführen, indem Sie die Funktion im UniScript-Kommando-Fenster aufrufen: :: * main() Experimentieren Sie ein wenig mit der Funktion. Ändern Sie z. B. die Format-Zeichenkette der :ref:`printf`-Funktion. Führen Sie nach jeder Änderung im Editor den Menü-Befehl **Laden/Ausführen** aus, und rufen Sie die Funktion im UniScript-Kommando-Fenster auf. .. _temperaturtabelle---2.-version: Temperaturtabelle - 2. Version ------------------------------ Wir wollen nun eine neue Funktion schreiben, die die gleiche Ausgabe wie ``main()`` erzeugt. Wir nennen Sie ``main2()``. Sie können Sie in die selbe Datei wie ``main()`` schreiben; in UniScript kann eine Datei beliebig viele Funktionen enthalten. :: /* Umwandlung von Fahrenheit in Celsius fuer f = 0, 20, ..., 300 -- 2. Fassung -- */ def main2() { for (fahr in 0:20:300) { printf("%4d %6.1f\n", fahr, 5/9 * (fahr-32)); } } ``main2()`` verwendet anstatt der :keyword:`while`-Schleife eine :keyword:`for`-Schleife. Sie hat in UniScript die Form:: for (var in vektor) { ... } :keyword:`for` und :keyword:`in` sind Schlüsselwörter, ``var`` steht für einen beliebigen Variablennamen, ``vektor`` steht für den Namen eines Vektors oder für einen konstanten Vektor. .. index:: Vektor Vektoren können in UniScript auf verschiedene Weise erzeugt werden. Eine Möglichkeit ist die Aufzählung der Elemente in eckigen Klammern wie weiter oben bereits gezeigt. :: vektor = [0,20,40,60,80] Eine andere Möglichkeit ist die Verwendung des Vektor-Erzeugungs-Operators ``:`` in der Form: :: vektor = start:step:end ``step`` kann auch weggelassen werden (``vektor = start:end``), dann wird für ``step`` 1.0 verwendet. ``0:20:100`` erzeugt beispielsweise den Vektor ``[0, 20, 40, 60, 80, 100]``. Die :keyword:`for`-Schleife :: for (fahr in 0:20:300) { printf("%4d %6.1f\n", fahr, (5/9)*(fahr-32.0)); } erzeugt am Anfang der Schleife den Vektor ``0:20:300`` und weist ``fahr`` nacheinander die Werte 0, 20, 40 bis 300 zu. Wenn am Anfang einer Schleife bekannt ist, wie oft eine Schleife ausgeführt werden muss, ist die :keyword:`for`-Schleife besser geeignet als die :keyword:`while`-Schleife, so daß ``main2()`` sicherlich eine bessere Lösung ist als ``main()``. .. _temperaturtabelle---3.-version: Temperaturtabelle - 3. Version ------------------------------ Es gibt in UniScript noch bessere Lösungen. Es kann bei diesem Problem ganz auf Schleifen verzichtet werden: :: def main3() { fahr = (0:20:300)'; printf("%4.0f %6.1f\n", fahr, (5/9)*(fahr-32)); } In ``main()`` und ``main2()`` wurden skalare Werte an die Funktion :ref:`printf` übergeben, nämlich nacheinander die Werte 0, 20, 40 usw. In ``main3()`` wird mit der Anweisung :: fahr = (0:20:300)'; ein Spaltenvektor erzeugt. ``'`` ist der Transponierungs-Operator, der aus dem Zeilenvektor ``0:20:300`` einen Spaltenvektor macht. Da ``fahr`` ein Spaltenvektor ist, ist auch ``(5/9)*(fahr-32)`` ein Spaltenvektor mit genau so vielen Zeilen wie ``fahr``. :ref:`printf` arbeitet so oft die Format- Zeichenkette ``"%4.0f %6.1f\n"`` ab, wie Zeilen in den anderen Argumenten sind; :ref:`printf` hat sozusagen eine eingebaute :keyword:`for`-Schleife. Es gibt in UniScript viele Funktionen mit eingebauten :keyword:`for`-Schleifen :: y = sin(0:2*PI/100:2*PI) erzeugt z. B. den Vektor ``y`` mit 100 Werten, ohne daß die Verwendung einer Schleife erforderlich ist. Dadurch können mit UniScript sehr kompakte Programme geschrieben werden. .. _temperaturtabelle---4.-version: Temperaturtabelle - 4. Version ------------------------------ Es soll nun die Temperatur-Tabellen-Ausgabe nicht als Funktion, sondern in einer einzigen Anweisung geschrieben werden. Sie können den Funktionsaufruf entweder direkt ins UniScript-Kommandofenster schreiben oder in einen Editor. Bei jedem :ref:`uniscriptspeichern/ausfuhren`-Befehl wird die Zeile direkt ausgeführt. :: printf("%4d %6.1f\n", fahr = (0:20:300)', 5/9*(fahr-32)); Die Zeile zeigt eine weitere interessante Möglichkeit von UniScript, kompakte Programme zu schreiben. Eine Zuweisung ist nicht nur eine Anweisung wie bei den meisten Programmiersprachen, sondern wie in C auch ein Ausdruck. Dadurch sind Formulierungen wie ``a = 3 * (b = 5)`` möglich - ``a`` bekommt den Wert 15, und ``b`` den Wert 5 in einer Anweisung zugewiesen. In UniScript gibt es als vereinfachte Ausgabemöglichkeit die :keyword:`print`-Anweisung, bei der kein Format-String erforderlich ist. :keyword:`print` ist kein Funktionsaufruf, sondern eine in die Sprache UniScript eingebaute Anweisung. Es werden deshalb keine Klammern um die Argumente geschrieben. Die Zeile :: print [fahr = (0:20:300)', 5/9*(fahr-32)]; erzeugt zunächst aus den beiden Vektoren eine Matrix mit zwei Spalten, die anschließend in einem Standard-Format ausgegeben wird. Würde :keyword:`print` in der Form :: print fahr = (0:20:300)', 5/9*(fahr-32) geschrieben werden, so würden die beiden Vektoren nacheinander ausgegeben werden. Der Nachteil der :keyword:`print`-Anweisung ist, daß keine genaue Kontrolle über die Ausgabe vorhanden ist. (Schauen Sie sich die :ref:`format`-Funktion im Hilfe-System an. Mit dieser Funktion kann das Standard-Format geändert werden.) Außerdem kann mit der :keyword:`print`-Anweisung nicht direkt in Dateien geschrieben werden, wie dies mit einer speziellen Version der :ref:`printf`-Funktion möglich ist (:ref:`fprintf`). .. _ausgabe-der-temperaturtabelle-als-graphik: Ausgabe der Temperaturtabelle als Grafik ---------------------------------------- Als letztes Beispiel soll die Temperatur-Fahrenheit-Tabelle als Diagramm dargestellt werden. Ein Diagramm kann mit der Funktion :ref:`plot` erzeugt werden. :: h = plot(fahr = 0:20:300, 5/9 * (fahr - 32)) :ref:`plot` ist eine Funktion, die selber in UniScript geschrieben ist. Sie können sich den Quelltext von :ref:`plot` in der Datei :file:`script/plot.ic` anschauen. :ref:`plot` hat den Zweck, XY-Diagramme aus Funktionen oder Vektoren zu erzeugen. In der Abbildung sehen Sie das Ergebnis des :ref:`plot`-Aufrufs. .. image:: S:/uniplot-obj/images/UniScriptFahrenheitCelsius.* Das Diagramm muss bei Ihnen nicht exakt genau so aussehen; :ref:`plot` verwendet die Standard-Einstellungen, die Sie mit dem Befehl **Extras** in UniPlot verändern können. Die :ref:`plot`-Funktion hat ein neues Fenster erzeugt, in das Fenster ein Koordinatensystem gezeichnet, und die x- und die y-Koordinaten als Kurvenzug im Koordinatensystem ausgegeben. Für diese drei Begriffe sollen im folgenden die Begriffe Dokument, Layer und Datensatz verwendet werden. Ein Fenster repräsentiert ein Dokument, ein Dokument ist der Inhalt des Fensters. In einem Dokument können ein oder mehrere Layer enthalten sein. Ein Layer hat ein Koordinatensystem, das nicht unbedingt sichtbar sein muss. Ein Layer kann neben Datensätzen auch Zeichenelemente enthalten. Ein Datensatz hat Datenpunkte mit Koordinaten. Er enthält aber auch Informationen über seine Darstellungsart. UniPlot ist in der objekt-orientierten Programmiersprache C++ programmiert worden. Dokumente, Layer und Datensätze sind dabei die Objekte, die mit UniPlot/UniScript erzeugt und verändert werden können. UniScript selber ist keine objekt-orientierte Programmiersprache. Um die Objekte dennoch zu verändern, werden in UniScript Zugriffsnummern (handle) auf die von UniPlot erzeugten Objekte verwendet. Der Aufruf :: h = plot(fahr = 0:20:300, 5/9 * (fahr - 32)) gibt einen Vektor von Zugriffsnummern zurück. * ``h[1]`` ist dabei die Zugriffsnummer der Dokument-Seite, * ``h[2]`` ist die Zugriffsnummer des Layers (Diagramms) und * ``h[3]`` die Zugriffsnummer des Datensatzes. Ordnen Sie das Kommandofenster und das Fenster mit dem Diagramm nebeneinander an und geben Sie im Kommandofenster .. index:: PagePrint :: PagePrint(h[1]) ein. Das Dokument wird gedruckt. Die Namen aller UniScript-Funktionen, die Dokumente verändern können, fangen mit den Buchstaben ``Doc`` an. Um eine Liste dieser Funktionen zu erhalten, geben Sie ``what("Doc*")`` ein:: * what ("Doc*") DocAddPage DocCopyPage DocCreate DocDestroy DocGetActivePage DocGetAllPages ... DocSetProtectionFlags DocSetReadOnly DocSetSummaryInfo DocSetTitle DocShow 54 function(s) defined .. index:: what, LayerSetAxisTitle Die Funktion :ref:`what` gibt die Namen aller geladenen Funktionen aus, die ein bestimmtes Muster haben. Versuchen Sie ``what()``, ``what("Layer*")`` und ``what("XY*")``. Schauen Sie sich die Beschreibungen der Funktionen im Hilfesystem an. Um die Beschreibung einer bestimmten Funktion zu erhalten, können Sie im Kommandofenster den Namen der Funktion schreiben, mit der Pfeiltaste nach links ein Zeichen zurückgehen und die F1-Taste drücken. Anschließend löschen Sie den Namen wieder mit der ESC-Taste. Zum Schluß sollen noch die Achsenbeschriftungen geändert werden :: LayerSetAxisTitle(h[2], "X", "Celsius") LayerSetAxisTitle(h[2], "Y", "Fahrenheit") PageReplot(h[1]) Normalerweise würde man die Achsenbeschriftungen mit UniPlot interaktiv ändern. Wenn die Achsenbeschriftungen aber automatisch erzeugt werden sollen, z. B. indem die Texte aus einer Datei gelesen werden, muss UniScript verwendet werden. :sub:`id-1087286`