Ing Mathematik: Julia
Hallo Welt und allgemeine Hinweise
[Bearbeiten]Was ist Julia
[Bearbeiten]- Julia ist eine höhere Programmiersprache, die vor allem für numerisches und wissenschaftliches Rechnen entwickelt wurde.
- Julia ist Open-Source (MIT-Lizenz).
- Julia ist schnell (JIT-Compiler).
- Julia ist für wichtige Betriebssysteme erhältlich (z.B. für Linux, MS Windows, macOS).
- Julia als Programmiersprache ist case-sensitive - d.h. Groß- und Kleinschreibung ist relevant bei der Eingabe von Befehlen.
.
Julia installieren
[Bearbeiten]MS Windows
[Bearbeiten]Laden Sie das aktuelle Julia-Paket von der Webseite [1] herunter. Weiter geht es wie bei jedem anderen größeren zu installierenden Programm. Einfach das Installationsprogramm im Explorer doppelklicken und den Anweisungen des Setup-Programmes folgen.
Julia starten
[Bearbeiten]MS Windows
[Bearbeiten]Das Icon für das Julia-Programm doppelklicken. Und schon startet das Programm.
Das Julia-System präsentiert sich dann folgendermaßen (interaktives Kommandozeilenprogramm REPL [Read–eval–print loop]):
Ein paar Worte zur Erklärung
[Bearbeiten]Getestet wurden die Beispiele unter dem Betriebssystem MS Windows 10 mit den Julia-Versionen 1.9.4 und 1.10.2. An Beliebtheit rangiert Julia mit Stand November 2024 mit einem Rating von 0,54% an 29. Stelle der beliebtesten Programmiersprachen (lt. TPCI - TIOBE Programming Community Index).
Ein erstes Programm
[Bearbeiten]Kommentare werden in Julia mit der Raute (#) eingeleitet. Sie werden vom Julia-Interpreter ignoriert. Text kann mit der print- oder println-Funktion ausgegeben werden. Starten Sie Julia und geben sie folgende Anweisungen zeilenweise ein (die Anweisungen sind jeweils mit der Return-Taste abzuschließen)
julia> # Das ist ein Kommentar julia> print("Hallo Welt!")
Als Ergebnis erhalten Sie
Hallo Welt!
Der Prompt (julia>) ist selbstverständlich nicht einzutippen, sondern wird vom Julia-System geliefert.
Strings sind in Julia in Anführungszeichen (") zu setzen. Zwischen dem Befehl print und der öffnenden Klammer ( darf kein Leerzeichen gesetzt werden.
Julia als Taschenrechner
[Bearbeiten]Allgemeines
[Bearbeiten]Wir wollen 3 * 5 berechnen. Dazu starten wir Julia. Geben Sie dann die Formel
julia> 3 * 5
ein, drücken die Taste ENTER/RETURN und erhalten als Ergebnis
15
Auch kompliziertere Ausdrücke sind möglich. Beispielsweise mit Winkelfunktionen, Quadratwurzeln etc. Wir wollen nun den Ausdruck berechnen :
julia> sin(sqrt(15)) -0.6679052983383519
Mit dieser Zahl kann unmittelbar weitergerechnet werden, z.B.
julia> ans * 2 -1.3358105966767038
"ans" steht übrigens für den Begriff "answer" (auf Deutsch "Antwort").
Das Mal-Zeichen (*) kann übrigens eingespart werden. ans * 2
ist dasselbe wie 2ans
. Man beachte aber, dass in der Kurzform kein Leerzeichen zwischen 2 und ans stehen darf.
Beenden lässt sich das Julia-Programm durch Eingabe von exit() (und natürlich ist zur Bestätigung die RETURN-Taste zu drücken). Beachten Sie wieder, dass zwischen der Funktion exit und der öffnenden Klammer kein Leerzeichen stehen darf.
Die Hilfefunktion von Julia
[Bearbeiten]Bei Eingabe eines Fragezeichens (?) springt Julia in das Hilfesystem.
Eingabe:
?
Eingabe:
help?> sin
Ausgabe:
sin search: sin sinh sind sinc sinpi sincos sincosd sincospi asin using isinf asinh asind isinteger isinteractive thisind sin(x) Compute sine of x, where x is in radians. See also sind, sinpi, sincos, cis, asin. Examples ≡≡≡≡≡≡≡≡≡≡ julia> round.(sin.(range(0, 2pi, length=9)'), digits=3) ... ... ... 0.454649 0.454649
Für die komplette Julia-Dokumentation siehe [2].
Aufgaben
[Bearbeiten]- Erkunden Sie die Tangensfunktion "tan" mittels Julia-Hilfe.
- Berechnen Sie mit Julia den Ausdruck . Siehe für die Exponentialfunktion im Julia-Hilfesystem auch den Befehl exp(). Potenzieren kann man bei Julia mit dem ^-Operator (z.B. 2^3 = 8)
- Berechnen Sie mit Julia den Ausdruck . Anmerkung: cosd erwartet den Parameter im Gradmaß (d für "degree"), sin erwartet den Parameter im Bogenmaß.
Julia als Scriptsprache
[Bearbeiten]Häufig wird man aber kompliziertere Anweisungsfolgen verarbeiten müssen. Diese will man normalerweise nicht jedesmal neu eingeben, sondern in einer Datei speichern und diese Datei dann zur Ausführung bringen. Speichern Sie dazu folgenden Code in einer Textdatei, z.B. unter MS Windows als c:\tmp\test1.jl
# Das ist ein Kommentar print("Hallo Welt!")
Julia-Dateien werden mit der Dateiendung .jl versehen.
Danach bringen Sie die Skriptdatei test1.jl (sozusagen das Hauptprogramm) folgendermaßen zur Ausführung:
1) Starten Sie unter MS Windows die Eingabeaufforderung (oder alternativ die Windows PowerShell). Das sieht dann etwa so aus:
Microsoft Windows [Version 10.0.19045.3693] (c) Microsoft Corporation. Alle Rechte vorbehalten. C:\Users\xyz>
- Falls jemand nicht weiß, wie man die Eingabeaufforderung startet: Eine Möglichkeit ist, einfach in der Taskleiste von Windows das "Start"-Symbol mit der rechten Maustaste anklicken. "Ausführen" auswählen (oder alternativ für die PowerShell den Eintrag "Windows PowerShell"). Im sich öffnenden Dialogfenster gibt man in die "Öffnen"-Zeile das Wort
cmd
ein und mit "OK" wird das Ganze bestätigt.
2) Wechseln Sie mittels cd c:\tmp
in das Verzeichnis c:\tmp
3) Angenommen, Sie haben Julia unter dem Pfad c:\devel\Julia-1.9.4\
installiert. Starten Sie das Programm so (der Prompt c:\tmp>
ist natürlich nicht mit einzutippen):
c:\tmp>c:\devel\Julia-1.9.4\bin\julia.exe test1.jl
4) Wie erwartet ergibt sich folgende Ausgabe am Bildschirm
Hallo Welt!
Variablen
[Bearbeiten]Variablenbezeichner können aus Buchstaben (A-Za-z), Ziffern (0-9), Underscores (_) und etlichen Unicode-Zeichen bestehen, dürfen aber nicht mit einer Zahl beginnen.
Gültige Variablenbezeichner wären also:
xyz x1 _wert name_anzahl a₂ γπΩ
Wie kann man eigentlich die griechischen Zeichen im vorhergehenden Beispiel eingeben? Auf einer deutschen oder englischen Tastatur sind sie jedenfalls nicht zu finden. Des Rätsels Lösung kann folgendermaßen aussehen (wird am Beispiel des Omega-Zeichens (Ω) vorgeführt):
1) Starten Sie das Julia-System (z.B. mittels Doppelklick auf das Julia-Icon oder in der Eingabeaufforderung durch direkte Eingabe von julia.exe (ggf. mit dem entsprechenden Programmpfad).
2) geben Sie \Omega
ein (ohne den Befehl mit Return abzuschließen)
julia> \Omega
3 Tippen Sie auf die Tabulatortaste und schon erscheint das Ω.
4) Dieses Zeichen können Sie dann mittels Zwischenablage z.B. auch in eine jl.-Datei einfügen (ggf. unter Verwendung eines geeigneten Text-Editors, z.B. Geany)
Ähnliches gilt für tiefgestellte Indizes, z.B. a\_2
gefolgt von einem Tabulator ergibt a₂.
Da Julia case-sensitiv ist, repräsentieren folgende Bezeichner verschiedene Variablen:
xyz XYZ xYz
Werte werden an Variablen mittels Gleich-Zeichen (=) zugewiesen. Im Folgenden wird der Code immer in der Datei c:\tmp\test1.jl
gespeichert.
x = 5 y = 10 z = x*y print(z)
Bringen Sie die Datei test1.jl zur Ausführung, so erhalten Sie folgende Bildschirmausgabe
50
Sie können auch mehrere Anweisungen in einer Zeile durch Semikolon getrennt schreiben.
x = 5; y = 10; z = x*y print(z)
Ausgabe:
50
Auch aus der Programmiersprache C/C++ oder Java bekannte Konstrukte können Sie verwenden, z.B.
x = 5; println(x) # x = x - 2 x -= 2 println(x)
Bildschirmausgabe:
5 3
Beachten Sie, dass mit dem =-Zeichen eine Wertezuweisung durchgeführt wird. Dies ist nicht äquivalent zum mathematischen =-Zeichen, wie am vorigen Beispiel zu ersehen ist. Die Verwendung von Prä-/Postfix-Operatoren (++, --) wie unter C/C++ oder Java ist in Julia nicht erlaubt, sondern liefert nur eine Fehlermeldung.
Soll eine Anweisung auf mehrere Zeilen verteilt werden, z.B. weil sie zu lang ist, so kann dies geschehen, wie nachfolgend dargestellt.
x = 5; y = 1000 * x + sin(x/2) print(y)
Ausgabe:
5000.598472144104
Beachten Sie, dass die Zeilentrennung nach einem Operator erfolgt! Folgendes würde ein falsches Resultat liefern:
x = 5; y = 1000 * x + sin(x/2) print(y)
Ausgabe:
5000
Variablen sind nicht an einen bestimmten Datentyp gebunden, folgendes ist mit Julia problemlos möglich:
wert = 10 println(wert) wert = 35.5 println(wert) wert = "Hallo" println(wert) wert = pi println(wert)
Ausgabe:
10 35.5 Hallo π
Hexadezimale, oktale und binäre Zahlen
[Bearbeiten]# Hexadezimale Zahl println(0xABC) # Oktale Zahl println(0o56) # Binäre Zahl println( 0b1000011 )
Ausgabe (als Dezimalzahlen):
2748 46 67
Julia kann auch dezimale in binäre Zahlen etc. umwandeln:
Eingabe:
b = bitstring(30) println(b)
Ausgabe:
0000000000000000000000000000000000000000000000000000000000011110
Ein anderes Beispiel (hexadezimal nach binär):
# hexadezimal -> binär s = string(0xF, base=2) print(s)
Ausgabe:
1111
Verzweigungen
[Bearbeiten]if
[Bearbeiten]Die IF-Verzweigung ist aus anderen Programmiersprachen bereits bekannt. In Pseudocode lässt sie sich folgendermaßen darstellen:
WENN bedingung TRUE führe block1 aus SONST führe block2 aus ENDE
Die test1.jl-Datei laute also wie folgt:
x = 5; if x < 4 println("x ist kleiner als 4"); else println("Der else-Zweig wird ausgefuehrt"); println("x ist groesser oder gleich 4"); end
Ausgabe:
Der else-Zweig wird ausgefuehrt x ist groesser oder gleich 4
Julia kennt eine Reihe von Vergleichs- und Verknüpfungsoperatoren:
- <, <= ... kleiner (gleich)
- >, >= ... größer (gleich)
- == ... gleich
- != ... ungleich
- &, && ... AND
- |, || ... OR
Beispielsweise:
a = 5; b = 9; if a<=10 & b!=7 println("OK"); else println("Nicht OK"); end
Ausgabe:
OK
Erweiterung der if-else-end-Verzweigung - ein Beispiel mit elseif
:
a = 5 if a==10 println("OK") elseif a==5 println("Nicht OK") println("a = 5") elseif a==6 println("Auch nicht OK") else println("Weiß nicht") end
Ausgabe:
Nicht OK a = 5
Ternärer Operator
[Bearbeiten]Eingabedatei:
a = 5 a >= 6 ? println("größer gleich 6") : println("kleiner 6")
Ausgabe:
kleiner 6
Schleifen
[Bearbeiten]while
[Bearbeiten]Die WHILE-Schleife ist kopfgesteuert. Sie funktioniert nicht ganz so wie aus anderen Programmiersprachen bekannt.
In Pseudocode:
SOLANGE bedingung TRUE führe block aus ENDE
In Julia:
x = 0 while x <= 10 println(x) global x += 1 end
Ausgabe:
0 1 2 3 4 5 6 7 8 9 10
Außerhalb von Funktionen muss das Schlüsselwort global
verwendet werden. Ansonsten gibt es eine Warnung und eine Fehlermeldung. Innerhalb einer Funktion benötigt man das global
nicht.
for
[Bearbeiten]for x = 0 : 2 : 10 println(x); end
Ausgabe:
0 2 4 6 8 10
Der FOR-Schleifenkopf ist in Form einer Zahlenkolonne folgendermaßen aufgebaut:
for variable = startwert : schrittweite : endwert
Alternativ findet man in der Literatur auch folgende for-Schleifenaufbauten.
for x in 0 : 2 : 10 println(x); end
for x ∈ 0 : 2 : 10 println(x); end
Achtung: Das ∈ ist kein \epsilon, sondern ein \in.
Die unterschiedlichen for-Schleifen liefern jeweils das gleiche Ergebnis.
break und continue
[Bearbeiten]Zum Abbrechen einer Schleife gibt es den Befehl "break".
for var = 0 : 1 : 100 println(var) if var == 5 break; end end
Ausgabe:
0 1 2 3 4 5
"continue" setzt mit dem nächsten Schleifendurchlauf fort, z.B.
for var = 0 : 1 : 10 if var == 5 continue; end println(var); end
Ausgabe:
0 1 2 3 4 6 7 8 9 10
Eingabe via Tastatur
[Bearbeiten]Datei c:\tmp\test1.jl:
print("Geben Sie eine Zahl ein: ") # Einlesen als String str = readline(stdin) print("Die Zahl lautet ") println(str) # Umwandeln in einen Float zahl = parse(Float64, str) print("Die Zahl lautet ") println(zahl)
Eingabe der Zahl via Tastatur:
67.8
Mit der RETURN-Taste bestätigen.
Ausgabe:
Die Zahl lautet 67.8 Die Zahl lautet 67.8
In diesem Fall wird, wie gezeigt, zweimal Die Zahl lautet 67.8
ausgegeben. Gibt man aber z.B. Eins
ein, so wird einmal Die Zahl lautet Eins
ausgegeben. Das ist klar, da Eins
ein gültiger String ist. Danach folgt aber eine Fehlermeldung, weil Eins
nicht in eine Fließkommazahl umgewandelt werden kann.
Grafiken zeichnen
[Bearbeiten]Es gibt in Julia mehrere Möglichkeiten Grafiken zu zeichnen. Hier wird eine Einführung in das Package Plots gegeben.
Plots installieren
[Bearbeiten]Im Julia-REPL die schließende eckige Klammer ] eintippen. Damit springt man in das Package-System, angezeigt wird das mit dem Prompt (@v1.9) pkg>
.
Das Plots-Package zum Julia-System hinzufügen:
(@v1.9) pkg> add Plots
Mit STRG-C kann das Package-System wieder verlassen werden.
2D
[Bearbeiten]Graph einer Funktion
[Bearbeiten]Es soll die cosh-Funktion im Intervall gezeichnet werden. Der Programmcode lautet in der einfachsten Form:
using Plots x = -3 : .1 : 3 y = cosh.(x) p = plot(x, y) gui() while(true) end
Ausgabe:
Der Code ist quasi selbsterklärend. Das Plots-Package wird importiert. x läuft von -3 bis +3. y wird für jeden x-Wert per Formel ausgerechnet. "plot" ist der Zeichenbefehl. "gui" ist notwendig, um das Fenster mit der Grafik anzuzeigen. Es folgt eine Endlossschleife. Diese ist notwendig, weil das Fenster mit der Grafik sonst nur kurz aufblinkt und das Programm danach beendet wird. Das Gesagte gilt, wenn man die test1.jl-Datei direkt ausführt. Im REPL kann man sich den Befehl "gui" und die Endlosschleife sparen.
Die Schrittweite 0.1 wurde so gewählt, um einen ausreichend glatten Verlauf des Graphen zu gewährleisten. Das ist immer ein Kompromiss zwischen Berechnungszeit und Ansehnlichkeit. Testen Sie einfach ein paar verschiedene Werte, um ein Gefühl dafür zu zu bekommen.
Hinweise:
- Bis das Fenster mit dem cosh-Graphen erscheint, kann es einige Sekunden dauern.
- Beenden kann man die Endlosschleife, indem man STRG-C drückt (STRG ist die Steuerungs- oder Control-Taste)
- Beachten Sie den Punkt (.) bei der cosh-Funktion. Vergessen Sie diesen, so wird eine Fehlermeldung ausgegeben.
Ein etwas komplexeres Beispiel ist folgendes
using Plots x = -3 : .1: 3 y = cosh.(x) + 2 .^x plot(x,y) gui() while true end
Man beachte die Punkte bei der Funktion y. Vergisst man die Punkte, dann erhält man eine Fehlermeldung. Weiters beachte man das Leerzeichen und die Position desselben bei 2 .^x. Setzt man das Leerzeichen an die falsche Stelle oder vergisst es ganz, so ist das auch ein Fehler.
Ausgabe:
Graphen mehrerer Funktionen und weiteres
[Bearbeiten]Mehrere Graphen lassen sich folgendermaßen in ein Fenster zeichnen (es werden auch Titel und Labels gesetzt):
using Plots x = -3 : .1: 3 y1 = cosh.(x) + 2 .^x y2 = sin.(x) .* cos.(x) plot(x, [y1, y2], title="Screenshot", label=["cosh(x) + 2^x" "sin(x) + cos(x)"], xlabel="x", ylabel="y") gui() while true end
Will man mehrere Graphen in ein Fenster zeichnen, aber nicht alles in einen plot-Befehl quetschen, so kann die "plot!"-Anweisung die Lösung des Problems sein. Auch die Linienstile sollen nun etwas individueller gestaltet werden:
using Plots x = -3 : .1: 3 y1 = cosh.(x) + 2 .^x y2 = sin.(x) .* cos.(x) plot(x, y1, linestyle=:dot, label="cosh ...", linewidth=5) plot!(x, y2, ls=:dot, label="sin ...", lw=3) title!("Funktionsgraphen") xlabel!("x") ylabel!("y") gui() while true end
Funktion in Parameterdarstellung
[Bearbeiten]Es soll die archimedische Spirale im Intervall gezeichnet werden.
using Plots t = 0 : .1: 6*pi x = t .* cos.(t) y = t .* sin.(t) plot(x, y, lw=5) gui() while true end
Der Graph erscheint in der obigen Darstellung verzerrt. Will man das nicht, so setze man das aspect_ratio
auf :equal
:
using Plots t = 0 : .1: 6*pi x = t .* cos.(t) y = t .* sin.(t) plot(x, y, lw=5, aspect_ratio = :equal) gui() while true end
Logarithmische Achsenskalierung
[Bearbeiten]using Plots f(x) = 10^x p1 = plot(f, 1, 5, lw=2, title="kartesische Koordinaten") p2 = plot(f, 1, 5, yscale=:log10, lw=2, title="Semilog") p3 = plot(f, 1, 5, xscale=:log10, yscale=:log10, lw=2, title="LogLog") plot(p1, p2, p3, layout=(3,1)) gui() while true end
Ausgabe:
Aufgaben
[Bearbeiten]- Zeichnen Sie die Strophoide . Das Ganze sollte in etwa so aussehen wie folgende Grafik:
- Zeichnen Sie die verschlungene Hypozykloide . Das Ganze sollte in etwa so aussehen wie folgende Grafik:
- Testen Sie bei den obigen Übungsaufgaben verschiedene Werte für a, c, r und R.
3D
[Bearbeiten]Räumliche Kurven
[Bearbeiten]Mittels "plot3d" lassen sich Raumkurven zeichnen.
using Plots t = 0 : .1: 6*pi x = t .* cos.(t) y = t .* sin.(t) z = t plot3d(x, y, z) gui() while true end
Flächen
[Bearbeiten]using Plots x = 0 : .1 : 10; y = 0 : .1 : 10; z(x,y) = sin(x) + 3*cos(y); surface(x,y,z) gui() while true end
Das Ganze in Netzdarstellung läßt sich so programmieren:
using Plots x = 0 : .5 : 10 y = 0 : .5 : 10 z(x,y) = sin(x) + 3*cos(y) wireframe(x, y, z) gui() while true end
Die Kameraposition lässt sich verändern:
using Plots x = 0 : .1 : 10 y = 0 : .1 : 10 z(x,y) = sin(x) + 3*cos(y) # Kamerawinkel in Grad (Azimut, Altitude) surface(x,y,z, camera = (75, 60)) gui() while true end
Höhenlinien
[Bearbeiten]using Plots x = 0 : .1 : 10 y = 0 : .1 : 10 z(x,y) = sin(x) + 3*cos(y) contour(x,y,z) gui() while true end
Etwas abgewandelt sind das so aus:
using Plots x = 0 : .1 : 10 y = 0 : .1 : 10 z(x,y) = sin(x) + 3*cos(y) contour(x, y, z, levels=10, clabels=true, cbar=false) gui() while true end
Und noch eine Variante sei gezeigt.
using Plots x = 0 : .1 : 10 y = 0 : .1 : 10 z(x,y) = sin(x) + 3*cos(y) contourf(x, y, z) gui() while true end
Aufgaben
[Bearbeiten]- Zeichnen Sie die räumliche Kurve , , , .
- Zeichnen Sie die Fläche .
Animationen
[Bearbeiten]using Plots anim = Animation() for i = 1:100 plt = plot(sin, 0, i*2pi/10, ylims = (-1., 1.), lab="") frame(anim, plt) end gif(anim, "c:/tmp/Julia_anim1.gif",fps=10)
Dieses Programm schreibt ein animiertes GIF in die Datei c:/tmp/Julia_anim1.gif
.
Vektoren und Matrizen
[Bearbeiten]Vektoren
[Bearbeiten]Vektoren sollten jedem aus der Linearen Algebra bekannt sein.
Spalten- und Zeilenvektoren
[Bearbeiten]Starten Sie die Julia-REPL. Geben Sie folgenden Befehl ein, um einen Spaltenvektor zu erstellen:
julia> v1 = [1, 2, 3]
Ausgabe:
3-element Vector{Int64}: 1 2 3
Geben Sie folgenden Befehl ein, um einen Zeilenvektor (oder genauer eine 1x3-Matrix) zu erstellen:
julia> v1 = [1 2 3]
Ausgabe:
1×3 Matrix{Int64}: 1 2 3
Zugriff auf Vektorelemente
[Bearbeiten]Nachfolgend seien Zugriffsmöglichkeiten auf die Vektorelemente erläutert.
Auf ein einzelnes Element kann via Index zugegriffen werden. Der Index startet bei 1:
v1 = [1, 2, 3] println(v1[2])
Ausgabe:
2
Mehrere Elemente werden folgendermaßen angesprochen:
v1 = [1 2 4 8 16] print(v1[3:4])
Ausgabe:
[4, 8]
Liefere den Teilvektor von einem gegebenen Index bis zum letzten Element:
v1 = [1 2 4 8 16] print(v1[3:end])
Ausgabe:
[4, 8, 16]
Addition und Subtraktion von Vektoren
[Bearbeiten]v1 = [1, 2, 3] v2 = [5, 7, 9] println(v1 + v2) println(v1 - v2)
Ausgabe:
[6, 9, 12] [-4, -5, -6]
Multiplikation mit Skalaren
[Bearbeiten]faktor = 3; v = [1, 2, 3]; println(v * faktor)
Ausgabe:
[3, 6, 9]
Skalarprodukt
[Bearbeiten]Das Skalarprodukt ist bekanntermaßen als definiert. In Julia sieht das so aus:
using LinearAlgebra v1 = [1, 2, 3] v2 = [2, 5, 10] println(LinearAlgebra.dot(v1, v2))
Ausgabe:
42
Hinweis: Wenn das LinearAlgebra-Paket noch nicht installiert ist, so muss dies eventuell nachgeholt werden. Wie das prinzipiell funktioniert, wurde im Kapitel "Grafiken zeichnen" am Beispiel des Plots-Pakets vorgeführt.
Vektorprodukt
[Bearbeiten]
Julia-Code:
using LinearAlgebra v1 = [1, 2, 3] v2 = [2, 5, 10] println(LinearAlgebra.cross(v1, v2))
Ausgabe:
[5, -4, 1]
Transponierter Vektor
[Bearbeiten]using LinearAlgebra v = [1, 2, 3] println(LinearAlgebra.transpose(v))
Ausgabe:
[1 2 3]
Einige weitere Vektorfunktionen
[Bearbeiten]Die euklidische Norm in Julia:
using LinearAlgebra v = [1 2 3] println(norm(v))
Ausgabe:
3.7416573867739413
Beispiel:
# 1 + 2 + 3 v = [1 2 3] println(sum(v))
Ausgabe:
6
Beispiel:
# 1 * 2 * 3 * 4 v = [1 2 3 4] println(prod(v))
Ausgabe:
24
Matrizen
[Bearbeiten]Starten Sie die Julia-REPL. Geben Sie folgenden Befehl ein, um eine 2x3-Matrix zu erstellen:
julia> [1 2 3; 4 5 6]
Ausgabe:
2×3 Matrix{Int64}: 1 2 3 4 5 6
Damit verlassen wir die Julia-REPL wieder und arbeiten im Folgenden mit der test1.jl-Datei weiter.
Zugriff auf Matrizenelemente
[Bearbeiten]m = [1 2 3; 4 5 6] # Element aus Zeile 2 und Spalte 3 println(m[2,3])
Ausgabe:
6
Eine andere Zugriffsmöglichkeit ist diese:
m = [1 2 3; 4 5 6] # Auf das Element an Position 5 soll zugegriffen werden println(m[5])
Ausgabe:
3
Die Matrix wird also spaltenweise durchlaufen (nicht zeilenweise). Dies ist vielleicht auf den ersten Blick etwas ungewöhnlich, wird aber z.B. auch in Fortran oder Octave so gehandhabt.
Addition und Subtraktion von Matrizen
[Bearbeiten]m1 = [1 2 3; 4 5 6] m2 = [-4 -2 0; 2 4 6] println(m1 + m2) println(m1 - m2)
Ausgabe:
[-3 0 3; 6 9 12] [5 4 3; 2 1 0]
Transponierte Matrix
[Bearbeiten]m = [1 2 3; 4 5 6] println(m')
Ausgabe:
[1 4; 2 5; 3 6]
Rang einer Matrix
[Bearbeiten]using LinearAlgebra m1 = [1 2 3; 4 5 6] m2 = [1 2 3; 2 4 6] println(LinearAlgebra.rank(m1)) println(LinearAlgebra.rank(m2))
Ausgabe:
2 1
Inverse Matrix
[Bearbeiten]using LinearAlgebra m = [1 3; 0 -5 ] println(LinearAlgebra.inv(m))
Ausgabe:
[1.0 0.6000000000000001; 0.0 -0.2]
Determinate einer Matrix
[Bearbeiten]using LinearAlgebra m1 = [1 3; 0 -5 ] m2 = [1 2; 2 4] println(LinearAlgebra.det(m1)) println(LinearAlgebra.det(m2))
Ausgabe:
-5.0 0.0
m1 ist regulär, m2 ist singulär. Determinanten können nur von quadratischen Matrizen gebildet werden.
Multiplikation von Matrizen (falksches Schema)
[Bearbeiten]m1 = [1 3 4; 0 -5 1] m2 = [1 2; 2 3; 0 2] println(m1 * m2)
Ausgabe:
[7 19; -10 -13]
Teilmatrizen
[Bearbeiten]m = [1 2 3; 0 5 1] # Die Matrix in einen Spaltenvektor umwandeln println(m[:]) # Das Element aus der 1. Zeile und der 2. Spalte extrahieren println(m[1,2]) # Erste Zeile extrahieren println(m[1, 1:3]) println(m[1, :]) # Zweite Spalte extrahieren println(m[1:2, 2]) println(m[:, 2])
Ausgabe:
[1, 0, 2, 5, 3, 1] 2 [1, 2, 3] [1, 2, 3] [2, 5] [2, 5]
Eigenwerte und Eigenvektoren
[Bearbeiten]using LinearAlgebra A = [5 8; 1 3] # Eigenvektoren und Eigenwerte println(eigvals(A)) println(eigvecs(A))
Ausgabe:
[1.0, 7.0] [-0.8944271909999159 0.9701425001453319; 0.447213595499958 0.24253562503633297]
LR-Zerlegung einer Matrix
[Bearbeiten]Führen Sie die LR-Faktorisierung (LR ... links/rechts bzw. LU ... left/upper) einer Matrix m aus. Dazu springen wir wieder in die REPL und geben folgende Befehle ein:
julia> using LinearAlgebra julia> m=[1 0 5; -1 1 -2; 0 0 3] 3×3 Matrix{Int64}: 1 0 5 -1 1 -2 0 0 3 julia> f = factorize(m) LU{Float64, Matrix{Float64}, Vector{Int64}} L factor: 3×3 Matrix{Float64}: 1.0 0.0 0.0 -1.0 1.0 0.0 0.0 0.0 1.0 U factor: 3×3 Matrix{Float64}: 1.0 0.0 5.0 0.0 1.0 3.0 0.0 0.0 3.0
Schwach besetzte Matrizen
[Bearbeiten]In der Technik treten häufig große Matrizen auf, die aber nur relativ wenige von Null verschiedene Werte mit Bandstruktur besitzen. Für diese ist es ineffizient, alle Matrizenelemente zu speichern. Effizienter ist es, nur die von Null verschiedenen Elemente zu speichern. Zu diesem Zwecke gibt es das SparseArrays
-Paket.
julia> using SparseArrays julia> ms = sparse([1, 2, 3, 3, 4, 5, 5], [2, 4, 1, 4, 3, 4, 5], [1, 3, 4, 2, 1, 1, 7])
Ausgabe:
⋅ 1 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 3 ⋅ 4 ⋅ ⋅ 2 ⋅ ⋅ ⋅ 1 ⋅ ⋅ ⋅ ⋅ ⋅ 1 7
Spezielle Matrizen
[Bearbeiten]Nachfolgend sollen eine Nullmatrix und eine Matrix mit lauter Einsen generiert werden. Dazu starten wir wieder die Julia-REPL, geben die entsprechenden Befehle ein und erhalten:
julia> zeros(3,2) 3×2 Matrix{Float64}: 0.0 0.0 0.0 0.0 0.0 0.0 julia> ones(3,2) 3×2 Matrix{Float64}: 1.0 1.0 1.0 1.0 1.0 1.0
Insbesondere für Testzwecke kann es manchmal sinnvoll sein größere Matrizen mit Zufallswerten zu bilden. Dazu stellt Julia den rand-Befehl zur Verfügung.
julia> m = rand(5,6) 5×6 Matrix{Float64}: 0.554722 0.7314 0.571432 0.804651 0.192327 0.912537 0.684459 0.748819 0.642302 0.552636 0.671043 0.250012 0.624424 0.722093 0.125511 0.342248 0.398071 0.820795 0.0894763 0.0514967 0.310389 0.96167 0.382739 0.0181225 0.957162 0.365172 0.50859 0.0742012 0.555778 0.512406
Einheitsmatrizen: Man beachte das I
nach der Zahl 1. Die Matrix muss quadratisch sein.
julia> using LinearAlgebra julia> M = 1I + zeros(4,4) 4×4 Matrix{Float64}: 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0
Alternativ:
julia> using LinearAlgebra julia> M = 1I(4) 4×4 Diagonal{Int64, Vector{Int64}}: 1 ⋅ ⋅ ⋅ ⋅ 1 ⋅ ⋅ ⋅ ⋅ 1 ⋅ ⋅ ⋅ ⋅ 1
Diagonalmatrizen, z.B.:
julia> using LinearAlgebra julia> M = 3I + zeros(4,4) 4×4 Matrix{Float64}: 3.0 0.0 0.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0 3.0
Und damit verlassen wir die REPL wieder.
Komplexe Zahlen
[Bearbeiten]Die imaginäre Einheit wird in Julia durch die Buchstabenkombination im
symbolisiert. Darstellen kann man eine komplexe Zahl bekannterweise in mehreren Formen:
- Kartesische Darstellung
- Polardarstellungen
Die konjugiert komplexe Zahl ist
Mit komplexen Zahlen rechnen
[Bearbeiten]z1 = 2 + 5im # kartesische Darstellung z2 = 3 * exp(3im) # Polardarstellung # Addition res = z1 + z2 println("z1 + z2 = ", res) # Multiplikation res = z1 * z2 println("z1 * z2 = ", res) # Realteil res = real(z2) println("Realteil von z2 = ", res) # Imaginärteil res = imag(z2) println("Imaginaerteil von z2 = ", res) # Betrag res = abs(z1) println("Betrag von z1 = ", res) # Argument res = angle(z1) println("Argument von z1 = ", res) # Konjugiert komplexe Zahl res = conj(z1) println("Konjugiert komplexe Zahl von z1 = ", res)
Ausgabe:
z1 + z2 = -0.9699774898013365 + 5.423360024179601im z1 * z2 = -8.05675510050068 - 14.003167400647481im Realteil von z2 = -2.9699774898013365 Imaginaerteil von z2 = 0.4233600241796016 Betrag von z1 = 5.385164807134504 Argument von z1 = 1.1902899496825317 Konjugiert komplexe Zahl von z1 = 2 - 5im
Funktionen
[Bearbeiten]Um Programme zu strukturieren und einfacher zu gestalten können Programmteile in Funktionen ausgelagert werden. Eingebaute Funktionen haben wir schon kennengelernt (z.B. die Sinus-Funktion sin). Nun wollen wir sehen, wie man selbst solche Funktionen schreiben kann.
Eine einfache Funktion schreiben
[Bearbeiten]f(a, b) = a + b println(f(2, 3))
Ausgabe:
5
function
[Bearbeiten]Datei c:\tmp\func.jl
:
function add(a,b) println(a + b) end
Datei c:\tmp\test1.jl
:
include("func.jl") add(5, 11)
Folgendes wird ausgegeben, wenn wir die test1.jl-Datei ausführen
16
Anonyme Funktionen
[Bearbeiten]println(map(a -> 5a + 10, [2, 3]))
Ausgabe:
[20, 25]
return
[Bearbeiten]Datei c:\tmp\func.jl
:
function add(a,b) return a + b end
Datei c:\tmp\test1.jl
:
include("func.jl") println(add(5, 11))
Folgendes wird ausgegeben, wenn wir die test1.jl-Datei ausführen
16
Auch die Rückgabe mehrerer Werte ist möglich.
Datei c:\tmp\func.jl
:
function add(a, b) return a + b, "Addition" end
Datei c:\tmp\test1.jl
:
include("func.jl") x, y = add(10, 20) println(x) println(y)
Ausgabe:
30 Addition
Optionale Argumente
[Bearbeiten]Datei c:\tmp\func.jl
:
function add(a, b = 100) return a + b end
Datei c:\tmp\test1.jl
:
include("func.jl") println(add(5, 11)) println(add(5))
Folgendes wird ausgegeben, wenn wir die test1.jl-Datei ausführen
16 105
Schlüsselwort-Argumente
[Bearbeiten]Datei c:\tmp\func.jl
:
function add(a; b = 100) return a + b end
Man beachte, dass hier zwischen den Argumenten a und b kein Beistrich, sondern ein Semikolon steht.
Datei c:\tmp\test1.jl
:
include("func.jl") println(add(b=16, 5)) println(add(5, b=16)) println(add(5))
Ausgabe:
21 21 105
Polynome
[Bearbeiten]Sofern noch nicht geschehen, fügen Sie das Paket Polynomials
zum Julia-System hinzu.
Ein erstes einfaches Beispiel
[Bearbeiten]using Polynomials println(Polynomial([1, 0, 5, 7]))
Ausgabe:
1 + 5*x^2 + 7*x^3
Einzelne Polynomwerte berechnen
[Bearbeiten]using Polynomials p = Polynomial([1, 0, 5, 7]); println(p(1.5))
Ausgabe:
35.875
Polynome integrieren und differenzieren
[Bearbeiten]using Polynomials p = Polynomial([1, 0, 5, 7]); i = integrate(p) d = derivative(p) println(i) println(d)
Ausgabe:
1.0*x + 1.66667*x^3 + 1.75*x^4 10*x + 21*x^2
Nullstellen bestimmen
[Bearbeiten]using Polynomials p = Polynomial([4, 0, 5, 2]); r = roots(p) println(r)
Ausgabe:
ComplexF64[-2.7621427020576714 + 0.0im, 0.13107135102883646 - 0.8407709868482356im, 0.13107135102883646 + 0.8407709868482356im]
Aufgaben
[Bearbeiten]- Berechnen Sie den Wert für x = 3 des Polynoms .
- Differenzieren und integrieren Sie das Polynom .
- Berechnen Sie die Nullstellen von .
Lineare Gleichungssysteme
[Bearbeiten]Sei ein lineares Gleichungssystem. sei die Koeffizientenmatrix, der Lösungsvektor und ein bekannter Vektor.
Beispiel:
A = [5 1; 0 2] b = [1, 2] x = A \ b println(x)
Ausgabe:
[0.0, 1.0]
Interpolation
[Bearbeiten]Als erstes muss das Interpolations-Paket installiert werden. Wenn Sie nicht wissen, wie man das macht, so sehen Sie unter dem Abschnitt "Grafiken zeichnen" den Absatz "Plots installieren". Dort wird die Vorgehensweise detailliert beschrieben.
Datei "c:\tmp\test1.jl":
using Interpolations using Plots # Stützpunkte xp = 1 : 1 : 5 yp = [0; -5; 2; 7; 6] # Interpolationsfunktionen lspl = LinearInterpolation(xp, yp, extrapolation_bc = Line()) cspl = CubicSplineInterpolation(xp, yp, extrapolation_bc = Line()) # Stützpunkte zeichnen plot(xp,yp,marker=4,linetype=:scatter, label = "Data", title = "Interpolation") # Interpolierende zeichnen x = 1 : .1 : 5 plot!(x, lspl(x), label="Linearer Spline") plot!(x, cspl(x), label="Kubischer Spline") gui() while true end
Ausgabe:
Differenzialrechnung
[Bearbeiten]Symbolische Differenziation
[Bearbeiten]julia> using Calculus julia> differentiate("sin(x)", :x)
Ausgabe:
:(1 * cos(x))
Auswertung:
julia> x = pi/2; julia> round(eval(differentiate("sin(x)", :x)))
Ausgabe:
0.0
Numerische Differenziation
[Bearbeiten]julia> using Calculus julia> derivative("sin", pi/2)
Ausgabe:
0.0
Integralrechnung
[Bearbeiten]julia> using QuadGK julia> integral, err = quadgk(x -> sin(x), 0, pi/2, rtol=1e-8)
Ausgabe:
(0.9999999999999999, 1.1102230246251565e-16)
Im Rahmen der Näherung ist das Resultat richtig (exakt sollte (1.0, 0.0) rauskommen).
Gewöhnliche Differenzialgleichungen
[Bearbeiten]Das Paket DifferentialEquations
ist, wie so viele andere, umfangreich. Hier sei nur ein einfaches Beispiel dargestellt. Für weiterführende Studien sei auf die entsprechenden Weblinks verwiesen.
Folgende Differentialgleichung sei gegeben: .
using DifferentialEquations using Plots f(y, p, x) = x^2 + y^3 problem = ODEProblem(f, 0.0, (0.0, 1.0)) s = solve(problem, Tsit5(), reltol = 1e-8, abstol = 1e-8) plot(s, title = "ODE") gui() while true end
Ausgabe:
Ein- und Ausgabe
[Bearbeiten]Dateien lesen
[Bearbeiten]# Textdatei im aktuellen Verzeichnis öffnen f = open("test1.jl") # Lesen aus Datei lines = readlines(f) # Zeilenweise Ausgabe am Bildschirm for l in lines println("$l") end # Datei schließen close(f)
Als Ausgabe erscheint exakt obiger Source-Code im Terminal.
Dateien schreiben
[Bearbeiten]open("test.txt", "w") do f write(f, "Schreibe eine Zeile in Textdatei\n") end
Der Inhalt der Datei "test.txt" ist dann:
Schreibe eine Zeile in Textdatei
Benutzeroberflächen erstellen
[Bearbeiten]Hier wird nur eine (sehr) kurze Einführung in das Thema GUI mit Gtk (Gimp toolkit, [3]) gegeben. Nähere Details siehe die Gtk.jl-Dokumentation ([4]). Nachfolgend wird ein gegenüber der offiziellen Dokumentation abgewandeltes Beispiel gezeigt. Das ist nötig, um Gtk.jl unter Windows 10 zum Laufen (bzw. um ein Fenster angezeigt) zu bekommen. Das Problem scheint schon seit Langem bekannt zu sein, siehe Gtk.jl, Julia Bindings for Gtk: Gtk Window is not displayed outside the REPL.
using Gtk win = GtkWindow("Hallo Welt", 400, 200) b = GtkButton("Push the button") push!(win,b) c = Condition() endit(w) = notify(c) signal_connect(endit, win, :destroy) showall(win) wait(c)
Ausgabe:
Ein etwas komplizierteres (aber zugegebenerweise noch nicht sehr schönes) Beispiel sei nachfolgend gezeigt. Es sollen zwei Strings miteinander verknüpft und ausgegeben werden.
using Gtk win = GtkWindow("Stringverknüpfung") hbox = GtkBox(:h) push!(win, hbox) e1 = GtkEntry() l1 = GtkLabel("verknüpfe mit") e2 = GtkEntry() b = GtkButton("=") l2 = GtkLabel(" ") push!(hbox, e1) push!(hbox, l1) push!(hbox, e2) push!(hbox, b) push!(hbox, l2) function on_button_clicked(b) GAccessor.text(l2, get_gtk_property(e1, :text, String) * get_gtk_property(e2, :text, String)) end signal_connect(on_button_clicked, b, "clicked") c = Condition() endit(w) = notify(c) signal_connect(endit, win, :destroy) showall(win) wait(c)
Ausgabe (vor der Eingabe der Teilstrings):
Ausgabe (nach der Eingabe der Teilstrings und dem Drücken des =-Buttons):
Ausblick
[Bearbeiten]Dies war eine kurze Einführung in die Berechnungs- und Darstellungsmöglichkeiten mit Julia. Es sollten etliche relevante Themen behandelt, oder zumindest kurz angesprochen worden sein. Wem dieser Text nicht ausreichend ist, der sei auf die entsprechenden weiterführenden Weblinks und die Julia-Hilfefunktion verwiesen. Julia kennt noch viel mehr Befehle, als hier dargestellt wurden. Das Themenspektrum ist auch durch die Einbindung externer Pakete fast beliebig erweiterbar.
Weblinks
[Bearbeiten]- Julia Homepage
- Julia Dokumentation
- Englisches Wikibook zu Julia
- Makie - a data visualization ecosystem for Julia
- Plots - powerful convenience for visualization in Julia
- Numerical Computing in Julia
- Julia Programming Tutorial
- Polynomials.jl
- Calculus.jl
- QuadGK.jl
- DifferentialEquations.jl: Efficient Differential Equation Solving in Julia
- Solving ODEs in Julia
- Gtk.jl