english translation started
This commit is contained in:
@@ -11,96 +11,97 @@ import QuartoNotebookWorker
|
|||||||
Base.stdout = QuartoNotebookWorker.with_context(stdout)
|
Base.stdout = QuartoNotebookWorker.with_context(stdout)
|
||||||
```
|
```
|
||||||
|
|
||||||
# Zeichen, Strings und Unicode
|
# Characters, Strings, and Unicode
|
||||||
|
|
||||||
## Zeichencodierungen (Frühgeschichte)
|
## Character Encodings (Early History)
|
||||||
|
|
||||||
Es gab - abhängig von Hersteller, Land, Programmiersprache, Betriebsssystem,... - eine große Vielzahl von Codierungen.
|
There were - depending on manufacturer, country, programming language, operating system, etc. - a large variety of encodings.
|
||||||
|
|
||||||
Bis heute relevant sind:
|
Still relevant today:
|
||||||
|
|
||||||
|
|
||||||
### ASCII
|
### ASCII
|
||||||
Der _American Standard Code for Information Interchange_ wurde 1963 in den USA als Standard veröffentlicht.
|
The _American Standard Code for Information Interchange_ was published as a standard in the USA in 1963.
|
||||||
|
|
||||||
- Er definiert $2^7=128$ Zeichen, und zwar:
|
- It defines $2^7=128$ characters, namely:
|
||||||
- 33 Steuerzeichen, wie `newline`, `escape`, `end of transmission/file`, `delete`
|
- 33 control characters, such as `newline`, `escape`, `end of transmission/file`, `delete`
|
||||||
- 95 graphisch darstellbare Zeichen:
|
- 95 graphically printable characters:
|
||||||
- 52 lateinische Buchstaben `a-z, A-Z`
|
- 52 Latin letters `a-z, A-Z`
|
||||||
- 10 Ziffern `0-9`
|
- 10 digits `0-9`
|
||||||
- 7 Satzzeichen `.,:;?!"`
|
- 7 punctuation marks `.,:;?!"`
|
||||||
- 1 Leerzeichen ` `
|
- 1 space ` `
|
||||||
- 6 Klammern `[{()}]`
|
- 6 parentheses `[{()}]`
|
||||||
- 7 mathematische Operationen `+-*/<>=`
|
- 7 mathematical operations `+-*/<>=`
|
||||||
- 12 Sonderzeichen ``` #$%&'\^_|~`@ ```
|
- 12 special characters ``` #$%&'\^_|~`@ ```
|
||||||
|
|
||||||
- ASCII ist heute noch der "kleinste gemeinsame Nenner" im Codierungs-Chaos.
|
- ASCII is still the "lowest common denominator" in the encoding chaos.
|
||||||
- Die ersten 128 Unicode-Zeichen sind identisch mit ASCII.
|
- The first 128 Unicode characters are identical to ASCII.
|
||||||
|
|
||||||
### ISO 8859-Zeichensätze
|
### ISO 8859 Character Sets
|
||||||
|
|
||||||
- ASCII nutzt nur 7 Bits.
|
- ASCII uses only 7 bits.
|
||||||
- In einem Byte kann man durch Setzen des 8. Bits weitere 128 Zeichen unterbringen.
|
- In a byte, one can fit another 128 characters by setting the 8th bit.
|
||||||
- 1987/88 wurden im ISO 8859-Standard verschiedene 1-Byte-Codierungen festgelegt, die alle ASCII-kompatibel sind, darunter:
|
- In 1987/88, various 1-byte encodings were standardized in ISO 8859, all ASCII-compatible, including:
|
||||||
|
|
||||||
:::{.narrow}
|
:::{.narrow}
|
||||||
|Codierung | Region | Sprachen|
|
|Encoding | Region | Languages|
|
||||||
|:-----------|:----------|:-------|
|
|:-----------|:----------|:-------|
|
||||||
|ISO 8859-1 (Latin-1) | Westeuropa | Deutsch, Französisch,...,Isländisch
|
|ISO 8859-1 (Latin-1) | Western Europe | German, French,..., Icelandic
|
||||||
|ISO 8859-2 (Latin-2) | Osteuropa | slawische Sprachen mit lateinischer Schrift
|
|ISO 8859-2 (Latin-2) | Eastern Europe | Slavic languages with Latin script
|
||||||
|ISO 8859-3 (Latin-3) | Südeuropa | Türkisch, Maltesisch,...
|
|ISO 8859-3 (Latin-3) | Southern Europe | Turkish, Maltese,...
|
||||||
|ISO 8859-4 (Latin-4) | Nordeuropa | Estnisch, Lettisch, Litauisch, Grönländisch, Sami
|
|ISO 8859-4 (Latin-4) | Northern Europe | Estonian, Latvian, Lithuanian, Greenlandic, Sami
|
||||||
|ISO 8859-5 (Latin/Cyrillic) | Osteuropa | slawische Sprachen mit kyrillischer Schrift
|
|ISO 8859-5 (Latin/Cyrillic) | Eastern Europe | Slavic languages with Cyrillic script
|
||||||
|ISO 8859-6 (Latin/Arabic) | |
|
|ISO 8859-6 (Latin/Arabic) | |
|
||||||
|ISO 8859-7 (Latin/Greek) | |
|
|ISO 8859-7 (Latin/Greek) | |
|
||||||
|...| |
|
|...| |
|
||||||
|ISO 8859-15 (Latin-9)| | 1999: Revision von Latin-1: jetzt u.a. mit Euro-Zeichen
|
|ISO 8859-15 (Latin-9)| | 1999: Revision of Latin-1: now including Euro sign
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
## Unicode
|
## Unicode
|
||||||
|
|
||||||
Das Ziel des Unicode-Consortiums ist eine einheitliche Codierung für alle Schriften der Welt.
|
The goal of the Unicode Consortium is a uniform encoding for all scripts of the world.
|
||||||
|
|
||||||
- Unicode Version 1 erschien 1991
|
- Unicode version 1 was published in 1991
|
||||||
- Unicode Version 15.1 erschien 2023 mit 149 813 Zeichen, darunter:
|
- Unicode version 15.1 was published in 2023 with 149,813 characters, including:
|
||||||
- 161 Schriften
|
- 161 scripts
|
||||||
- mathematische und technische Symbole
|
- mathematical and technical symbols
|
||||||
- Emojis und andere Symbole, Steuer- und Formatierungszeichen
|
- Emojis and other symbols, control and formatting characters
|
||||||
- davon entfallen über 90 000 Zeichen auf die CJK-Schriften (Chinesisch/Japanisch/Koreanisch)
|
- Over 90,000 characters are assigned to the CJK scripts (Chinese/Japanese/Korean)
|
||||||
|
|
||||||
|
|
||||||
### Technische Details
|
### Technical Details
|
||||||
|
|
||||||
- Jedem Zeichen wird ein `codepoint` zugeordnet. Das ist einfach eine fortlaufende Nummer.
|
- Each character is assigned a `codepoint`. This is simply a sequential number.
|
||||||
- Diese Nummer wird hexadezimal notiert
|
- This number is written hexadecimally
|
||||||
- entweder 4-stellig als `U+XXXX` (0-te Ebene)
|
- either 4-digit as `U+XXXX` (0th plane)
|
||||||
- oder 6-stellig als `U+XXXXXX` (weitere Ebenen)
|
- or 6-digit as `U+XXXXXX` (further planes)
|
||||||
- Jede Ebene geht von `U+XY0000` bis `U+XYFFFF`, kann also $2^{16}=65\;534$ Zeichen enthalten.
|
- Each plane ranges from `U+XY0000` to `U+XYFFFF`, thus can contain $2^{16}=65\;534$ characters.
|
||||||
- Vorgesehen sind bisher 17 Ebenen `XY=00` bis `XY=10`, also der Wertebereich von `U+0000` bis `U+10FFFF`.
|
- 17 planes `XY=00` to `XY=10` are provided so far, thus the value range from `U+0000` to `U+10FFFF`.
|
||||||
- Damit sind maximal 21 Bits pro Zeichen nötig.
|
- Thus, a maximum of 21 bits per character are needed.
|
||||||
- Die Gesamtzahl der damit möglichen Codepoints ist etwas kleiner als 0x10FFFF, da aus technischen Gründen gewisse Bereiche nicht verwendet werden. Sie beträgt etwa 1.1 Millionen, es ist also noch viel Platz.
|
- The total number of possible codepoints is slightly less than 0x10FFFF, as certain areas are not used for technical reasons. It is about 1.1 million, so there is still much room.
|
||||||
- Bisher wurden nur Codepoints aus den Ebenen
|
- So far, codepoints from the planes have been assigned only from
|
||||||
- Ebene 0 = BMP _Basic Multilingual Plane_ `U+0000 - U+FFFF`,
|
- Plane 0 = BMP _Basic Multilingual Plane_ `U+0000 - U+FFFF`,
|
||||||
- Ebene 1 = SMP _Supplementary Multilingual Plane_ `U+010000 - U+01FFFF`,
|
- Plane 1 = SMP _Supplementary Multilingual Plane_ `U+010000 - U+01FFFF`,
|
||||||
- Ebene 2 = SIP _Supplementary Ideographic Plane_ `U+020000 - U+02FFFF`,
|
- Plane 2 = SIP _Supplementary Ideographic Plane_ `U+020000 - U+02FFFF`,
|
||||||
- Ebene 3 = TIP _Tertiary Ideographic Plane_ `U+030000 - U+03FFFF` und
|
- Plane 3 = TIP _Tertiary Ideographic Plane_ `U+030000 - U+03FFFF` and
|
||||||
- Ebene 14 = SSP _Supplementary Special-purpose Plane_ `U+0E0000 - U+0EFFFF`
|
- Plane 14 = SSP _Supplementary Special-purpose Plane_ `U+0E0000 - U+0EFFFF`
|
||||||
vergeben.
|
have been assigned.
|
||||||
- `U+0000` bis `U+007F` ist identisch mit ASCII
|
- `U+0000` to `U+007F` is identical to ASCII
|
||||||
- `U+0000` bis `U+00FF` ist identisch mit ISO 8859-1 (Latin-1)
|
- `U+0000` to `U+00FF` is identical to ISO 8859-1 (Latin-1)
|
||||||
|
|
||||||
### Eigenschaften von Unicode-Zeichen
|
### Properties of Unicode Characters
|
||||||
|
|
||||||
Im Standard wird jedes Zeichen beschrieben duch
|
In the standard, each character is described by
|
||||||
|
|
||||||
- seinen Codepoint (Nummer)
|
- its codepoint (number)
|
||||||
- einen Namen (welcher nur aus ASCII-Großbuchstaben, Ziffern und Minuszeichen besteht) und
|
- a name (which consists only of ASCII uppercase letters, digits, and hyphens) and
|
||||||
- verschiedene Attributen wie
|
- various attributes such as
|
||||||
- Laufrichtung der Schrift
|
- script direction
|
||||||
- Kategorie: Großbuchstabe, Kleinbuchstabe, modifizierender Buchstabe, Ziffer, Satzzeichen, Symbol, Seperator,....
|
- category: uppercase letter, lowercase letter, modifier letter, digit, punctuation, symbol, separator,....
|
||||||
|
|
||||||
Im Unicode-Standard sieht das dann so aus (zur Vereinfachung nur Codepoint und Name):
|
In the Unicode standard, this looks like this (simplified, only codepoint and name):
|
||||||
```
|
```
|
||||||
...
|
...
|
||||||
U+0041 LATIN CAPITAL LETTER A
|
U+0041 LATIN CAPITAL LETTER A
|
||||||
@@ -118,29 +119,29 @@ U+21B4 RIGHTWARDS ARROW WITH CORNER DOWNWARDS
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
Wie sieht 'RIGHTWARDS ARROW WITH CORNER DOWNWARDS' aus?
|
What does 'RIGHTWARDS ARROW WITH CORNER DOWNWARDS' look like?
|
||||||
|
|
||||||
Julia verwendet `\U...` zur Eingabe von Unicode Codepoints.
|
Julia uses `\U...` for input of Unicode codepoints.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
'\U21b4'
|
'\U21b4'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Eine Auswahl an Schriften
|
### A Selection of Scripts
|
||||||
|
|
||||||
::: {.content-visible when-format="html"}
|
::: {.content-visible when-format="html"}
|
||||||
|
|
||||||
:::{.callout-note}
|
:::{.callout-note}
|
||||||
Falls im Folgenden einzelne Zeichen oder Schriften in Ihrem Browser nicht darstellbar sind, müssen Sie geeignete
|
If individual characters or scripts are not displayable in your browser, you must install appropriate
|
||||||
Fonts auf Ihrem Rechner installieren.
|
fonts on your computer.
|
||||||
|
|
||||||
Alternativ können Sie die PDF-Version dieser Seite verwenden. Dort sind alle Fonts eingebunden.
|
Alternatively, you can use the PDF version of this page. There, all fonts are embedded.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Eine kleine Hilfsfunktion:
|
A small helper function:
|
||||||
```{julia}
|
```{julia}
|
||||||
function printuc(c, n)
|
function printuc(c, n)
|
||||||
for i in 0:n-1
|
for i in 0:n-1
|
||||||
@@ -149,14 +150,15 @@ function printuc(c, n)
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
__Kyrillisch__
|
__Cyrillic__
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
printuc('\U0400', 100)
|
printuc('\U0400', 100)
|
||||||
```
|
```
|
||||||
|
|
||||||
__Tamilisch__
|
__Tamil__
|
||||||
|
|
||||||
|
|
||||||
:::{.cellmerge}
|
:::{.cellmerge}
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -177,21 +179,21 @@ printuc('\U0be7',20)
|
|||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
__Schach__
|
__Chess__
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
printuc('\U2654', 12)
|
printuc('\U2654', 12)
|
||||||
```
|
```
|
||||||
|
|
||||||
__Mathematische Operatoren__
|
__Mathematical Operators__
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
printuc('\U2200', 255)
|
printuc('\U2200', 255)
|
||||||
```
|
```
|
||||||
|
|
||||||
__Runen__
|
__Runes__
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -200,12 +202,11 @@ printuc('\U16a0', 40)
|
|||||||
|
|
||||||
:::{.cellmerge}
|
:::{.cellmerge}
|
||||||
|
|
||||||
__Scheibe (Diskus) von Phaistos__
|
__Phaistos Disc__
|
||||||
|
|
||||||
- Diese Schrift ist nicht entziffert.
|
|
||||||
- Es ist unklar, welche Sprache dargestellt wird.
|
|
||||||
- Es gibt nur ein einziges Dokument in dieser Schrift: die Tonscheibe von Phaistos aus der Bronzezeit
|
|
||||||
|
|
||||||
|
- This script is not deciphered.
|
||||||
|
- It is unclear what language is represented.
|
||||||
|
- There is only one single document in this script: the Phaistos Disc from the Bronze Age
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -226,54 +227,54 @@ printuc('\U101D0', 46 )
|
|||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### Unicode transformation formats: UTF-8, UTF-16, UTF-32
|
### Unicode Transformation Formats: UTF-8, UTF-16, UTF-32
|
||||||
|
|
||||||
_Unicode transformation formats_ legen fest, wie eine Folge von Codepoints als eine Folge von Bytes dargestellt wird.
|
_Unicode transformation formats_ define how a sequence of codepoints is represented as a sequence of bytes.
|
||||||
|
|
||||||
Da die Codepoints unterschiedlich lang sind, kann man sie nicht einfach hintereinander schreiben. Wo hört einer auf und fängt der nächste an?
|
Since the codepoints are of different lengths, they cannot simply be written down one after the other. Where does one end and the next begin?
|
||||||
|
|
||||||
- __UTF-32__: Das einfachste, aber auch speicheraufwändigste, ist, sie alle auf gleiche Länge zu bringen. Jeder Codepoint wird in 4 Bytes = 32 Bit kodiert.
|
- __UTF-32__: The simplest but also most memory-intensive is to make them all the same length. Each codepoint is encoded in 4 bytes = 32 bits.
|
||||||
- Bei __UTF-16__ wird ein Codepoint entweder mit 2 Bytes oder mit 4 Bytes dargestellt.
|
- In __UTF-16__, a codepoint is represented either with 2 bytes or with 4 bytes.
|
||||||
- Bei __UTF-8__ wird ein Codepoint mit 1,2,3 oder 4 Bytes dargestellt.
|
- In __UTF-8__, a codepoint is represented with 1, 2, 3, or 4 bytes.
|
||||||
- __UTF-8__ ist das Format mit der höchsten Verbreitung. Es wird auch von Julia verwendet.
|
- __UTF-8__ is the format with the highest prevalence. Julia also uses it.
|
||||||
|
|
||||||
|
|
||||||
### UTF-8
|
### UTF-8
|
||||||
|
|
||||||
- Für jeden Codepoint werden 1, 2, 3 oder 4 volle Bytes verwendet.
|
- For each codepoint, 1, 2, 3, or 4 full bytes are used.
|
||||||
|
|
||||||
- Bei einer Codierung mit variabler Länge muss man erkennen können, welche Bytefolgen zusammengehören:
|
- With variable-length encoding, one must be able to recognize which byte sequences belong together:
|
||||||
- Ein Byte der Form 0xxxxxxx steht für einen ASCII-Codepoint der Länge 1.
|
- A byte of the form 0xxxxxxx represents an ASCII codepoint of length 1.
|
||||||
- Ein Byte der Form 110xxxxx startet einen 2-Byte-Code.
|
- A byte of the form 110xxxxx starts a 2-byte code.
|
||||||
- Ein Byte der Form 1110xxxx startet einen 3-Byte-Code.
|
- A byte of the form 1110xxxx starts a 3-byte code.
|
||||||
- Ein Byte der Form 11110xxx startet einen 4-Byte-Code.
|
- A byte of the form 11110xxx starts a 4-byte code.
|
||||||
- Alle weiteren Bytes eines 2-,3- oder 4-Byte-Codes haben die Form 10xxxxxx.
|
- All further bytes of a 2-, 3-, or 4-byte code have the form 10xxxxxx.
|
||||||
|
|
||||||
- Damit ist der Platz, der für den Codepoint zur Verfügung steht (Anzahl der x):
|
- Thus, the space available for the codepoint (number of x):
|
||||||
- Ein-Byte-Code: 7 Bits
|
- One-byte code: 7 bits
|
||||||
- Zwei-Byte-Code: 5 + 6 = 11 Bits
|
- Two-byte code: 5 + 6 = 11 bits
|
||||||
- Drei-Byte-Code: 4 + 6 + 6 = 16 Bits
|
- Three-byte code: 4 + 6 + 6 = 16 bits
|
||||||
- Vier-Byte-Code: 3 + 6 + 6 + 6 = 21 Bits
|
- Four-byte code: 3 + 6 + 6 + 6 = 21 bits
|
||||||
|
|
||||||
- Damit ist jeder ASCII-Text automatisch auch ein korrekt codierter UTF-8-Text.
|
- Thus, every ASCII text is automatically also a correctly encoded UTF-8 text.
|
||||||
|
|
||||||
- Sollten die bisher für Unicode festgelegten 17 Ebenen (= 21 Bit = 1.1 Mill. mögliche Zeichen) mal erweitert werden, dann wird UTF-8 auf 5- und 6-Byte-Codes erweitert.
|
- If the 17 planes (= 21 bits = 1.1 million possible characters) defined for Unicode so far are ever expanded, UTF-8 will be expanded to 5- and 6-byte codes.
|
||||||
|
|
||||||
|
|
||||||
## Zeichen und Zeichenketten in Julia
|
## Characters and Character Strings in Julia
|
||||||
|
|
||||||
### Zeichen: `Char`
|
### Characters: `Char`
|
||||||
|
|
||||||
Der Datentyp `Char` kodiert ein einzelnes Unicode-Zeichen.
|
The `Char` type encodes a single Unicode character.
|
||||||
|
|
||||||
- Julia verwendet dafür einfache Anführungszeichen: `'a'`.
|
- Julia uses single quotes for this: `'a'`.
|
||||||
- Ein `Char` belegt 4 Bytes Speicher und
|
- A `Char` occupies 4 bytes of memory and
|
||||||
- repräsentiert einen Unicode-Codepoint.
|
- represents a Unicode codepoint.
|
||||||
- `Char`s können von/zu `UInt`s umgewandelt werden und
|
- `Char`s can be converted to/from `UInt`s and
|
||||||
- der Integer-Wert ist gleich dem Unicode-codepoint.
|
- the integer value is equal to the Unicode codepoint.
|
||||||
|
|
||||||
|
|
||||||
`Char`s können von/zu `UInt`s umgewandelt werden.
|
`Char`s can be converted to/from `UInt`s.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
UInt('a')
|
UInt('a')
|
||||||
@@ -284,10 +285,10 @@ UInt('a')
|
|||||||
b = Char(0x2656)
|
b = Char(0x2656)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Zeichenketten: `String`
|
### Character Strings: `String`
|
||||||
|
|
||||||
- Für Strings verwendet Julia doppelte Anführungszeichen: `"a"`.
|
- For strings, Julia uses double quotes: `"a"`.
|
||||||
- Sie sind UTF-8-codiert, d.h., ein Zeichen kann zwischen 1 und 4 Bytes lang sein.
|
- They are UTF-8 encoded, i.e., one character can be between 1 and 4 bytes long.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -297,21 +298,21 @@ b = Char(0x2656)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
__Bei einem Nicht-ASCII-String unterscheiden sich Anzahl der Bytes und Anzahl der Zeichen:__
|
__For a non-ASCII string, the number of bytes and the number of characters differ:__
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
asciistr = "Hello World!"
|
asciistr = "Hello World!"
|
||||||
@show length(asciistr) ncodeunits(asciistr);
|
@show length(asciistr) ncodeunits(asciistr);
|
||||||
```
|
```
|
||||||
(Das Leerzeichen zählt natürlich auch.)
|
(The space, of course, also counts.)
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
str = "😄 Hellö 🎶"
|
str = "😄 Hellö 🎶"
|
||||||
@show length(str) ncodeunits(str);
|
@show length(str) ncodeunits(str);
|
||||||
```
|
```
|
||||||
|
|
||||||
__Iteration über einen String iteriert über die Zeichen:__
|
__Iterating over a string iterates over the characters:__
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -320,76 +321,76 @@ for i in str
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
### Verkettung von Strings
|
### Concatenation of Strings
|
||||||
|
|
||||||
"Strings mit Verkettung bilden ein nichtkommutatives Monoid."
|
"Strings with concatenation form a non-commutative monoid."
|
||||||
|
|
||||||
Deshalb wird in Julia die Verkettung multiplikativ geschrieben.
|
Therefore, Julia writes concatenation multiplicatively.
|
||||||
```{julia}
|
```{julia}
|
||||||
str * asciistr * str
|
str * asciistr * str
|
||||||
```
|
```
|
||||||
|
|
||||||
Damit sind auch Potenzen mit natürlichem Exponenten definiert.
|
Powers with natural exponents are thus also defined.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
str^3, str^0
|
str^3, str^0
|
||||||
```
|
```
|
||||||
|
|
||||||
### Stringinterpolation
|
### String Interpolation
|
||||||
|
|
||||||
Das Dollarzeichen hat in Strings eine Sonderfunktion, die wir schon oft in
|
The dollar sign has a special function in strings, which we have often used in
|
||||||
`print()`-Anweisungen genutzt haben. MAn kann damit eine Variable oder einen Ausdruck interpolieren:
|
`print()` statements. One can interpolate a variable or expression with it:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
a = 33.4
|
a = 33.4
|
||||||
b = "x"
|
b = "x"
|
||||||
|
|
||||||
s = "Das Ergebnis für $b ist gleich $a und die verdoppelte Wurzel daraus ist $(2sqrt(a))\n"
|
s = "The result for $b is equal to $a and the doubled square root of it is $(2sqrt(a))\n"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Backslash escape sequences
|
### Backslash Escape Sequences
|
||||||
|
|
||||||
Der _backslash_ `\` hat in Stringkonstanten ebenfalls eine Sonderfunktion.
|
The _backslash_ `\` also has a special function in string constants.
|
||||||
Julia benutzt die von C und anderen Sprachen bekannten _backslash_-Codierungen für Sonderzeichen und für Dollarzeichen und Backslash selbst:
|
Julia uses the backslash codings known from C and other languages for special characters and for dollar signs and backslashes themselves:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
s = "So bekommt man \'Anführungszeichen\" und ein \$-Zeichen und einen\nZeilenumbruch und ein \\ usw... "
|
s = "This is how one gets \'quotes\" and a \$ sign and a\nline break and a \\ etc... "
|
||||||
print(s)
|
print(s)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Triple-Quotes
|
### Triple Quotes
|
||||||
|
|
||||||
Man kann Strings auch mit Triple-Quotes begrenzen.
|
Strings can also be delimited with triple quotes.
|
||||||
In dieser Form bleiben Zeilenumbrüche und Anführungszeichen erhalten:
|
In this form, line breaks and quotes are preserved:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
s = """
|
s = """
|
||||||
Das soll
|
This should
|
||||||
ein "längerer"
|
be a "longer"
|
||||||
'Text' sein.
|
'text'.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
print(s)
|
print(s)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Raw strings
|
### Raw Strings
|
||||||
|
|
||||||
In einem `raw string` sind alle backslash-Codierungen außer `\"` abgeschaltet:
|
In a `raw string`, all backslash codings except `\"` are disabled:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
s = raw"Ein $ und ein \ und zwei \\ und ein 'bla'..."
|
s = raw"A $ and a \ and two \\ and a 'bla'..."
|
||||||
print(s)
|
print(s)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Weitere Funktionen für Zeichen und Strings (Auswahl)
|
## Further Functions for Characters and Strings (Selection)
|
||||||
|
|
||||||
### Tests für Zeichen
|
### Tests for Characters
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -397,9 +398,9 @@ print(s)
|
|||||||
@show isnumeric('½') iscntrl('\n') ispunct(';');
|
@show isnumeric('½') iscntrl('\n') ispunct(';');
|
||||||
```
|
```
|
||||||
|
|
||||||
### Anwendung auf Strings
|
### Application to Strings
|
||||||
|
|
||||||
Diese Tests lassen sich z.B. mit `all()`, `any()` oder `count()` auf Strings anwenden:
|
These tests can e.g. be used with `all()`, `any()`, or `count()` on strings:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -408,7 +409,7 @@ all(ispunct, ";.:")
|
|||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
any(isdigit, "Es ist 3 Uhr! 🕒" )
|
any(isdigit, "It is 3 o'clock! 🕒" )
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -416,7 +417,7 @@ any(isdigit, "Es ist 3 Uhr! 🕒" )
|
|||||||
count(islowercase, "Hello, du!!")
|
count(islowercase, "Hello, du!!")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Weitere String-Funktionen
|
### Other String Functions
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -438,50 +439,50 @@ count(islowercase, "Hello, du!!")
|
|||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
split("π ist irrational.")
|
split("π is irrational.")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
replace("π ist irrational.", "ist" => "ist angeblich")
|
replace("π is irrational.", "is" => "is allegedly")
|
||||||
```
|
```
|
||||||
|
|
||||||
## Indizierung von Strings
|
## Indexing of Strings
|
||||||
|
|
||||||
Strings sind nicht mutierbar aber indizierbar. Dabei gibt es ein paar Besonderheiten.
|
Strings are immutable but indexable. There are a few special features here.
|
||||||
|
|
||||||
- Der Index nummeriert die Bytes des Strings.
|
- The index numbers the bytes of the string.
|
||||||
- Bei einem nicht-ASCII-String sind nicht alle Indizes gültig, denn
|
- For a non-ASCII string, not all indices are valid, because
|
||||||
- ein gültiger Index adressiert immer ein Unicode-Zeichen.
|
- a valid index always addresses a Unicode character.
|
||||||
|
|
||||||
Unser Beispielstring:
|
Our example string:
|
||||||
```{julia}
|
```{julia}
|
||||||
str
|
str
|
||||||
```
|
```
|
||||||
|
|
||||||
Das erste Zeichen
|
The first character
|
||||||
```{julia}
|
```{julia}
|
||||||
str[1]
|
str[1]
|
||||||
```
|
```
|
||||||
|
|
||||||
Dieses Zeichen ist in UTF8-Kodierung 4 Bytes lang. Damit sind 2,3 und 4 ungültige Indizes.
|
This character is 4 bytes long in UTF-8 encoding. Thus, 2, 3, and 4 are invalid indices.
|
||||||
```{julia}
|
```{julia}
|
||||||
str[2]
|
str[2]
|
||||||
```
|
```
|
||||||
|
|
||||||
Erst das 5. Byte ist ein neues Zeichen:
|
Only the 5th byte is a new character:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
str[5]
|
str[5]
|
||||||
```
|
```
|
||||||
|
|
||||||
Auch bei der Adressierung von Substrings müssen Anfang und Ende jeweils gültige Indizes sein, d.h., der Endindex muss ebenfalls das erste Byte eines Zeichens indizieren und dieses Zeichen ist das letzte des Teilstrings.
|
Even when addressing substrings, start and end must always be valid indices, i.e., the end index must also index the first byte of a character, and that character is the last of the substring.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
str[1:7]
|
str[1:7]
|
||||||
```
|
```
|
||||||
|
|
||||||
Die Funktion `eachindex()` liefert einen Iterator über die gültigen Indizes:
|
The function `eachindex()` returns an iterator over the valid indices:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
for i in eachindex(str)
|
for i in eachindex(str)
|
||||||
@@ -490,24 +491,24 @@ for i in eachindex(str)
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Wie üblich macht collect() aus einem Iterator einen Vektor.
|
As usual, `collect()` makes an iterator into a vector.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
collect(eachindex(str))
|
collect(eachindex(str))
|
||||||
```
|
```
|
||||||
|
|
||||||
Die Funktion `nextind()` liefert den nächsten gültigen Index.
|
The function `nextind()` returns the next valid index.
|
||||||
```{julia}
|
```{julia}
|
||||||
@show nextind(str, 1) nextind(str, 2);
|
@show nextind(str, 1) nextind(str, 2);
|
||||||
```
|
```
|
||||||
|
|
||||||
Warum verwendet Julia einen Byte-Index und keinen Zeichenindex? Der Hauptgrund dürfte die Effizienz der Indizierung sein.
|
Why does Julia use a byte index instead of a character index? The main reason is the efficiency of indexing.
|
||||||
|
|
||||||
- In einem langen String, z.B. einem Buchtext, ist die Stelle `s[123455]` mit einem Byte-Index schnell zu finden.
|
- In a long string, e.g., a book text, the position `s[123455]` can be found quickly with a byte index.
|
||||||
- Ein Zeichen-Index müsste in der UTF-8-Codierung den ganzen String durchlaufen, um das n-te Zeichen zu finden, da die Zeichen 1,2,3 oder 4 Bytes lang sein können.
|
- A character index would have to traverse the entire string in UTF-8 encoding to find the n-th character, since the characters can be 1, 2, 3, or 4 bytes long.
|
||||||
|
|
||||||
|
|
||||||
Einige Funktionen liefern Indizes oder Ranges als Resultat. Sie liefern immer gültige Indizes:
|
Some functions return indices or ranges as results. They always return valid indices:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -529,9 +530,8 @@ str2 = "αβγδϵ"^3
|
|||||||
n = findfirst('γ', str2)
|
n = findfirst('γ', str2)
|
||||||
```
|
```
|
||||||
|
|
||||||
So kann man ab dem nächsten nach `n=5` gültigen Index weitersuchen:
|
So one can continue searching from the next valid index after `n=5`:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
findnext('γ', str2, nextind(str2, n))
|
findnext('γ', str2, nextind(str2, n))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ engine: julia
|
|||||||
using InteractiveUtils
|
using InteractiveUtils
|
||||||
```
|
```
|
||||||
|
|
||||||
# Lineare Algebra in Julia
|
# Linear Algebra in Julia
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using LinearAlgebra
|
using LinearAlgebra
|
||||||
```
|
```
|
||||||
|
|
||||||
Das `LinearAlgebra`-Paket liefert unter anderem:
|
The `LinearAlgebra` package provides among other things:
|
||||||
|
|
||||||
- zusätzliche Subtypen von `AbstractMatrix`: genauso verwendbar, wie andere Matrizen, z.B.
|
- additional subtypes of `AbstractMatrix`: usable like other matrices, e.g.,
|
||||||
|
|
||||||
- `Tridiagonal`
|
- `Tridiagonal`
|
||||||
- `SymTridiagonal`
|
- `SymTridiagonal`
|
||||||
@@ -25,26 +25,26 @@ Das `LinearAlgebra`-Paket liefert unter anderem:
|
|||||||
- `UpperTriangular`
|
- `UpperTriangular`
|
||||||
|
|
||||||
|
|
||||||
- zusätzliche/erweiterte Funktionen: `norm`, `opnorm`, `cond`, `inv`, `det`, `exp`, `tr`, `dot`, `cross`, ...
|
- additional/extended functions: `norm`, `opnorm`, `cond`, `inv`, `det`, `exp`, `tr`, `dot`, `cross`, ...
|
||||||
|
|
||||||
- einen universellen Solver für lineare Gleichungssysteme: `\`
|
- a universal solver for systems of linear equations: `\`
|
||||||
- `x = A \ b` löst $A \mathbf{x}=\mathbf{b}$ durch geeignete Matrixfaktorisierung und Vorwärts/Rückwärtssubstition
|
- `x = A \ b` solves $A \mathbf{x}=\mathbf{b}$ by appropriate matrix factorization and forward/backward substitution
|
||||||
|
|
||||||
- [Matrixfaktorisierungen](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#man-linalg-factorizations)
|
- [Matrix factorizations](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#man-linalg-factorizations)
|
||||||
- `LU`
|
- `LU`
|
||||||
- `QR`
|
- `QR`
|
||||||
- `Cholesky`
|
- `Cholesky`
|
||||||
- `SVD`
|
- `SVD`
|
||||||
- ...
|
- ...
|
||||||
|
|
||||||
- Berechnung von Eigenwerte/-vektoren
|
- Computation of eigenvalues/eigenvectors
|
||||||
|
|
||||||
- `eigen`, `eigvals`, `eigvecs`
|
- `eigen`, `eigvals`, `eigvecs`
|
||||||
|
|
||||||
|
|
||||||
- Zugriff auf BLAS/LAPACK-Funktionen
|
- Access to BLAS/LAPACK functions
|
||||||
|
|
||||||
## Matrixtypen
|
## Matrix Types
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -57,31 +57,31 @@ A = SymTridiagonal(fill(1.0, 4), fill(-0.3, 3))
|
|||||||
B = UpperTriangular(A)
|
B = UpperTriangular(A)
|
||||||
```
|
```
|
||||||
|
|
||||||
Diese Typen werden platzsparend gespeichert. Die üblichen Rechenoperationen sind implementiert:
|
These types are stored space-efficiently. The usual arithmetic operations are implemented:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
A + B
|
A + B
|
||||||
```
|
```
|
||||||
|
|
||||||
Lesende Indexzugriffe sind möglich,
|
Read-only index access is possible,
|
||||||
```{julia}
|
```{julia}
|
||||||
A[1,4]
|
A[1,4]
|
||||||
```
|
```
|
||||||
|
|
||||||
schreibende nicht unbedingt:
|
write operations not necessarily:
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: true
|
#| error: true
|
||||||
A[1,3] = 17
|
A[1,3] = 17
|
||||||
```
|
```
|
||||||
|
|
||||||
Die Umwandlung in eine 'normale' Matrix ist z.B. mit `collect()` möglich:
|
Conversion to a 'normal' matrix is possible, for example, with `collect()`:
|
||||||
```{julia}
|
```{julia}
|
||||||
A2 = collect(A)
|
A2 = collect(A)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Die Einheitsmatrix `I`
|
### The Identity Matrix `I`
|
||||||
|
|
||||||
`I` bezeichnet eine Einheitsmatrix (quadratisch, Diagonalelemente = 1, alle anderen = 0) in der jeweils erforderlichen Größe
|
`I` denotes an identity matrix (square, diagonal elements = 1, all others = 0) of the respective required size
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -89,39 +89,39 @@ A + 4I
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Normen
|
## Norms
|
||||||
|
|
||||||
Um Fragen wie Kondition oder Konvergenz eines Algorithmus studieren zu können, brauchen wir eine Metrik. Für lineare Räume ist es zweckmäßig, die Metrik über eine Norm zu definieren:
|
To be able to study questions such as conditioning or convergence of an algorithm, we need a metric. For linear spaces, it is appropriate to define the metric via a norm:
|
||||||
$$
|
$$
|
||||||
d(x,y) := ||x-y||
|
d(x,y) := ||x-y||
|
||||||
$$
|
$$
|
||||||
|
|
||||||
### $p$-Normen
|
### $p$-Norms
|
||||||
|
|
||||||
Eine einfache Klasse von Normen im $ℝ^n$ sind die $p$-Normen
|
A simple class of norms in $ℝ^n$ are the $p$-norms
|
||||||
$$
|
$$
|
||||||
||\mathbf{x}||_p = \left(\sum |x_i|^p\right)^\frac{1}{p},
|
||\mathbf{x}||_p = \left(\sum |x_i|^p\right)^\frac{1}{p},
|
||||||
$$
|
$$
|
||||||
die die die euklidische Norm $p=2$ verallgemeinern.
|
which generalize the Euclidean norm $p=2$.
|
||||||
|
|
||||||
|
|
||||||
:::{.callout-note}
|
:::{.callout-note}
|
||||||
|
|
||||||
## Die Max-Norm $p=\infty$
|
## The Max-Norm $p=\infty$
|
||||||
|
|
||||||
Sei $x_{\text{max}}$ die _betragsmäßig_ größte Komponente von $\mathbf{x}\in ℝ^n$. Dann gilt stets
|
Let $x_{\text{max}}$ be the _largest in absolute value_ component of $\mathbf{x}\in ℝ^n$. Then always
|
||||||
$$ |x_{\text{max}}| \le ||\mathbf{x}||_p \le n^\frac{1}{p} |x_{\text{max}}|
|
$$ |x_{\text{max}}| \le ||\mathbf{x}||_p \le n^\frac{1}{p} |x_{\text{max}}|
|
||||||
$$
|
$$
|
||||||
(Man betrachte einen Vektor, dessen Komponenten alle gleich $x_{\text{max}}$ sind bzw. einen Vektor, dessen Komponenten außer $x_{\text{max}}$ alle gleich Null sind.)
|
(Consider a vector whose components are all equal to $x_{\text{max}}$ respectively a vector whose components are all equal to zero except $x_{\text{max}}$.)
|
||||||
|
|
||||||
Damit folgt
|
Thus follows
|
||||||
$$
|
$$
|
||||||
\lim_{p \rightarrow \infty} ||\mathbf{x}||_p = |x_{\text{max}}| =: ||\mathbf{x}||_\infty.
|
\lim_{p \rightarrow \infty} ||\mathbf{x}||_p = |x_{\text{max}}| =: ||\mathbf{x}||_\infty.
|
||||||
$$
|
$$
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
In Julia definiert das `LinearAlgebra`-Paket eine Funktion `norm(v, p)`.
|
In Julia, the `LinearAlgebra` package defines a function `norm(v, p)`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
v = [3, 4]
|
v = [3, 4]
|
||||||
@@ -130,10 +130,10 @@ w = [-1, 2, 33.2]
|
|||||||
@show norm(v) norm(v, 2) norm(v, 1) norm(v, 4) norm(w, Inf);
|
@show norm(v) norm(v, 2) norm(v, 1) norm(v, 4) norm(w, Inf);
|
||||||
```
|
```
|
||||||
|
|
||||||
- Wenn das 2. Argument `p` fehlt, wird `p=2` gesetzt.
|
- If the 2nd argument `p` is missing, `p=2` is set.
|
||||||
- Das 2. Argument kann auch `Inf` (also $+\infty$) sein.
|
- The 2nd argument can also be `Inf` (i.e., $+\infty$).
|
||||||
- Das 1. Argument kann ein beliebiger Container voller Zahlen sein. Die Summe $\sum |x_i|^p$ erstreckt sich über *alle* Elemente des Containers.
|
- The 1st argument can be any container full of numbers. The sum $\sum |x_i|^p$ extends over *all* elements of the container.
|
||||||
- Damit ist für eine Matrix `norm(A)` gleich der _Frobenius-Norm_ der Matrix `A`.
|
- Thus, for a matrix `norm(A)` is equal to the _Frobenius norm_ of the matrix `A`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
A = [1 2 3
|
A = [1 2 3
|
||||||
@@ -144,12 +144,12 @@ norm(A) # Frobenius norm
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Da Normen homogen unter Multiplikation mit Skalaren sind,
|
Since norms are homogeneous under multiplication with scalars,
|
||||||
$||\lambda \mathbf{x}|| = |\lambda|\cdot||\mathbf{x}||$, sind sie durch die Angabe der Einheitskugel vollständig bestimmt. Subadditivität der Norm (Dreiecksungleichung) ist äquivalent zur Konvexität der Einheitskugel
|
$||\lambda \mathbf{x}|| = |\lambda|\cdot||\mathbf{x}||$, they are completely determined by the specification of the unit ball. Subadditivity of the norm (triangle inequality) is equivalent to the convexity of the unit ball
|
||||||
(Code durch anklicken sichtbar).
|
(code visible by clicking).
|
||||||
```{julia}
|
```{julia}
|
||||||
#| code-fold: true
|
#| code-fold: true
|
||||||
#| fig-cap: "Einheitskugeln im $ℝ^2$ für verschiedene $p$-Normen: $p$=0.8; 1; 1.5; 2; 3.001 und 1000"
|
#| fig-cap: "Unit balls in $ℝ^2$ for different $p$-norms: $p$=0.8; 1; 1.5; 2; 3.001 and 1000"
|
||||||
using Plots
|
using Plots
|
||||||
|
|
||||||
colors=[:purple, :green, :red, :blue,:aqua, :black]
|
colors=[:purple, :green, :red, :blue,:aqua, :black]
|
||||||
@@ -163,35 +163,35 @@ for p ∈ (0.8, 1, 1.5, 2, 3.001, 1000)
|
|||||||
end
|
end
|
||||||
fig1
|
fig1
|
||||||
```
|
```
|
||||||
Wie man sieht, muß $p\ge 1$ sein, damit die Einheitskugel konvex und $||.||_p$ eine Norm ist.
|
As one can see, $p\ge 1$ must hold so that the unit ball is convex and $||.||_p$ is a norm.
|
||||||
|
|
||||||
Die Julia-Funktion `norm(v, p)` liefert allerdings für beliebige Parameter `p` ein Ergebnis.
|
However, the Julia function `norm(v, p)` returns a result for arbitrary parameters `p`.
|
||||||
|
|
||||||
|
|
||||||
### Induzierte Normen (Operatornormen)
|
### Induced Norms (Operator Norms)
|
||||||
|
|
||||||
Matrizen $A$ repräsentieren lineare Abbildungen $\mathbf{v}\mapsto A\mathbf{v}$. Die von einer Vektornorm Induzierte Matrixnorm beantwortet die Frage:
|
Matrices $A$ represent linear mappings $\mathbf{v}\mapsto A\mathbf{v}$. The matrix norm induced by a vector norm answers the question:
|
||||||
|
|
||||||
> _„Um welchen Faktor kann ein Vektor durch die Transformation $A$ maximal gestreckt werden?“_
|
> _"By what factor can a vector be maximally stretched by the transformation $A$?"_
|
||||||
|
|
||||||
Auf Grund der Homogenität der Norm unter Multiplikation mit Skalaren reicht es aus, das Bild der Einheitskugel unter der Transformation $A$ zu betrachten.
|
Due to the homogeneity of the norm under multiplication with scalars, it is sufficient to consider the image of the unit ball under the transformation $A$.
|
||||||
|
|
||||||
::: {.callout-tip}
|
::: {.callout-tip}
|
||||||
## Definition
|
## Definition
|
||||||
Sei $V$ ein Vektorraum mit einer Dimension $0<n<\infty$ und
|
Let $V$ be a vector space with dimension $0<n<\infty$ and
|
||||||
$A$ eine $n\times n$-Matrix. Dann ist
|
$A$ an $n\times n$-matrix. Then
|
||||||
$$
|
$$
|
||||||
||A||_p = \max_{||\mathbf{v}||_p=1} ||A\mathbf{v}||_p
|
||A||_p = \max_{||\mathbf{v}||_p=1} ||A\mathbf{v}||_p
|
||||||
$$
|
$$
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Induzierte Normen lassen sich für allgemeines $p$ nur schwer berechnen. Ausnahmen sind die Fälle
|
Induced norms can only be calculated with difficulty for general $p$. Exceptions are the cases
|
||||||
|
|
||||||
- $p=1$: Spaltensummennorm
|
- $p=1$: column sum norm
|
||||||
- $p=2$: Spektralnorm und
|
- $p=2$: spectral norm and
|
||||||
- $p=\infty$: Zeilensummennorm
|
- $p=\infty$: row sum norm
|
||||||
|
|
||||||
Diese 3 Fälle sind in Julia in der Funktion `opnorm(A, p)` aus dem `LinearAlgebra`-Paket implementiert, wobei wieder `opnorm(A) = opnorm(A, 2)` gilt.
|
These 3 cases are implemented in Julia in the function `opnorm(A, p)` from the `LinearAlgebra` package, where again `opnorm(A) = opnorm(A, 2)` holds.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
A = [ 0 1
|
A = [ 0 1
|
||||||
@@ -200,7 +200,7 @@ A = [ 0 1
|
|||||||
@show opnorm(A, 1) opnorm(A, Inf) opnorm(A, 2) opnorm(A);
|
@show opnorm(A, 1) opnorm(A, Inf) opnorm(A, 2) opnorm(A);
|
||||||
```
|
```
|
||||||
|
|
||||||
Das folgende Bild zeigt die Wirkung von $A$ auf Einheitsvektoren. Vektoren gleicher Farbe werden aufeinander abgebildet. (Code durch anklicken sichtbar):
|
The following picture shows the effect of $A$ on unit vectors. Vectors of the same color are mapped onto each other. (Code visible by clicking):
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: false
|
#| error: false
|
||||||
@@ -214,12 +214,12 @@ CairoMakie.activate!(type = "svg")
|
|||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| code-fold: true
|
#| code-fold: true
|
||||||
#| fig-cap: "Bild der Einheitskugel unter $v \\mapsto Av$ mit $||A||\\approx 2.088$"
|
#| fig-cap: "Image of the unit ball under $v \\mapsto Av$ with $||A||\\approx 2.088$"
|
||||||
|
|
||||||
using CairoMakie
|
using CairoMakie
|
||||||
|
|
||||||
# Makie bug https://github.com/MakieOrg/Makie.jl/issues/3255
|
# Makie bug https://github.com/MakieOrg/Makie.jl/issues/3255
|
||||||
# Würgaround https://github.com/MakieOrg/Makie.jl/issues/2607#issuecomment-1385816645
|
# Workaround https://github.com/MakieOrg/Makie.jl/issues/2607#issuecomment-1385816645
|
||||||
tri = BezierPath([
|
tri = BezierPath([
|
||||||
MoveTo(Point2f(-0.5, -1)), LineTo(0, 0), LineTo(0.5, -1), ClosePath()
|
MoveTo(Point2f(-0.5, -1)), LineTo(0, 0), LineTo(0.5, -1), ClosePath()
|
||||||
])
|
])
|
||||||
@@ -253,9 +253,9 @@ arrows!(fig2[1,3], x, y, Auv[1], Auv[2], arrowsize=10, arrowhead=tri, colormap=:
|
|||||||
fig2
|
fig2
|
||||||
```
|
```
|
||||||
|
|
||||||
### Konditionszahl
|
### Condition Number
|
||||||
|
|
||||||
Für p = 1, p = 2 (default) oder p = Inf liefert `cond(A,p)` die Konditionszahl in der $p$-Norm
|
For p = 1, p = 2 (default) or p = Inf, `cond(A,p)` returns the condition number in the $p$-norm
|
||||||
$$
|
$$
|
||||||
\text{cond}_p(A) = ||A||_p \cdot ||A^{-1}||_p
|
\text{cond}_p(A) = ||A||_p \cdot ||A^{-1}||_p
|
||||||
$$
|
$$
|
||||||
@@ -264,37 +264,37 @@ $$
|
|||||||
@show cond(A, 1) cond(A, 2) cond(A) cond(A, Inf);
|
@show cond(A, 1) cond(A, 2) cond(A) cond(A, Inf);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Matrixfaktorisierungen
|
## Matrix Factorizations
|
||||||
|
|
||||||
Basisaufgaben der numerischen linearen Algebra:
|
Basic tasks of numerical linear algebra:
|
||||||
|
|
||||||
- Löse ein lineares Gleichungssystem $A\mathbf{x} = \mathbf{b}$.
|
- Solve a system of linear equations $A\mathbf{x} = \mathbf{b}$.
|
||||||
- Falls keine Lösung existiert, finde die beste Annäherung, d.h., den Vektor $\mathbf{x}$, der $||A\mathbf{x} - \mathbf{b}||$ minimiert.
|
- If no solution exists, find the best approximation, i.e., the vector $\mathbf{x}$ that minimizes $||A\mathbf{x} - \mathbf{b}||$.
|
||||||
- Finde Eigenwerte und Eigenvektoren $A\mathbf{x} = \lambda \mathbf{x}$ von $A$.
|
- Find eigenvalues and eigenvectors $A\mathbf{x} = \lambda \mathbf{x}$ of $A$.
|
||||||
|
|
||||||
Diese Aufgaben sind mit Matrixfaktorisierungen lösbar. Einige grundlegende Matrixfaktorisierungen:
|
These tasks can be solved using matrix factorizations. Some fundamental matrix factorizations:
|
||||||
|
|
||||||
- **LU-Zerlegung** $A=L\cdot U$
|
- **LU decomposition** $A=L\cdot U$
|
||||||
- faktorisiert eine Matrix als Produkt einer _lower_ und einer _upper_ Dreiecksmatrix
|
- factorizes a matrix as a product of a _lower_ and an _upper_ triangular matrix
|
||||||
- im Deutschen auch LR-Zerlegung (aber die Julia-Funktion heisst `lu()`)
|
- in German also called LR decomposition (but the Julia function is called `lu()`)
|
||||||
- geht (eventuell nach Zeilenvertauschung - Pivoting) immer
|
- always works (possibly after row exchanges - pivoting)
|
||||||
- **Cholesky-Zerlegung** $A=L\cdot L^*$
|
- **Cholesky decomposition** $A=L\cdot L^*$
|
||||||
- die obere Dreiecksmatrix ist die konjugierte der unteren,
|
- the upper triangular matrix is the conjugate of the lower,
|
||||||
- halber Aufwand im Vergleich zu LU
|
- half the effort compared to LU
|
||||||
- geht nur, wenn $A$ hermitesch und positiv definit ist
|
- only works if $A$ is Hermitian and positive definite
|
||||||
- **QR-Zerlegung** $A=Q\cdot R$
|
- **QR decomposition** $A=Q\cdot R$
|
||||||
- zerlegt $A$ als Produkt einer orthogonalen (bzw. unitären im komplexen Fall) Matrix und einer oberen Dreiecksmatrix
|
- decomposes $A$ as a product of an orthogonal (or unitary in the complex case) matrix and an upper triangular matrix
|
||||||
- $Q$ ist längenerhaltend (Drehungen und/oder Spiegelungen); die Stauchungen/Streckungen werden durch $R$ beschrieben
|
- $Q$ is length-preserving (rotations and/or reflections); the scalings are described by $R$
|
||||||
- geht immer
|
- always works
|
||||||
- **SVD** _(Singular value decomposition)_: $A = U\cdot D \cdot V^*$
|
- **SVD** _(Singular value decomposition)_: $A = U\cdot D \cdot V^*$
|
||||||
- $U$ und $V$ sind orthogonal (bzw. unitär), $D$ ist eine Diagonalmatrix mit Einträgen in der Diagonale $σ_i\ge 0$, den sogenannten _Singulärwerten_ von $A$.
|
- $U$ and $V$ are orthogonal (or unitary), $D$ is a diagonal matrix with entries on the diagonal $σ_i\ge 0$, the so-called _singular values_ of $A$.
|
||||||
- Jede lineare Transformation $\mathbf{v} \mapsto A\mathbf{v}$ läßt sich somit darstellen als eine Drehung (und/oder Spiegelung) $V^*$, gefolgt von einer reinen Skalierung $v_i \mapsto \sigma_i v_i$ und einer weitere Drehung $U$.
|
- Every linear transformation $\mathbf{v} \mapsto A\mathbf{v}$ can thus be represented as a rotation (and/or reflection) $V^*$, followed by a pure scaling $v_i \mapsto \sigma_i v_i$ and another rotation $U$.
|
||||||
|
|
||||||
|
|
||||||
### LU-Faktorisierung
|
### LU Factorization
|
||||||
|
|
||||||
LU-Faktorisierung ist Gauß-Elimination. Das Resultat der Gauß-Elimination ist die obere Dreiecksmatrix $U$. Die untere Dreiecksmatrix $L$ enthält Einsen auf der Diagonale und die nichtdiagonalen Einträge $l_{ij}$ sind gleich minus den Koeffizienten, mit denen im Gauß-Algorithmus Zeile $Z_j$ multipliziert und zu Zeile $Z_i$ addiert wird.
|
LU factorization is Gaussian elimination. The result of Gaussian elimination is the upper triangular matrix $U$. The lower triangular matrix $L$ contains ones on the diagonal and the non-diagonal entries $l_{ij}$ are equal to minus the coefficients by which row $Z_j$ is multiplied and added to row $Z_i$ in the Gaussian algorithm.
|
||||||
Ein Beispiel:
|
An example:
|
||||||
$$
|
$$
|
||||||
A=\left[
|
A=\left[
|
||||||
\begin{array}{ccc}
|
\begin{array}{ccc}
|
||||||
@@ -342,11 +342,11 @@ A = \left[
|
|||||||
$$
|
$$
|
||||||
|
|
||||||
|
|
||||||
- Häufig in der Praxis: $A\mathbf{x}=\mathbf{b}$ muss für ein $A$ und viele rechte Seiten $\mathbf{b}$ gelöst werden.
|
- Often in practice: $A\mathbf{x}=\mathbf{b}$ must be solved for one $A$ and many right-hand sides $\mathbf{b}$.
|
||||||
- Die Faktorisierung, deren Aufwand kubisch $\sim n^3$ mit der Matrixgröße $n$ wächst, muss nur einmal gemacht werden.
|
- The factorization, whose effort grows cubically $\sim n^3$ with the matrix size $n$, only needs to be done once.
|
||||||
- Der anschliessende Aufwand der Vorwärts/Rückwärtssubstition für jedes $\mathbf{b}$ ist nur noch quadratisch $\sim n^2$.
|
- The subsequent effort of forward/backward substitution for each $\mathbf{b}$ is only quadratically $\sim n^2$.
|
||||||
|
|
||||||
Das `LinearAlgebra`-Paket von Julia enthält zur Berechnung einer LU-Zerlegung die Funktion `lu(A, options)`:
|
The `LinearAlgebra` package of Julia contains the function `lu(A, options)` for calculating an LU decomposition:
|
||||||
```{julia}
|
```{julia}
|
||||||
A = [ 1 2 2
|
A = [ 1 2 2
|
||||||
3 -4 4
|
3 -4 4
|
||||||
@@ -361,7 +361,7 @@ display(U)
|
|||||||
|
|
||||||
#### Pivoting
|
#### Pivoting
|
||||||
|
|
||||||
Sehen wir uns einen Schritt der Gauß-Elimination an:
|
Let's look at one step of Gaussian elimination:
|
||||||
$$
|
$$
|
||||||
\left[
|
\left[
|
||||||
\begin{array}{cccccc}
|
\begin{array}{cccccc}
|
||||||
@@ -375,37 +375,34 @@ $$
|
|||||||
\end{array}
|
\end{array}
|
||||||
\right]
|
\right]
|
||||||
$$
|
$$
|
||||||
Ziel ist es, als nächstes den Eintrag $a_{i+1,j}$ zum Verschwinden zu bringen, indem zur Zeile $Z_{i+1}$ ein geeignetes Vielfaches von Zeile $Z_i$ addiert wird. Das geht nur, wenn das _Pivotelement_ $\textcolor{red}{a_{ij}}$ nicht Null ist. Falls $\textcolor{red}{a_{ij}}=0$, müssen wir Zeilen vertauschen um dies zu beheben.
|
The goal is to make the entry $a_{i+1,j}$ disappear by adding an appropriate multiple of row $Z_i$ to row $Z_{i+1}$. This only works if the _pivot element_ $\textcolor{red}{a_{ij}}$ is not zero. If $\textcolor{red}{a_{ij}}=0$, we must exchange rows to fix this.
|
||||||
|
|
||||||
Darüber hinaus ist die Kondition des Algorithmus am besten, wenn man bei jedem Schritt die Matrix so anordnet, dass das Pivotelement das betragsmäßig größte
|
Furthermore, the conditioning of the algorithm is best if we arrange the matrix at each step so that the pivot element is the largest in absolute value in the corresponding column of the remaining submatrix. In (row) pivoting, rows are exchanged at each step to ensure that
|
||||||
in der entsprechenden Spalte der noch zu bearbeitenden Umtermatrix ist. Beim (Zeilen-)Pivoting wird bei jedem Schritt durch Zeilenvertauschung sichergestellt, dass
|
|
||||||
gilt:
|
|
||||||
$$
|
$$
|
||||||
|\textcolor{red}{a_{ij}}|=\max_{k=i,...,m} |\textcolor{blue}{a_{kj}}|
|
|\textcolor{red}{a_{ij}}|=\max_{k=i,...,m} |\textcolor{blue}{a_{kj}}|
|
||||||
$$
|
$$
|
||||||
|
|
||||||
#### LU in Julia
|
#### LU in Julia
|
||||||
|
|
||||||
- Die Faktorisierungen in Julia geben ein spezielles Objekt zurück, das die Matrixfaktoren und weitere
|
- The factorizations in Julia return a special object that contains the matrix factors and additional information.
|
||||||
Informationen enthält.
|
- The Julia function `lu(A)` performs an LU factorization with pivoting.
|
||||||
- Die Julia-Funktion `lu(A)` führt eine LU-Faktorisierung mit Pivoting durch.
|
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
F = lu(A)
|
F = lu(A)
|
||||||
typeof(F)
|
typeof(F)
|
||||||
```
|
```
|
||||||
Elemente des Objekts:
|
Elements of the object:
|
||||||
```{julia}
|
```{julia}
|
||||||
@show F.L F.U F.p;
|
@show F.L F.U F.p;
|
||||||
```
|
```
|
||||||
Man kann auch gleich auf der linken Seite ein entsprechendes Tupel verwenden:
|
One can also use an appropriate tuple on the left side:
|
||||||
```{julia}
|
```{julia}
|
||||||
L, U, p = lu(A);
|
L, U, p = lu(A);
|
||||||
p
|
p
|
||||||
```
|
```
|
||||||
|
|
||||||
Der Permutationsvektor zeigt an, wie die Zeilen der Matrix permutiert wurden. Es gilt: $$ L\cdot U = PA$$. Die Syntax der indirekten Indizierung erlaubt es, die Zeilenpermutation durch die Schreibweise `A[p,:]` anzuwenden:
|
The permutation vector indicates how the rows of the matrix have been permuted. It holds: $$ L\cdot U = PA$$. The syntax of indirect indexing allows applying the row permutation with the notation `A[p,:]`:
|
||||||
```{julia}
|
```{julia}
|
||||||
display(A)
|
display(A)
|
||||||
display(A[p,:])
|
display(A[p,:])
|
||||||
@@ -413,28 +410,28 @@ display(L*U)
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Die Vorwärts/Rückwärtssubstition mit einem `LU`- erledigt der Operator `\`:
|
Forward/backward substitution with an `LU`-object is performed by the `\` operator:
|
||||||
```{julia}
|
```{julia}
|
||||||
b = [1, 2, 3]
|
b = [1, 2, 3]
|
||||||
x = F \ b
|
x = F \ b
|
||||||
```
|
```
|
||||||
Probe:
|
Verification:
|
||||||
```{julia}
|
```{julia}
|
||||||
A * x - b
|
A * x - b
|
||||||
```
|
```
|
||||||
|
|
||||||
In Julia verbirgt sich hinter dem `\`-Operator ein ziemlich universeller "matrix solver" und man kann ihn auch direkt anwenden:
|
In Julia, the `\` operator hides a quite universal "matrix solver", and it can also be applied directly:
|
||||||
```{julia}
|
```{julia}
|
||||||
A \ b
|
A \ b
|
||||||
```
|
```
|
||||||
Dabei wird implizit eine geeignete Faktorisierung durchgeführt, deren Ergebnis allerdings nicht abgespeichert.
|
An appropriate factorization is performed implicitly, but its result is not saved.
|
||||||
|
|
||||||
|
|
||||||
### QR-Zerlegung
|
### QR Decomposition
|
||||||
|
|
||||||
|
|
||||||
Die Funktion `qr()` liefert ein epezielles QR-Objekt zurück, das die Komponenten $Q$ und $R$ enthält. Die orthogonale (bzw. unitäre) Matrix $Q$ ist
|
The function `qr()` returns a special QR object that contains the components $Q$ and $R$. The orthogonal (or unitary) matrix $Q$ is
|
||||||
[in einer optimierten Form](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#man-linalg-abstractq) abgespeichert. Umwandlung in eine "normale" Matrix ist bei Bedarf wie immer mit `collect()` möglich.
|
[in an optimized form](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#man-linalg-abstractq) stored. Conversion to a "normal" matrix is, as always, possible with `collect()` if needed.
|
||||||
```{julia}
|
```{julia}
|
||||||
F = qr(A)
|
F = qr(A)
|
||||||
@show typeof(F) typeof(F.Q)
|
@show typeof(F) typeof(F.Q)
|
||||||
@@ -442,11 +439,11 @@ display(collect(F.Q))
|
|||||||
display(F.R)
|
display(F.R)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Passende Faktorisierung
|
### Appropriate Factorization
|
||||||
|
|
||||||
|
|
||||||
Die Funktion `factorize()` liefert eine dem Matrixtyp angepasste Form der Faktorisierung, siehe [Dokumentation](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#LinearAlgebra.factorize) für Details.
|
The function `factorize()` returns a factorization form adapted to the matrix type, see [documentation](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#LinearAlgebra.factorize) for details.
|
||||||
Wenn man Lösungen zu mehreren rechten Seiten $\mathbf{b_1}, \mathbf{b_2},...$ benötigt, sollte man die Faktorisierung nur einmal durchführen:
|
If solutions for several right-hand sides $\mathbf{b_1}, \mathbf{b_2},...$ are needed, the factorization should only be performed once:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -462,4 +459,3 @@ Af \ [1, 2, 3]
|
|||||||
```{julia}
|
```{julia}
|
||||||
Af \ [5, 7, 9]
|
Af \ [5, 7, 9]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,23 @@
|
|||||||
engine: julia
|
engine: julia
|
||||||
---
|
---
|
||||||
|
|
||||||
# Ein- und Ausgabe
|
```{julia}
|
||||||
|
#| error: false
|
||||||
|
#| echo: false
|
||||||
|
#| output: false
|
||||||
|
using InteractiveUtils
|
||||||
|
import QuartoNotebookWorker
|
||||||
|
Base.stdout = QuartoNotebookWorker.with_context(stdout)
|
||||||
|
```
|
||||||
|
|
||||||
|
```{julia}
|
||||||
|
#| error: false
|
||||||
|
#| echo: false
|
||||||
|
#| output: false
|
||||||
|
flush(stdout)
|
||||||
|
```
|
||||||
|
|
||||||
|
# Input and Output
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -22,51 +38,50 @@ Base.active_module() = myactive_module()
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Konsole
|
## Console
|
||||||
|
|
||||||
Das Betriebssystem stellt für ein Programm üblicherweise 3 Kanäle _(streams)_ zur Verfügung:
|
The operating system normally provides 3 channels (_streams_) for a program:
|
||||||
|
|
||||||
- Standardeingabekanal `stdin`
|
- Standard input channel `stdin`
|
||||||
- Standardausgabekanal `stdout` und
|
- Standard output channel `stdout` and
|
||||||
- Standardfehlerausgabekanal `stderr`.
|
- Standard error output channel `stderr`.
|
||||||
|
|
||||||
Wenn das Programm in einem Terminal (oder Konsole bzw. Shell) gestartet wird, kann das Programm über `stdin` die Tastatureingaben
|
When the program is started in a terminal (or console or shell), the program can read keyboard input via `stdin` and output appears in the terminal via `stdout` and `stdout`.
|
||||||
einlesen und Ausgaben über `stdout` sowie `stdout` erscheinen im Terminal.
|
|
||||||
|
|
||||||
|
|
||||||
- Schreiben nach `stdout`: `print()`,`println()`,`printstyled()`
|
- Writing to `stdout`: `print()`,`println()`,`printstyled()`
|
||||||
- Schreiben nach `stderr`: `print(strerr,...)`, `println(stderr,...)`, `printstyled(stderr,...)`
|
- Writing to `stderr`: `print(strerr,...)`, `println(stderr,...)`, `printstyled(stderr,...)`
|
||||||
- Lesen von `stdin`: `readline()`
|
- Reading from `stdin`: `readline()`
|
||||||
|
|
||||||
|
|
||||||
### Eingaben
|
### Input
|
||||||
|
|
||||||
Die Sprache _Python_ stellt eine Funktion `input()` zur Verfügung:
|
The language _Python_ provides a function `input()`:
|
||||||
```{.python}
|
```{.python}
|
||||||
ans = input("Bitte eine positive Zahl eingeben!")
|
ans = input("Please enter a positive number!")
|
||||||
```
|
```
|
||||||
Die Funktion gibt den Prompt aus, wartet auf eine Eingabe und liefert die
|
The function prints the prompt, waits for input, and returns the
|
||||||
Eingabe als `string` zurück.
|
input as a `string`.
|
||||||
|
|
||||||
|
|
||||||
In Julia kann man diese Funktion so implementieren:
|
In Julia, you can implement this function as follows:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
function input(prompt = "Eingabe:")
|
function input(prompt = "Input:")
|
||||||
println(prompt)
|
println(prompt)
|
||||||
flush(stdout)
|
flush(stdout)
|
||||||
return chomp(readline())
|
return chomp(readline())
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
**Anmerkungen**
|
**Comments**
|
||||||
|
|
||||||
- Schreibanweisungen werden von modernen Betriebssystemen gebuffert. Mit `flush(stdout)` wird die Leerung des Buffers und sofortige Schreiboperation erzwungen.
|
- Write instructions are buffered by modern operating systems. With `flush(stdout)`, the buffer is emptied and the write operation is forced to complete immediately.
|
||||||
- `readline()` liefert einen String zurück, der mit einer Newline `\n` endet. Die Funktion `chomp()` entfernt einen eventuellen Zeilenumbruch vom Ende eines Strings.
|
- `readline()` returns a string ending with a newline `\n`. The function `chomp()` removes a possible line break from the end of a string.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| eval: false
|
#| eval: false
|
||||||
a = input("Bitte 2 Zahlen eingeben!")
|
a = input("Please enter 2 numbers!")
|
||||||
```
|
```
|
||||||
```{julia}
|
```{julia}
|
||||||
#| echo: false
|
#| echo: false
|
||||||
@@ -74,32 +89,33 @@ a = "34 56"
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Verarbeitung der Eingabe
|
### Processing the Input
|
||||||
|
|
||||||
> `split(str)` zerlegt einen String in "Wörter" und liefert einen _(array of strings)_:
|
> `split(str)` splits a string into "words" and returns an _(array of strings)_:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
av = split(a)
|
av = split(a)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
> `parse(T, str)` versucht, `str` in den Typ `T` umzuwandeln:
|
> `parse(T, str)` tries to convert `str` to type `T`:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
v = parse.(Int, av)
|
v = parse.(Int, av)
|
||||||
```
|
```
|
||||||
|
|
||||||
`parse()` erzeugt einen Fehler, wenn der String sich nicht als Wertangabe von Typ `T` parsen lässt. Man kann den Fehler mit
|
`parse()` generates an error if the string cannot be parsed as a value of type `T`. You can catch the error with
|
||||||
`try/catch` abfangen oder die Funktion `tryparse(T, str)` verwenden, die in so einem Fall `nothing` zurückgibt - worauf man dann
|
`try/catch` or use the function `tryparse(T, str)`, which returns `nothing` in such a case - on which you can then
|
||||||
z.B. mit `isnothing()` testen kann.
|
e.g. test with `isnothing()`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Einzelne Tastenanschläge einlesen
|
|
||||||
|
|
||||||
- `readline()` u.ä. warten auf den Abschluss der Eingabe durch Drücken der `Enter`-Taste.
|
### Reading Individual Keystrokes
|
||||||
- Techniken zum Einlesen einzelner _keystrokes_ findet man hier:
|
|
||||||
|
- `readline()` and similar functions wait for the input to be completed by pressing the `Enter` key.
|
||||||
|
- Techniques for reading individual _keystrokes_ can be found here:
|
||||||
|
|
||||||
- [https://stackoverflow.com/questions/56888266/how-to-read-keyboard-inputs-at-every-keystroke-in-julia](https://stackoverflow.com/questions/56888266/how-to-read-keyboard-inputs-at-every-keystroke-in-julia)
|
- [https://stackoverflow.com/questions/56888266/how-to-read-keyboard-inputs-at-every-keystroke-in-julia](https://stackoverflow.com/questions/56888266/how-to-read-keyboard-inputs-at-every-keystroke-in-julia)
|
||||||
- [https://stackoverflow.com/questions/60954235/how-can-i-test-whether-stdin-has-input-available-in-julia](https://stackoverflow.com/questions/60954235/how-can-i-test-whether-stdin-has-input-available-in-julia)
|
- [https://stackoverflow.com/questions/60954235/how-can-i-test-whether-stdin-has-input-available-in-julia](https://stackoverflow.com/questions/60954235/how-can-i-test-whether-stdin-has-input-available-in-julia)
|
||||||
@@ -107,30 +123,30 @@ z.B. mit `isnothing()` testen kann.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Formatierte Ausgabe mit dem `Printf`-Makro
|
## Formatted Output with the `Printf` Macro
|
||||||
|
|
||||||
Oft möchte man Zahlen oder Strings mit einer strikten Formatvorgabe - Gesamtlänge, Nachkommastellen, rechts/linksbündig usw - ausgeben.
|
Often you want to output numbers or strings with a strict format specification - total length, decimal places, right/left-aligned, etc.
|
||||||
|
|
||||||
Dazu definiert das Paket `Printf` die Makros `@sprintf` und `@printf`, welche sehr ähnlich wie die gleichnamigen C-Funktionen arbeiten.
|
To this end, the `Printf` package defines the macros `@sprintf` and `@printf`, which work very similarly to the corresponding C functions.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using Printf
|
using Printf
|
||||||
|
|
||||||
x = 123.7876355638734
|
x = 123.7876355638734
|
||||||
|
|
||||||
@printf("Ausgabe rechtsbündig mit max. 10 Zeichen Platz und 3 Nachkommastellen: x= %10.3f", x)
|
@printf("Output right-aligned with max. 10 character width and 3 decimal places: x= %10.3f", x)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Das erste Argument ist ein String, der Platzhalter (hier: `%10.3`) für auszugebende Variablen enthält; gefolgt von diesen Variablen als weitere Argumente.
|
The first argument is a string containing placeholders (here: `%10.3`) for variables to be output; followed by these variables as further arguments.
|
||||||
|
|
||||||
Platzhalter haben die Form
|
Placeholders have the form
|
||||||
```
|
```
|
||||||
%[flags][width][.precision]type
|
%[flags][width][.precision]type
|
||||||
```
|
```
|
||||||
wobei die Angaben in eckigen Klammern alle optional sind.
|
where the entries in square brackets are all optional.
|
||||||
|
|
||||||
**Typangaben im Platzhalter**
|
**Type specifications in placeholders**
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|:--|:------------|
|
|:--|:------------|
|
||||||
@@ -149,9 +165,9 @@ wobei die Angaben in eckigen Klammern alle optional sind.
|
|||||||
|
|
||||||
| | |
|
| | |
|
||||||
|:----|:-----|
|
|:----|:-----|
|
||||||
|Pluszeichen| rechtsbündig (Standard)|
|
|Plus sign| right-aligned (default)|
|
||||||
|Minuszeichen| linksbündig|
|
|Minus sign| left-aligned|
|
||||||
|Null| mit führenden Nullen|
|
|Zero| with leading zeros|
|
||||||
|
|
||||||
: {.striped .hover}
|
: {.striped .hover}
|
||||||
|
|
||||||
@@ -159,37 +175,37 @@ wobei die Angaben in eckigen Klammern alle optional sind.
|
|||||||
**Width**
|
**Width**
|
||||||
|
|
||||||
```
|
```
|
||||||
Anzahl der minimal verwendeten Zeichen (wenn nötig, werden auch mehr genommen)
|
Number of minimum characters used (more will be taken if necessary)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Beispiele:
|
### Examples:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using Printf # Paket laden nicht vergessen!
|
using Printf # Don't forget to load the package!
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@printf("|%s|", "Hallo") # string mit Platzhalter für String
|
@printf("|%s|", "Hello") # string with placeholder for string
|
||||||
```
|
```
|
||||||
Die senkrechten Striche sind nicht Teil des Platzhalters. Sie sollen die Begrenzung des Ausgabefeldes anzeigen.
|
The vertical bars are not part of the placeholder. They are intended to indicate the boundaries of the output field.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@printf("|%10s|", "Hallo") # Minimallänge, rechtsbündig
|
@printf("|%10s|", "Hello") # Minimum length, right-aligned
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@printf("|%-10s|", "Hallo") # linksbündig
|
@printf("|%-10s|", "Hello") # left-aligned
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@printf("|%3s|", "Hallo") # Längenangabe kann überschritten werden
|
@printf("|%3s|", "Hello") # Length specification can be exceeded
|
||||||
# besser eine 'kaputt formatierte' Tabelle als falsche Werte!
|
# Better a 'badly formatted' table than incorrect values!
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -198,37 +214,36 @@ j = 123
|
|||||||
k = 90019001
|
k = 90019001
|
||||||
l = 3342678
|
l = 3342678
|
||||||
|
|
||||||
@printf("j= %012i, k= %-12i, l = %12i", j, k, l) # 0-Flag für führende Nullen
|
@printf("j= %012i, k= %-12i, l = %12i", j, k, l) # 0-flag for leading zeros
|
||||||
```
|
```
|
||||||
|
|
||||||
`@printf` und `@sprintf` können wie alle Makros wie Funktionen aufgerufen werden:
|
`@printf` and `@sprintf` can be called like functions or as macros:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@printf("%i %i", 22, j)
|
@printf("%i %i", 22, j)
|
||||||
```
|
```
|
||||||
|
|
||||||
-- oder wie Makros, also ohne Funktionsklammern und ohne Komma:
|
-- or as macros, i.e., without function parentheses and without comma:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@printf "%i %i" 22 j
|
@printf "%i %i" 22 j
|
||||||
```
|
```
|
||||||
|
|
||||||
`@printf` kann als erstes Argument noch einen Stream übergeben bekommen.
|
`@printf` can take a stream as its first argument.
|
||||||
|
|
||||||
Ansonsten besteht die Argumentliste aus
|
Otherwise, the argument list consists of
|
||||||
|
|
||||||
- Formatstring mit Platzhaltern
|
- format string with placeholders
|
||||||
- Variablen in der Reihenfolge der Platzhalter, in Anzahl und Typ zu den Platzhaltern passend
|
- variables in the order of the placeholders, matching in number and type to the placeholders
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@printf(stderr, "Erstes Resultat: %i %s\nZweites Resultat %i",
|
@printf(stderr, "First result: %i %s\nSecond result %i",
|
||||||
j, "(geschätzt)" ,k)
|
j, "(estimated)" ,k)
|
||||||
```
|
```
|
||||||
|
|
||||||
Das Makro `@sprintf` druckt nichts, sondern liefert den ausgefüllten formatierten String zurück:
|
The macro `@sprintf` does not print anything but returns the filled formatted string:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -240,52 +255,52 @@ str = @sprintf("x = %10.6f", π );
|
|||||||
str
|
str
|
||||||
```
|
```
|
||||||
|
|
||||||
### Formatierung der Gleitkommazahlen:
|
### Formatting Floating Point Numbers:
|
||||||
|
|
||||||
Bedeutung des _Precision_-Wertes:
|
Meaning of the _precision_ value:
|
||||||
|
|
||||||
- `%f` und `%e`-Format: maximale Anzahl der Nachkommastellen
|
- `%f` and `%e` format: maximum number of decimal places
|
||||||
- `%g`-Format: maximale Anzahl von ausgegebenen Ziffern (Vor- + Nachkommastellen)
|
- `%g` format: maximum number of digits output (integer + decimal places)
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 123456.7890123456
|
x = 123456.7890123456
|
||||||
|
|
||||||
@printf("%20.4f %20.4e", x, x) # 4 Nachkommastellen
|
@printf("%20.4f %20.4e", x, x) # 4 decimal places
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@printf("%20.7f %20.7e", x, x) # 7 Nachkommastellen
|
@printf("%20.7f %20.7e", x, x) # 7 decimal places
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@printf("%20.7g %20.4g", x, x) # insgesamt 7 bzw. 4 Stellen
|
@printf("%20.7g %20.4g", x, x) # total 7 and 4 digits respectively
|
||||||
```
|
```
|
||||||
|
|
||||||
## Dateioperationen
|
## File Operations
|
||||||
|
|
||||||
Dateien werden
|
Files are
|
||||||
|
|
||||||
- geöffnet $\Longrightarrow$ dabei ensteht ein neues _stream_-Objekt (zusätzlich zu `stdin, stdout, stderr`)
|
- opened $\Longrightarrow$ a new _stream_-object is created (in addition to `stdin, stdout, stderr`)
|
||||||
- dann kann dieser _stream_ gelesen und geschrieben werden
|
- then this _stream_ can be read from and written to
|
||||||
- geschlossen $\Longrightarrow$ _stream_-Objekt wird von Datei getrennt
|
- closed $\Longrightarrow$ _stream_-object is detached from file
|
||||||
|
|
||||||
```{.julia}
|
```{.julia}
|
||||||
stream = open(path, mode)
|
stream = open(path, mode)
|
||||||
```
|
```
|
||||||
|
|
||||||
- path: Dateiname/pfad
|
- path: filename/path
|
||||||
- mode:
|
- mode:
|
||||||
|
|
||||||
```
|
```
|
||||||
"r" read, öffnet am Dateianfang
|
"r" read, opens at file beginning
|
||||||
"w" write, öffnet am Dateianfang (Datei wird neu angelegt oder überschrieben)
|
"w" write, opens at file beginning (file is created or overwritten)
|
||||||
"a" append, öffnet zum Weiterschreiben am Dateiende
|
"a" append, opens to continue writing at file end
|
||||||
```
|
```
|
||||||
|
|
||||||
Schreiben wir mal eine Datei:
|
Let's write a file:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
file = open("datei.txt", "w")
|
file = open("datei.txt", "w")
|
||||||
@@ -298,7 +313,7 @@ file = open("datei.txt", "w")
|
|||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
println(file, " zweite Zeile")
|
println(file, " second line")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -306,59 +321,58 @@ println(file, " zweite Zeile")
|
|||||||
close(file)
|
close(file)
|
||||||
```
|
```
|
||||||
|
|
||||||
Schauen wir uns die Datei an:
|
Let's look at the file:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
;cat datei.txt
|
;cat datei.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
...und jetzt öffnen wir sie wieder zum Einlesen:
|
...and now we open it again for reading:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
stream = open("datei.txt", "r")
|
stream = open("datei.txt", "r")
|
||||||
```
|
```
|
||||||
|
|
||||||
`readlines(stream)` liefert alle Zeilen einer Textdatei als Vector von Strings.
|
`readlines(stream)` returns all lines of a text file as a vector of strings.
|
||||||
|
|
||||||
`eachline(stream)` liefert einen Iterator über die Zeilen der Datei.
|
`eachline(stream)` returns an iterator over the lines of the file.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
n = 0
|
n = 0
|
||||||
for line in eachline(stream) # Lese zeilenweise
|
for line in eachline(stream) # Read line by line
|
||||||
n += 1
|
n += 1
|
||||||
println(n, line) # Drucke mit Zeilennummer
|
println(n, line) # Print with line number
|
||||||
end
|
end
|
||||||
close(stream)
|
close(stream)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Pakete für Dateiformate
|
## Packages for File Formats
|
||||||
|
|
||||||
Für die Ein- und Ausgabe in den verschiedensten Dateiformaten existieren Julia-Pakete, z.B.
|
For input and output in various file formats, there are Julia packages, e.g.,
|
||||||
|
|
||||||
- [PrettyTables.jl](https://ronisbr.github.io/PrettyTables.jl/stable/) Ausgabe von formatierten Tabellen
|
- [PrettyTables.jl](https://ronisbr.github.io/PrettyTables.jl/stable/) Output of formatted tables
|
||||||
- [DelimitedFiles.jl](https://docs.julialang.org/en/v1/stdlib/DelimitedFiles/) Ein- und Ausgabe von Matrizen u.ä.
|
- [DelimitedFiles.jl](https://docs.julialang.org/en/v1/stdlib/DelimitedFiles/) Input and output of matrices, etc.
|
||||||
- [CSV.jl](https://csv.juliadata.org/stable/) Ein- und Ausgabe von Dateien mit "comma-separated values" u.ä.
|
- [CSV.jl](https://csv.juliadata.org/stable/) Input and output of "comma-separated values" files, etc.
|
||||||
- [XLSX.jl](https://felipenoris.github.io/XLSX.jl/stable/tutorial/) Ein- und Ausgabe von Excel-Dateien
|
- [XLSX.jl](https://felipenoris.github.io/XLSX.jl/stable/tutorial/) Input and output of Excel files
|
||||||
|
|
||||||
und viele andere mehr...
|
and many more...
|
||||||
|
|
||||||
### DelimitedFiles.jl
|
### DelimitedFiles.jl
|
||||||
|
|
||||||
Dieses Paket ermöglicht das bequeme Abspeichern/Einlesen von Matrizen. Dazu stellt es die Funktionen `writedlm()` und `readdlm()` zur
|
This package enables convenient saving/reading of matrices. It provides the functions `writedlm()` and `readdlm()`.
|
||||||
Verfügung.
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using DelimitedFiles
|
using DelimitedFiles
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Wir erzeugen eine 200×3-Matrix von Zufallszahlen
|
We generate a 200×3 matrix of random numbers
|
||||||
```{julia}
|
```{julia}
|
||||||
A = rand(200,3)
|
A = rand(200,3)
|
||||||
```
|
```
|
||||||
|
|
||||||
und speichern diese
|
and save it
|
||||||
```{julia}
|
```{julia}
|
||||||
f = open("data2.txt", "w")
|
f = open("data2.txt", "w")
|
||||||
writedlm(f, A)
|
writedlm(f, A)
|
||||||
@@ -366,23 +380,23 @@ close(f)
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Die geschriebene Datei fängt so an:
|
The written file starts like this:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
;head data2.txt
|
;head data2.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Das Wiedereinlesen ist noch einfacher:
|
Reading it back is even simpler:
|
||||||
```{julia}
|
```{julia}
|
||||||
B = readdlm("data2.txt")
|
B = readdlm("data2.txt")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Noch ein Punkt: Beim Umgang mit Dateien wird in Julia oft die `do`-Notation verwendet, s. @sec-do.
|
One more point: In Julia, the `do` notation is often used for file handling, see @sec-do.
|
||||||
Dazu nutzt man, dass `open()` auch Methoden hat, bei denen das 1. Argument eine `function(iostream)` ist.
|
This uses the fact that `open()` also has methods where the 1st argument is a `function(iostream)`.
|
||||||
Diese wird dann auf den _stream_ angewendet und dieser abschliessend automatisch geschlossen. Die `do`-Notation erlaubt es,
|
This function is then applied to the _stream_ and the stream is automatically closed at the end. The `do` notation allows you to
|
||||||
diese Funktion anonym nach dem `do` zu definieren:
|
define this function anonymously after the `do`:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
open("data2.txt", "w") do io
|
open("data2.txt", "w") do io
|
||||||
@@ -390,18 +404,16 @@ open("data2.txt", "w") do io
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
### CSV und DataFrames
|
### CSV and DataFrames
|
||||||
|
|
||||||
- Das CSV-Format wird oft benutzt, um Tabellen in einer nicht nur mit MS Excel lesbaren Form zur Verfügung zu stellen.
|
|
||||||
- Ein Beispiel ist die Wetter- und Klimadatenbank _Meteostat_.
|
|
||||||
- Das Paket [DataFrames.jl](https://dataframes.juliadata.org/stable/) stellt Funktionen zum bequemen Umgang mit tabellarischen Daten
|
|
||||||
zur Verfügung.
|
|
||||||
|
|
||||||
|
- The CSV format is often used to provide tables in a form that can be read not only by MS Excel.
|
||||||
|
- An example is the weather and climate database _Meteostat_.
|
||||||
|
- The [DataFrames.jl](https://dataframes.juliadata.org/stable/) package provides functions for convenient handling of tabular data.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using CSV, DataFrames, Downloads
|
using CSV, DataFrames, Downloads
|
||||||
# Wetterdaten von Westerland, s. https://dev.meteostat.net/bulk/hourly.html
|
# Weather data from Westerland, see https://dev.meteostat.net/bulk/hourly.html
|
||||||
|
|
||||||
url = "https://bulk.meteostat.net/v2/hourly/10018.csv.gz"
|
url = "https://bulk.meteostat.net/v2/hourly/10018.csv.gz"
|
||||||
http_response = Downloads.download(url)
|
http_response = Downloads.download(url)
|
||||||
@@ -409,25 +421,26 @@ file = CSV.File(http_response, header=false);
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Die Daten sehen so aus:
|
The data looks like this:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
# https://dev.meteostat.net/bulk/hourly.html#endpoints
|
# https://dev.meteostat.net/bulk/hourly.html#endpoints
|
||||||
#
|
#
|
||||||
# Spalte 1 Datum
|
# Column 1 Date
|
||||||
# 2 Uhrzeit (Stunde)
|
# 2 Time (hour)
|
||||||
# 3 Temp
|
# 3 Temperature
|
||||||
# 5 Luftfeuchtigkeit
|
# 5 Humidity
|
||||||
# 6 Niederschlag
|
# 6 Precipitation
|
||||||
# 8 Windrichtung
|
# 8 Wind direction
|
||||||
# 9 Windstärke
|
# 9 Wind speed
|
||||||
|
|
||||||
df = DataFrame(file)
|
df = DataFrame(file)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: false
|
#| error: false
|
||||||
#| echo: false
|
#| echo: false
|
||||||
@@ -438,18 +451,19 @@ describe(df)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Zum bequemen Plotten und zum Umgang mit den Datums- und Zeitformaten in der Wettertabelle
|
|
||||||
laden wir noch 2 Helferlein:
|
For convenient plotting and handling of date and time formats in the weather table,
|
||||||
|
we load two helper packages:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using StatsPlots, Dates
|
using StatsPlots, Dates
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Wir erzeugen eine neue Spalte, die Datum (aus Spalte 1) und Uhrzeit (aus Spalte 2) kombiniert:
|
We create a new column that combines date (from column 1) and time (from column 2):
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
# neue Spalte mit Sp.1 und 2 (date & time) kombiniert
|
# new column combining col. 1 and 2 (date & time)
|
||||||
|
|
||||||
df[!, :datetime] = DateTime.(df.Column1) .+ Hour.(df.Column2);
|
df[!, :datetime] = DateTime.(df.Column1) .+ Hour.(df.Column2);
|
||||||
```
|
```
|
||||||
@@ -466,14 +480,12 @@ df[!, :datetime] = DateTime.(df.Column1) .+ Hour.(df.Column2);
|
|||||||
@df df plot(:datetime, :Column3)
|
@df df plot(:datetime, :Column3)
|
||||||
```
|
```
|
||||||
|
|
||||||
Und nun zum Plot:
|
And now to the plot:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@df df plot(:datetime, [:Column9, :Column6, :Column3],
|
@df df plot(:datetime, [:Column9, :Column6, :Column3],
|
||||||
xlims = (DateTime(2023,9,1), DateTime(2024,5,30)),
|
xlims = (DateTime(2023,9,1), DateTime(2024,5,30)),
|
||||||
layout=(3,1), title=["Wind" "Regen" "Temp"],
|
layout=(3,1), title=["Wind" "Rain" "Temp"],
|
||||||
legend=:none, size=(800,800))
|
legend=:none, size=(800,800))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,41 +10,41 @@ using InteractiveUtils
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
# Plots und Datenvisualisierung in Julia: _Plots.jl_
|
# Plots and Data Visualization in Julia: _Plots.jl_
|
||||||
|
|
||||||
Es gibt zahlreiche Grafikpakete für Julia. Zwei oft genutzte sind [Makie.jl](https://docs.makie.org/stable/) und
|
There are numerous graphics packages for Julia. Two frequently used ones are [Makie.jl](https://docs.makie.org/stable/) and
|
||||||
[Plots.jl](https://docs.juliaplots.org/latest/). Bevor wir diese genauer vorstellen, seien noch einige andere Pakete aufgelistet.
|
[Plots.jl](https://docs.juliaplots.org/latest/). Before presenting these in more detail, some other packages are listed.
|
||||||
|
|
||||||
## Kurze Übersicht: einige Grafikpakete
|
## Brief Overview: Some Graphics Packages
|
||||||
|
|
||||||
| Paket/Doku | Tutorial | Beispiele | Bemerkungen |
|
| Package/Documentation | Tutorial | Examples | Remarks |
|
||||||
|:----|:--|:--|:--------|
|
|:----|:--|:--|:--------|
|
||||||
|[Plots.jl](https://docs.juliaplots.org/latest/) | [Tutorial](https://docs.juliaplots.org/latest/tutorial/) | [Galerie](https://goropikari.github.io/PlotsGallery.jl/) | konzipiert als einheitliches Interface zu verschiedenen _backends_ (Grafikbibliotheken) |
|
|[Plots.jl](https://docs.juliaplots.org/latest/) | [Tutorial](https://docs.juliaplots.org/latest/tutorial/) | [Gallery](https://goropikari.github.io/PlotsGallery.jl/) | designed as a unified interface to various _backends_ (graphics libraries) |
|
||||||
| [Makie.jl](https://docs.makie.org/stable/) | [Basic tutorial](https://docs.makie.org/v0.21/tutorials/basic-tutorial) | [Beautiful Makie](https://beautiful.makie.org/) | "data visualization ecosystem for Julia", Backends: Cairo (Vektorgrafik), OpenGL, WebGL |
|
| [Makie.jl](https://docs.makie.org/stable/) | [Basic tutorial](https://docs.makie.org/v0.21/tutorials/basic-tutorial) | [Beautiful Makie](https://beautiful.makie.org/) | "data visualization ecosystem for Julia", backends: Cairo (vector graphics), OpenGL, WebGL |
|
||||||
|[PlotlyJS.jl](http://juliaplots.org/PlotlyJS.jl/stable/) | [Getting started](https://plotly.com/julia/getting-started/)| [Examples](https://plotly.com/julia/plotly-fundamentals/)| Interface zur [Plotly](https://plotly.com/graphing-libraries/) Javascript-Grafikbibliothek |
|
|[PlotlyJS.jl](http://juliaplots.org/PlotlyJS.jl/stable/) | [Getting started](https://plotly.com/julia/getting-started/)| [Examples](https://plotly.com/julia/plotly-fundamentals/)| Interface to the [Plotly](https://plotly.com/graphing-libraries/) JavaScript graphics library |
|
||||||
| [Gadfly.jl](https://gadflyjl.org/stable/)| [Tutorial](https://gadflyjl.org/stable/tutorial/) | [Galerie](https://github.com/GiovineItalia/Gadfly.jl?tab=readme-ov-file#gallery)| "a plotting and data visualization system written in Julia, influenced by R's [ggplot2](https://ggplot2.tidyverse.org/)" |
|
| [Gadfly.jl](https://gadflyjl.org/stable/)| [Tutorial](https://gadflyjl.org/stable/tutorial/) | [Gallery](https://github.com/GiovineItalia/Gadfly.jl?tab=readme-ov-file#gallery)| "a plotting and data visualization system written in Julia, influenced by R's [ggplot2](https://ggplot2.tidyverse.org/)" |
|
||||||
| [Bokeh.jl](https://cjdoris.github.io/Bokeh.jl/stable/) | | [Galerie](https://cjdoris.github.io/Bokeh.jl/stable/gallery/)| Julia-Frontend für [Bokeh](https://bokeh.org/) |
|
| [Bokeh.jl](https://cjdoris.github.io/Bokeh.jl/stable/) | | [Gallery](https://cjdoris.github.io/Bokeh.jl/stable/gallery/)| Julia frontend for [Bokeh](https://bokeh.org/) |
|
||||||
|[VegaLite.jl](https://www.queryverse.org/VegaLite.jl/stable/) | [Tutorial](https://www.queryverse.org/VegaLite.jl/stable/gettingstarted/tutorial/)| [Examples](https://www.queryverse.org/VegaLite.jl/stable/examples/examples_barcharts/)| Julia-Frontend für [Vega-Lite](https://vega.github.io/vega-lite/)|
|
|[VegaLite.jl](https://www.queryverse.org/VegaLite.jl/stable/) | [Tutorial](https://www.queryverse.org/VegaLite.jl/stable/gettingstarted/tutorial/)| [Examples](https://www.queryverse.org/VegaLite.jl/stable/examples/examples_barcharts/)| Julia frontend for [Vega-Lite](https://vega.github.io/vega-lite/)|
|
||||||
| [Luxor.jl](http://juliagraphics.github.io/Luxor.jl/stable/) |[Tutorial](https://juliagraphics.github.io/Luxor.jl/stable/tutorial/helloworld/)|[Examples](https://juliagraphics.github.io/Luxor.jl/stable/example/moreexamples/)| Allgemeine Vektorgrafik/Illustrationen |
|
| [Luxor.jl](http://juliagraphics.github.io/Luxor.jl/stable/) |[Tutorial](https://juliagraphics.github.io/Luxor.jl/stable/tutorial/helloworld/)|[Examples](https://juliagraphics.github.io/Luxor.jl/stable/example/moreexamples/)| General vector graphics/illustrations |
|
||||||
| [Javis.jl](https://juliaanimators.github.io/Javis.jl/stable/) |[Tutorials](https://juliaanimators.github.io/Javis.jl/stable/tutorials/)| [Examples](https://juliaanimators.github.io/Javis.jl/stable/examples/)| *Animierte* Vektorgrafik
|
| [Javis.jl](https://juliaanimators.github.io/Javis.jl/stable/) |[Tutorials](https://juliaanimators.github.io/Javis.jl/stable/tutorials/)| [Examples](https://juliaanimators.github.io/Javis.jl/stable/examples/)| *Animated* vector graphics
|
||||||
| [TidierPlots.jl](https://github.com/TidierOrg/TidierPlots.jl)| [Reference](https://tidierorg.github.io/TidierPlots.jl/latest/) || "is a 100% Julia implementation of the R package ggplot2 powered by Makie.jl"|
|
| [TidierPlots.jl](https://github.com/TidierOrg/TidierPlots.jl)| [Reference](https://tidierorg.github.io/TidierPlots.jl/latest/) || "is a 100% Julia implementation of the R package ggplot2 powered by Makie.jl"|
|
||||||
|[PythonPlot.jl](https://github.com/JuliaPy/PythonPlot.jl)| |[Examples (in Python)](https://matplotlib.org/stable/gallery/index.html)| Interface zu Matplotlib (Python), 1:1-Übertragung der Python-API, deswegen s. [Matplotlib-Dokumentation](https://matplotlib.org/stable/api/pyplot_summary.html)
|
|[PythonPlot.jl](https://github.com/JuliaPy/PythonPlot.jl)| |[Examples (in Python)](https://matplotlib.org/stable/gallery/index.html)| Interface to Matplotlib (Python), 1:1 transfer of the Python API, therefore see [Matplotlib documentation](https://matplotlib.org/stable/api/pyplot_summary.html)
|
||||||
|
|
||||||
: {.striped .hover}
|
{: .striped .hover}
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
| [PyPlot.jl](https://github.com/JuliaPy/PyPlot.jl) | | [Examples](https://gist.github.com/gizmaa/7214002)| Interface zu Matplotlib (Python), 1:1-Übertragung der Python-API, deswegen s. [Matplotlib-Dokumentation](https://matplotlib.org/stable/) |
|
| [PyPlot.jl](https://github.com/JuliaPy/PyPlot.jl) | | [Examples](https://gist.github.com/gizmaa/7214002)| Interface to Matplotlib (Python), 1:1 transfer of the Python API, therefore see [Matplotlib documentation](https://matplotlib.org/stable/) |
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Plots.jl
|
## Plots.jl
|
||||||
|
|
||||||
### Einfache Plots
|
### Simple Plots
|
||||||
|
|
||||||
Die `plot()`-Funktion erwartet im einfachsten Fall:
|
The `plot()` function expects, in the simplest case:
|
||||||
|
|
||||||
- als erstes Argument einen Vektor von $x$-Werten der Länge $n$ und
|
- as the first argument a vector of $x$-values of length $n$ and
|
||||||
- als zweites Argument einen gleichlangen Vektor mit den dazugehörigen $y$-Werten.
|
- as the second argument a vector of the same length with the corresponding $y$-values.
|
||||||
- Das zweite Argument kann auch eine $n\times m$-Matrix sein. Dann wird jeder Spaltenvektor als eigener Graph (in der Docu `series` genannt) angesehen und es werden $m$ Kurven geplottet:
|
- The second argument can also be an $n\times m$-matrix. Then each column vector is regarded as a separate graph (called `series` in the documentation) and $m$ curves are plotted:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -57,16 +57,16 @@ cx = @. cos(2x^(1/2))
|
|||||||
plot(x, [sx cx])
|
plot(x, [sx cx])
|
||||||
```
|
```
|
||||||
|
|
||||||
- Die Funktionen des _Plots.jl_-Paketes wie `plot(), scatter(), contour(), heatmap(), histogram(), bar(),...` usw. starten alle einen neuen Plot.
|
- The functions of the _Plots.jl_ package such as `plot(), scatter(), contour(), heatmap(), histogram(), bar(),...` etc. all start a new plot.
|
||||||
- Die Versionen `plot!(), scatter!(), contour!(), heatmap!(), histogram!(), bar!(),...` erweitern einen existierenden Plot:
|
- The versions `plot!(), scatter!(), contour!(), heatmap!(), histogram!(), bar!(),...` extend an existing plot:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
plot(x, sx) # plot only sin(x)
|
plot(x, sx) # plot only sin(x)
|
||||||
plot!(x, cx) # add second graph
|
plot!(x, cx) # add second graph
|
||||||
plot!(x, sqrt.(x)) # add a thirth one
|
plot!(x, sqrt.(x)) # add a third one
|
||||||
```
|
```
|
||||||
|
|
||||||
Plots sind Objekte, die zugewiesen werden können. Dann kann man sie später weiterverwenden, kopieren und insbesondere mit den `!`-Funktionen erweitern:
|
Plots are objects that can be assigned. Then they can be used later, copied, and in particular extended with the `!` functions:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
plot1 = plot(x, [sx cx])
|
plot1 = plot(x, [sx cx])
|
||||||
@@ -74,7 +74,7 @@ plot1a = deepcopy(plot1) # plot objects are quite deep structures
|
|||||||
scatter!(plot1, x, sx) # add scatter plot, i.e. unconnected data points
|
scatter!(plot1, x, sx) # add scatter plot, i.e. unconnected data points
|
||||||
```
|
```
|
||||||
|
|
||||||
Die kopierte Version `plot1a` ist durch die `scatter!`-Anweisung nicht modifiziert worden und kann unabhängig weiterverwendet werden:
|
The copied version `plot1a` has not been modified by the `scatter!` statement and can be used independently:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
plot!(plot1a, x, 2 .* sx)
|
plot!(plot1a, x, 2 .* sx)
|
||||||
@@ -82,7 +82,7 @@ plot!(plot1a, x, 2 .* sx)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Plot-Objekte kann man als Grafikdateien (PDF, SVG, PNG,...) abspeichern:
|
Plot objects can be saved as graphics files (PDF, SVG, PNG,...):
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -94,13 +94,13 @@ savefig(plot1, "plot.png")
|
|||||||
;ls -l plot.png
|
;ls -l plot.png
|
||||||
```
|
```
|
||||||
|
|
||||||
Plot-Objekte können auch als Teilplot in andere Plots eingefügt werden, siehe Abschnitt @sec-subplot.
|
Plot objects can also be inserted as subplots into other plots, see section @sec-subplot.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Funktionsplots
|
### Function Plots
|
||||||
|
|
||||||
Man kann `plot()` auch eine Funktion und einen Vektor mit $x$-Werten übergeben:
|
`plot()` can also be passed a function and a vector of $x$-values:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
# https://mzrg.com/math/graphs.shtml
|
# https://mzrg.com/math/graphs.shtml
|
||||||
@@ -111,7 +111,7 @@ plot(f, 0:0.01:3)
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Die parametrische Form $x = x(t),\ y = y(t)$ kann durch die Übergabe von zwei Funktionen und einen Vektor von $t$-Werten an `plot()` gezeichnet werden.
|
The parametric form $x = x(t),\ y = y(t)$ can be drawn by passing two functions and a vector of $t$-values to `plot()`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
# https://en.wikipedia.org/wiki/Butterfly_curve_(transcendental)
|
# https://en.wikipedia.org/wiki/Butterfly_curve_(transcendental)
|
||||||
@@ -123,16 +123,16 @@ plot(xt, yt, 0:0.01:12π)
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Plot-Themen
|
### Plot Themes
|
||||||
|
|
||||||
> "PlotThemes is a package to spice up the plots made with Plots.jl."\
|
> "PlotThemes is a package to spice up the plots made with Plots.jl."\
|
||||||
Hier geht es zur illustrierten [Liste der Themen](https://docs.juliaplots.org/stable/generated/plotthemes/)
|
Here is the illustrated [list of themes](https://docs.juliaplots.org/stable/generated/plotthemes/)
|
||||||
|
|
||||||
oder:
|
or:
|
||||||
```{julia}
|
```{julia}
|
||||||
using PlotThemes
|
using PlotThemes
|
||||||
|
|
||||||
# Liste der Themen
|
# list of themes
|
||||||
keys(PlotThemes._themes)
|
keys(PlotThemes._themes)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -149,48 +149,48 @@ plot(x, [sx cx 1 ./ (1 .+ x)])
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Plot-Attribute
|
### Plot Attributes
|
||||||
|
|
||||||
Die Funktionen des `Plots.jl`-Paketes haben eine große Anzahl von Optionen.
|
The functions of the `Plots.jl` package have a large number of options.
|
||||||
`Plots.jl` teilt die Attribute in 4 Gruppen ein:
|
`Plots.jl` divides the attributes into 4 groups:
|
||||||
|
|
||||||
::::{.cell}
|
::::{.cell}
|
||||||
```{julia}
|
```{julia}
|
||||||
#| output: asis
|
#| output: asis
|
||||||
plotattr(:Plot) # Attribute für den Gesamtplot
|
plotattr(:Plot) # attributes for the overall plot
|
||||||
```
|
```
|
||||||
::::
|
::::
|
||||||
|
|
||||||
::::{.cell}
|
::::{.cell}
|
||||||
```{julia}
|
```{julia}
|
||||||
#| output: asis
|
#| output: asis
|
||||||
plotattr(:Subplot) # Attribute für einen Teilplot
|
plotattr(:Subplot) # attributes for a subplot
|
||||||
```
|
```
|
||||||
::::
|
::::
|
||||||
|
|
||||||
::::{.cell}
|
::::{.cell}
|
||||||
```{julia}
|
```{julia}
|
||||||
#| output: asis
|
#| output: asis
|
||||||
plotattr(:Axis) # Attribute für eine Achse
|
plotattr(:Axis) # attributes for an axis
|
||||||
```
|
```
|
||||||
::::
|
::::
|
||||||
|
|
||||||
::::{.cell}
|
::::{.cell}
|
||||||
```{julia}
|
```{julia}
|
||||||
#| output: asis
|
#| output: asis
|
||||||
plotattr(:Series) # Attribute für eine Serie, also zB ein Linienzug im Plot
|
plotattr(:Series) # attributes for a series, e.g., a line in the plot
|
||||||
```
|
```
|
||||||
::::
|
::::
|
||||||
|
|
||||||
Man kann auch nachfragen, was die einzelnen Attribute bedeuten und welche Werte zulässig sind:
|
One can also ask what the individual attributes mean and which values are allowed:
|
||||||
```{julia}
|
```{julia}
|
||||||
plotattr("linestyle")
|
plotattr("linestyle")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Ein Beispiel:
|
An example:
|
||||||
```{julia}
|
```{julia}
|
||||||
theme(:default) # zurück zum Standardthema
|
theme(:default) # return to default theme
|
||||||
|
|
||||||
x = 0:0.05:1
|
x = 0:0.05:1
|
||||||
y = sin.(2π*x)
|
y = sin.(2π*x)
|
||||||
@@ -200,9 +200,9 @@ plot(x, y, seriestype = :sticks, linewidth = 4, seriescolor = "#00b300",
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Viele Angaben können auch sehr weit abgekürzt werden, siehe z.B. die Angabe `Aliases:` in der obigen Ausgabe des Kommandos `plotattr("linestyle")`.
|
Many specifications can also be abbreviated significantly, see e.g. the `Aliases:` in the above output of the command `plotattr("linestyle")`.
|
||||||
|
|
||||||
Das folgende `plot()`-Kommando is äquivalent zum vorherigen:
|
The following `plot()` command is equivalent to the previous one:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| eval: false
|
#| eval: false
|
||||||
@@ -210,61 +210,61 @@ plot(x, y, t = :sticks, w = 4, c = "#00b300", m = (:circle, 8, :green ))
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Weitere Extras
|
### Additional Extras
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using Plots # Wiederholung schadet nicht
|
using Plots # repetition does not hurt
|
||||||
using Plots.PlotMeasures # für Maßangaben in mm, cm,...
|
using Plots.PlotMeasures # for measurements in mm, cm,...
|
||||||
using LaTeXStrings # für LaTeX-Konstrukte in Plot-Beschriftungen
|
using LaTeXStrings # for LaTeX constructs in plot labels
|
||||||
using PlotThemes # vorgefertigte Themen
|
using PlotThemes # predefined themes
|
||||||
```
|
```
|
||||||
|
|
||||||
Das Paket `LaTeXStrings.jl` stellt einen String-Konstruktor `L"..."` zur Verfügung. Diese Strings können LaTeX-Konstrukte, insbesondere Formeln, enthalten. Wenn der String keine expliziten Dollarzeichen enthält, wird er automatisch im LaTeX-Math-Modus interpretiert.
|
The `LaTeXStrings.jl` package provides a string constructor `L"..."`. These strings can contain LaTeX constructs, especially formulas. If the string does not contain explicit dollar signs, it is automatically interpreted in LaTeX math mode.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
xs = range(0, 2π, length = 100)
|
xs = range(0, 2π, length = 100)
|
||||||
|
|
||||||
data = [sin.(xs) cos.(xs) 2sin.(xs) (x->sin(x^2)).(xs)] # 4 Funktionen
|
data = [sin.(xs) cos.(xs) 2sin.(xs) (x->sin(x^2)).(xs)] # 4 functions
|
||||||
|
|
||||||
theme(:ggplot2)
|
theme(:ggplot2)
|
||||||
|
|
||||||
plot10 = plot(xs, data,
|
plot10 = plot(xs, data,
|
||||||
fontfamily="Computer Modern",
|
fontfamily="Computer Modern",
|
||||||
|
|
||||||
# LaTeX-String L"..."
|
# LaTeX string L"..."
|
||||||
title = L"Winkelfunktionen $\sin(\alpha), \cos(\alpha), 2\sin(\alpha), \sin(\alpha^2)$",
|
title = L"Winkelfunktionen $\sin(\alpha), \cos(\alpha), 2\sin(\alpha), \sin(\alpha^2)$",
|
||||||
xlabel = L"Winkel $\alpha$",
|
xlabel = L"Winkel $\alpha$",
|
||||||
ylabel = "Funktionswert",
|
ylabel = "Funktionswert",
|
||||||
|
|
||||||
# 1x4-Matrizen mit Farben, Marker,... für die 4 'Series'
|
# 1x4-matrices with colors, markers,... for the 4 'series'
|
||||||
color=[:black :green RGB(0.3, 0.8, 0.2) :blue ],
|
color=[:black :green RGB(0.3, 0.8, 0.2) :blue ],
|
||||||
markers = [:rect :circle :utriangle :diamond],
|
markers = [:rect :circle :utriangle :diamond],
|
||||||
markersize = [2 1 0 4],
|
markersize = [2 1 0 4],
|
||||||
linewidth = [1 3 1 2],
|
linewidth = [1 3 1 2],
|
||||||
linestyle = [:solid :dash :dot :solid ],
|
linestyle = [:solid :dash :dot :solid ],
|
||||||
|
|
||||||
# Achsen
|
# axes
|
||||||
xlim = (0, 6.6),
|
xlim = (0, 6.6),
|
||||||
ylim = (-2, 2.3),
|
ylim = (-2, 2.3),
|
||||||
yticks = -2:.4:2.3, # mit Schrittweite
|
yticks = -2:.4:2.3, # with step size
|
||||||
|
|
||||||
# Legende
|
# legend
|
||||||
legend = :bottomleft,
|
legend = :bottomleft,
|
||||||
label = [ L"\sin(\alpha)" L"\cos(\alpha)" L"2\sin(\alpha)" L"\sin(\alpha^2)"],
|
label = [ L"\sin(\alpha)" L"\cos(\alpha)" L"2\sin(\alpha)" L"\sin(\alpha^2)"],
|
||||||
|
|
||||||
top_margin = 5mm, # hier wird Plots.PlotMeasures gebraucht
|
top_margin = 5mm, # here Plots.PlotMeasures is needed
|
||||||
)
|
)
|
||||||
|
|
||||||
# Zusatztext: annotate!(x-pos, y-pos, text("...", font, fontsize))
|
# additional text: annotate!(x-pos, y-pos, text("...", font, fontsize))
|
||||||
|
|
||||||
annotate!(plot10, 4.1, 1.8, text("nicht schön, aber viel","Computer Modern", 10) )
|
annotate!(plot10, 4.1, 1.8, text("nicht schön, aber viel","Computer Modern", 10) )
|
||||||
```
|
```
|
||||||
|
|
||||||
### Andere Plot-Funktionen
|
### Other Plot Functions
|
||||||
|
|
||||||
Bisher haben wir vor allem Linien geplottet. Es gibt noch viele andere Typen wie _scatter plot, contour, heatmap, histogram, stick,..._
|
So far, we have plotted mainly lines. There are many other types such as _scatter plot, contour, heatmap, histogram, stick,..._
|
||||||
|
|
||||||
Dies kann man mit dem `seriestype`-Attribut steuern:
|
This can be controlled with the `seriestype` attribute:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
theme(:default)
|
theme(:default)
|
||||||
@@ -273,7 +273,7 @@ x = range(0, 2π; length = 50)
|
|||||||
plot(x, sin.(x), seriestype=:scatter)
|
plot(x, sin.(x), seriestype=:scatter)
|
||||||
```
|
```
|
||||||
|
|
||||||
oder indem man die spezielle Funktion benutzt, die so heißt wie der `seriestype`:
|
or by using the specific function named after the `seriestype`:
|
||||||
```{julia}
|
```{julia}
|
||||||
x = range(0, 2π; length = 50)
|
x = range(0, 2π; length = 50)
|
||||||
scatter(x, sin.(x))
|
scatter(x, sin.(x))
|
||||||
@@ -281,9 +281,9 @@ scatter(x, sin.(x))
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Subplots und Layout {#sec-subplot}
|
### Subplots and Layout {#sec-subplot}
|
||||||
|
|
||||||
Mehrere Plots können zu einer Abbildung zusammengefasst werden. Die Anordnung bestimmt der `layout`-Parameter. Dabei bedeutet `layout=(m,n)`, dass die Plots in einem $m\times n$-Schema angeordnet werden:
|
Multiple plots can be combined into one figure. The arrangement is determined by the `layout` parameter. `layout=(m,n)` means that the plots are arranged in an $m\times n$ scheme:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = range(0, 2π; length = 100)
|
x = range(0, 2π; length = 100)
|
||||||
@@ -300,7 +300,7 @@ plot(plots..., layout=(4,1), legend=false, title=["sin" "cos" "tan" "sinc"])
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Man kann Layouts auch schachteln und mit dem `@layout`-Macro explizite Breiten/Höhenanteile vorgeben:
|
Layouts can also be nested and explicit width/height proportions can be specified using the `@layout` macro:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -317,27 +317,27 @@ plot(plots..., layout=mylayout, legend=false, title=["sin" "cos" "tan" "sinc"])
|
|||||||
|
|
||||||
### Backends
|
### Backends
|
||||||
|
|
||||||
`Plots.jl` ist konzipiert als ein einheitliches Interface zu verschiedenen _backends_ (Grafik-Engines). Man kann zu einem anderen Backend wechseln und dieselben Plot-Kommandos und -Attribute verwenden.
|
`Plots.jl` is designed as a unified interface to various _backends_ (graphics engines). One can switch to another backend and use the same plot commands and attributes.
|
||||||
|
|
||||||
Allerdings unterstützen nicht alle _backends_ alle Plot-Typen und -Attribute. Einen Überblick gibt es [hier](https://docs.juliaplots.org/stable/generated/supported/).
|
However, not all _backends_ support all plot types and attributes. An overview is available [here](https://docs.juliaplots.org/stable/generated/supported/).
|
||||||
|
|
||||||
Bisher wurde das Standard-Backend verwendet. Es heißt [GR](https://gr-framework.org/about.html) und ist eine am Forschungszentrum Jülich entwickelte und hauptsächlich in C geschriebene Grafik-Engine.
|
So far, the default backend has been used. It is called [GR](https://gr-framework.org/about.html) and is a graphics engine developed at the Jülich Research Center and written primarily in C.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using Plots
|
using Plots
|
||||||
backend() # Anzeige des gewählten backends, GR ist der default
|
backend() # display the selected backend, GR is the default
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Nochmal ein Beispiel
|
Another example
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 1:30
|
x = 1:30
|
||||||
y = rand(30)
|
y = rand(30)
|
||||||
plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Wasserstand")
|
plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Wasserstand")
|
||||||
```
|
```
|
||||||
|
|
||||||
und hier derselbe Plot mit dem `PlotlyJS`-Backend.
|
and here the same plot with the `PlotlyJS` backend.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -345,22 +345,22 @@ plotlyjs() # change plots backend
|
|||||||
plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Wasserstand")
|
plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Wasserstand")
|
||||||
```
|
```
|
||||||
|
|
||||||
Dieses Backend ermöglich mit Hilfe von Javascript eine gewisse Interaktivität. Wenn man die Maus in das Bild bewegt, kann man mit der Maus zoomen, verschieben und 3D-Plots auch drehen.
|
This backend enables a certain interactivity using JavaScript. When moving the mouse into the image, one can zoom and pan with the mouse, and 3D plots can also be rotated.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
gr() # zurück zu GR als backend
|
gr() # return to GR as backend
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 3D Plots
|
### 3D Plots
|
||||||
|
|
||||||
Die Funktionen `surface()` und `contour()` ermöglichen den Plot einer Funktion $f(x,y)$. Als Argumente werden benötigt:
|
The functions `surface()` and `contour()` allow plotting of a function $f(x,y)$. The required arguments are:
|
||||||
|
|
||||||
- eine Menge (Vektor) $X$ von $x$-Werten,
|
- a set (vector) $X$ of $x$-values,
|
||||||
- eine Menge (Vektor) $Y$ von $y$-Werten und
|
- a set (vector) $Y$ of $y$-values and
|
||||||
- eine Funktion von zwei Variablen, die dann auf $X \times Y$ ausgewertet und geplottet wird.
|
- a function of two variables that is then evaluated on $X \times Y$ and plotted.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
f(x,y) = (1 - x/2 + x^5 + y^3) * exp(-x^2 - y^2)
|
f(x,y) = (1 - x/2 + x^5 + y^3) * exp(-x^2 - y^2)
|
||||||
@@ -372,8 +372,8 @@ surface( -3:0.02:3, -3:0.02:3, f)
|
|||||||
contour( -3:0.02:3, -3:0.02:3, f, fill=true, colormap=:summer, levels=20, contour_labels=false)
|
contour( -3:0.02:3, -3:0.02:3, f, fill=true, colormap=:summer, levels=20, contour_labels=false)
|
||||||
```
|
```
|
||||||
|
|
||||||
Kurven (oder auch einfach Punktmengen) in drei Dimensionen lassen sich plotten, indem man `plot()` mit 3 Vektoren
|
Curves (or simply point sets) in three dimensions can be plotted by calling `plot()` with 3 vectors
|
||||||
aufruft, die jeweils die $x$, $y$ und $z$-Koordinaten der Datenpunkte enthalten.
|
containing the $x$, $y$ and $z$-coordinates of the data points, respectively.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
plotlyjs()
|
plotlyjs()
|
||||||
@@ -387,25 +387,25 @@ plot(x, y, z, zcolor=reverse(z), markersize=3, markershape= :circle,
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
> Wir verwenden mal das `plotlyjs`-Backend, damit ist der Plot interaktiv und kann mit der Maus gedreht und gezoomt werden.
|
> We use the `plotlyjs` backend here, so the plot is interactive and can be rotated and zoomed with the mouse.
|
||||||
|
|
||||||
### Plots.jl und _recipes_
|
### Plots.jl and _recipes_
|
||||||
|
|
||||||
Andere Pakete können die Möglichkeiten von `Plots.jl` erweitern, indem sie sogenannte _recipes_ für spezielle Plots und Datenstrukturen definieren, siehe [https://docs.juliaplots.org/latest/ecosystem/](https://docs.juliaplots.org/latest/ecosystem/), z.B.:
|
Other packages can extend the capabilities of `Plots.jl` by defining so-called _recipes_ for special plots and data structures, see [https://docs.juliaplots.org/latest/ecosystem/](https://docs.juliaplots.org/latest/ecosystem/), e.g.:
|
||||||
|
|
||||||
- `StatsPlots.jl` direktes Plotten von _Dataframes_, spezielle statistische Plots usw. oder
|
- `StatsPlots.jl` direct plotting of _Dataframes_, special statistical plots, etc. or
|
||||||
- `GraphRecipes.jl` [Plotten von Graphstrukturen](https://docs.juliaplots.org/latest/GraphRecipes/examples/)
|
- `GraphRecipes.jl` [Plotting of graph structures](https://docs.juliaplots.org/latest/GraphRecipes/examples/)
|
||||||
|
|
||||||
|
|
||||||
### Ein Säulendiagramm
|
### A Bar Chart
|
||||||
|
|
||||||
Für das letzte Beispiel laden wir ein Paket, das über 700 freie (_"public domain"_) Datensätze, darunter z.B:
|
For the last example, we load a package that provides over 700 free (_"public domain"_) datasets, including, for example:
|
||||||
|
|
||||||
- die Passagierliste der _Titanic_,
|
- the passenger list of the _Titanic_,
|
||||||
- Verbrauchsdaten amerikanischer Autos aus den 70ern oder
|
- fuel consumption data of American cars from the 70s or
|
||||||
- historische Währungskurse
|
- historical exchange rates
|
||||||
|
|
||||||
bereitstellt:
|
provides:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using RDatasets
|
using RDatasets
|
||||||
@@ -419,13 +419,13 @@ using RDatasets
|
|||||||
#RDatasets.datasets()
|
#RDatasets.datasets()
|
||||||
```
|
```
|
||||||
|
|
||||||
Der Datensatz ["Motor Trend Car Road Tests"](https://rdrr.io/r/datasets/mtcars.html)
|
The dataset ["Motor Trend Car Road Tests"](https://rdrr.io/r/datasets/mtcars.html)
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
cars = dataset("datasets", "mtcars")
|
cars = dataset("datasets", "mtcars")
|
||||||
```
|
```
|
||||||
|
|
||||||
Wir brauchen für den Plot nur die beiden Spalten `cars.Model` und `cars.MPG`, den Benzinverbrauch in _miles per gallon_ (Mehr heißt sparsamer!)
|
We only need the two columns `cars.Model` and `cars.MPG` for the plot, the fuel consumption in _miles per gallon_ (more means more economical!)
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
theme(:bright)
|
theme(:bright)
|
||||||
@@ -443,10 +443,10 @@ bar(cars.Model, cars.MPG,
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Was noch fehlt: Animation
|
### What is Missing: Animation
|
||||||
|
|
||||||
Hier sei auf die [Dokumentation](https://docs.juliaplots.org/latest/animations/) verwiesen und nur ein Beispiel
|
Please refer to the [documentation](https://docs.juliaplots.org/latest/animations/) and only an example
|
||||||
(von <https://www.juliafordatascience.com/animations-with-plots-jl/>) angegeben:
|
(from <https://www.juliafordatascience.com/animations-with-plots-jl/>) is given:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: false
|
#| error: false
|
||||||
|
|||||||
@@ -2,7 +2,18 @@
|
|||||||
engine: julia
|
engine: julia
|
||||||
---
|
---
|
||||||
|
|
||||||
# Arbeit mit Julia: REPL, Pakete, Introspection
|
```{julia}
|
||||||
|
#| error: false
|
||||||
|
#| echo: false
|
||||||
|
#| output: false
|
||||||
|
using InteractiveUtils
|
||||||
|
import QuartoNotebookWorker
|
||||||
|
Base.stdout = QuartoNotebookWorker.with_context(stdout)
|
||||||
|
myactive_module() = Main.Notebook
|
||||||
|
Base.active_module() = myactive_module()
|
||||||
|
```
|
||||||
|
|
||||||
|
# Working with Julia: REPL, Packages, Introspection
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: false
|
#| error: false
|
||||||
@@ -17,37 +28,36 @@ Base.active_module() = myactive_module()
|
|||||||
# https://github.com/JuliaLang/julia/blob/master/base/show.jl#L3073-L3077
|
# https://github.com/JuliaLang/julia/blob/master/base/show.jl#L3073-L3077
|
||||||
```
|
```
|
||||||
|
|
||||||
## Dokumentation
|
## Documentation
|
||||||
|
|
||||||
Die offizielle Julia-Dokumentation [https://docs.julialang.org/](https://docs.julialang.org/) enthält zahlreiche Übersichten, darunter:
|
The official Julia documentation [https://docs.julialang.org/](https://docs.julialang.org/) contains numerous overviews, including:
|
||||||
|
|
||||||
- [https://docs.julialang.org/en/v1/base/punctuation/](https://docs.julialang.org/en/v1/base/punctuation/) Verzeichnis der Symbole
|
|
||||||
- [https://docs.julialang.org/en/v1/manual/unicode-input/](https://docs.julialang.org/en/v1/manual/unicode-input/) Verzeichnis spezieller Unicode-Symbole und deren Eingabe in Julia via Tab-Vervollständigung
|
|
||||||
- [https://docs.julialang.org/en/v1/manual/mathematical-operations/#Rounding-functions](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Rounding-functions) Liste mathematischer Funktionen
|
|
||||||
|
|
||||||
|
- [https://docs.julialang.org/en/v1/base/punctuation/](https://docs.julialang.org/en/v1/base/punctuation/) List of symbols
|
||||||
|
- [https://docs.julialang.org/en/v1/manual/unicode-input/](https://docs.julialang.org/en/v1/manual/unicode-input/) List of special Unicode symbols and their input methods via tab completion in Julia
|
||||||
|
- [https://docs.julialang.org/en/v1/manual/mathematical-operations/#Rounding-functions](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Rounding-functions) List of mathematical functions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Julia REPL (Read - Eval - Print - Loop)
|
## Julia REPL (Read - Eval - Print - Loop)
|
||||||
|
|
||||||
Nach dem Start von Julia in einem Terminal kann man neben Julia-Code auch verschiedene Kommandos eingeben
|
After starting Julia in a terminal, you can enter both Julia code and various commands:
|
||||||
|
|
||||||
:::{.narrow}
|
:::{.narrow}
|
||||||
| Kommando | Wirkung |
|
| Command | Effect |
|
||||||
| :----------------------------| :------------------------ |
|
| :----------------------------| :------------------------ |
|
||||||
| `exit()` oder `Ctrl-d` | exit Julia |
|
| `exit()` or `Ctrl-d` | exit Julia |
|
||||||
| `Ctrl-c` | interrupt |
|
| `Ctrl-c` | interrupt |
|
||||||
| `Ctrl-l` | clear screen |
|
| `Ctrl-l` | clear screen |
|
||||||
| Kommando mit `;` beenden | Ausgabe unterdrückt |
|
| End command with `;` | suppress output |
|
||||||
| `include("filename.jl")` | Datei mit Julia-Code einlesen und ausführen |
|
| `include("filename.jl")` | read and execute file with Julia code |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Der REPL hat verschiedene Modi:
|
The REPL has several modes:
|
||||||
|
|
||||||
| Modus | Prompt | Modus starten | Modus verlassen |
|
| Mode | Prompt | Start mode | Exit mode |
|
||||||
| :- | :- | :- | :- |
|
| :- | :- | :- | :- |
|
||||||
| default| `julia>` | | `Ctrl-d` (beendet Julia) |
|
| default| `julia>` | | `Ctrl-d` (exits Julia) |
|
||||||
| Package manager | `pkg>` | `]` | `backspace` |
|
| Package manager | `pkg>` | `]` | `backspace` |
|
||||||
| Help | `help?>` | `?`| `backspace `|
|
| Help | `help?>` | `?`| `backspace `|
|
||||||
|Shell | `shell>` | `;` | `backspace`|
|
|Shell | `shell>` | `;` | `backspace`|
|
||||||
@@ -55,12 +65,12 @@ Der REPL hat verschiedene Modi:
|
|||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
## Jupyter-Notebooks (IJulia)
|
## Jupyter Notebooks (IJulia)
|
||||||
|
|
||||||
|
|
||||||
In einem Jupyter-Notebook sind die Modi sind als Einzeiler in einer eigenen Input-Zelle nutzbar:
|
In a Jupyter notebook, the modes are usable as single-line commands in their own input cells:
|
||||||
|
|
||||||
(i) ein Kommando des Paket-Managers:
|
(i) a package manager command:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -68,7 +78,7 @@ In einem Jupyter-Notebook sind die Modi sind als Einzeiler in einer eigenen Inpu
|
|||||||
] status
|
] status
|
||||||
```
|
```
|
||||||
|
|
||||||
(ii) eine Help-Abfrage:
|
(ii) a help query:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -76,7 +86,7 @@ In einem Jupyter-Notebook sind die Modi sind als Einzeiler in einer eigenen Inpu
|
|||||||
?sin
|
?sin
|
||||||
```
|
```
|
||||||
|
|
||||||
(iii) Ein Shell-Kommando:
|
(iii) a shell command:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -84,33 +94,33 @@ In einem Jupyter-Notebook sind die Modi sind als Einzeiler in einer eigenen Inpu
|
|||||||
;ls
|
;ls
|
||||||
```
|
```
|
||||||
|
|
||||||
## Der Paketmanager
|
## The Package Manager
|
||||||
|
|
||||||
Wichtiger Teil des _Julia Ecosystems_ sind die zahlreichen Pakete, die Julia erweitern.
|
An important part of the _Julia ecosystem_ is the numerous packages that extend Julia.
|
||||||
|
|
||||||
- Einige Pakete sind Teil jeder Julia-Installation und müssen nur mit einer `using Paketname`-Anweisung aktiviert werden.
|
- Some packages are part of every Julia installation and only need to be activated with a `using Packagename` statement.
|
||||||
- Sie bilden die sogenannte _Standard Library_ und dazu gehören
|
- They form the so-called _standard library_, which includes
|
||||||
- `LinearAlgebra`, `Statistics`, `SparseArrays`, `Printf`, `Pkg` und andere.
|
- `LinearAlgebra`, `Statistics`, `SparseArrays`, `Printf`, `Pkg`, and others.
|
||||||
- Über 9000 Pakete sind offiziell registriert, siehe [https://julialang.org/packages/](https://julialang.org/packages/).
|
- Over 9000 packages are officially registered, see [https://julialang.org/packages/](https://julialang.org/packages/).
|
||||||
- Diese können mit wenigen Tastendrücken heruntergeladen und installiert werden.
|
- These can be downloaded and installed with just a few keystrokes.
|
||||||
- Dazu dient der _package manager_ `Pkg`.
|
- The _package manager_ `Pkg` is used for this purpose.
|
||||||
- Man kann ihn auf zwei Arten verwenden:
|
- It can be used in two ways:
|
||||||
- als normale Julia-Anweisungen, die auch in einer `.jl`-Programmdatei stehen können:
|
- as normal Julia statements that can also be in a `.jl` program file:
|
||||||
```
|
```
|
||||||
using Pkg
|
using Pkg
|
||||||
Pkg.add("PaketXY")
|
Pkg.add("PackageXY")
|
||||||
```
|
```
|
||||||
- im speziellen pkg-Modus des Julia-REPLs:
|
- in the special pkg-mode of the Julia REPL:
|
||||||
```
|
```
|
||||||
] add PaketXY
|
] add PackageXY
|
||||||
```
|
```
|
||||||
- Anschließend kann das Paket mit `using PaketXY` verwendet werden.
|
- Afterward, the package can be used with `using PackageXY`.
|
||||||
- Man kann auch Pakete aus anderen Quellen und selbstgeschriebene Pakete installieren.
|
- You can also install packages from other sources and self-written packages.
|
||||||
|
|
||||||
|
|
||||||
### Einige Funktionen des Paketmanagers
|
### Some Package Manager Functions
|
||||||
|
|
||||||
| Funktion | `pkg` - Mode | Erklärung |
|
| Function | `pkg` - Mode | Explanation |
|
||||||
|:------------------------|:--------------------------| :-------------------------------------------------------|
|
|:------------------------|:--------------------------| :-------------------------------------------------------|
|
||||||
| `Pkg.add("MyPack")` | `pkg> add MyPack` | add `MyPack.jl` to current environment |
|
| `Pkg.add("MyPack")` | `pkg> add MyPack` | add `MyPack.jl` to current environment |
|
||||||
| `Pkg.rm("MyPack")` | `pkg> remove MyPack` | remove `MyPack.jl` from current environment |
|
| `Pkg.rm("MyPack")` | `pkg> remove MyPack` | remove `MyPack.jl` from current environment |
|
||||||
@@ -120,13 +130,13 @@ Wichtiger Teil des _Julia Ecosystems_ sind die zahlreichen Pakete, die Julia erw
|
|||||||
| `Pkg.instantiate()` | `pg> instantiate` | install all packages according to `Project.toml` |
|
| `Pkg.instantiate()` | `pg> instantiate` | install all packages according to `Project.toml` |
|
||||||
|
|
||||||
|
|
||||||
### Installierte Pakete und Environments
|
### Installed Packages and Environments
|
||||||
|
|
||||||
- Julia und der Paketmanager verwalten
|
- Julia and the package manager maintain
|
||||||
1. eine Liste der mit dem Kommando `Pkg.add()` bzw. `]add` explizit installierten Pakete mit genauer Versionsbezeichnung in einer Datei `Project.toml` und
|
1. a list of packages explicitly installed with the command `Pkg.add()` or `]add` with exact version specifications in a file `Project.toml` and
|
||||||
2. eine Liste aller dabei auch als implizite Abhängigkeiten installierten Pakete in der Datei `Manifest.toml`.
|
2. a list of all packages installed as implicit dependencies in the file `Manifest.toml`.
|
||||||
- Das Verzeichnis, in dem diese Dateien stehen, ist das `environment` und wird mit `Pkg.status()` bzw. `]status` angezeigt.
|
- The directory in which these files are located is the `environment` and is displayed with `Pkg.status()` or `]status`.
|
||||||
- Im Normalfall sieht das so aus:
|
- In the normal case, this looks like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
(@v1.10) pkg> status
|
(@v1.10) pkg> status
|
||||||
@@ -137,18 +147,18 @@ Wichtiger Teil des _Julia Ecosystems_ sind die zahlreichen Pakete, die Julia erw
|
|||||||
[295af30f] Revise v3.5.14
|
[295af30f] Revise v3.5.14
|
||||||
```
|
```
|
||||||
|
|
||||||
- Man kann für verschiedene Projekte eigene `environments` benutzen. Dazu kann man entweder Julia mit
|
- You can use separate `environments` for different projects. You can either start Julia with
|
||||||
```shell
|
```shell
|
||||||
julia --project=path/to/myproject
|
julia --project=path/to/myproject
|
||||||
```
|
```
|
||||||
starten oder in Julia das environment mit `Pkg.activate("path/to/myproject")` aktivieren. Dann werden `Project.toml, Manifest.toml` dort angelegt und verwaltet. (Die Installation der Paketdateien erfolgt weiterhin irgendwo unter `$HOME/.julia`)
|
or activate the environment in Julia with `Pkg.activate("path/to/myproject")`. Then `Project.toml, Manifest.toml` are created and managed there. (The installation of package files still takes place somewhere under `$HOME/.julia`)
|
||||||
|
|
||||||
|
|
||||||
### Zum Installieren von Paketen auf unserem Jupyter-Server `misun103`:
|
### For Installing Packages on Our Jupyter Server `misun103`:
|
||||||
|
|
||||||
- Es gibt ein zentrales Repository, in dem alle in diesem Kurs erwähnten Pakete bereits installiert sind.
|
- There is a central repository in which all packages mentioned in this course are already installed.
|
||||||
- Dort haben Sie keine Schreibrechte.
|
- There you have no write permissions.
|
||||||
- Sie können aber zusätzliche Pakete in Ihrem `HOME` installieren. Dazu ist als erster Befehl nötig, das aktuelle Verzeichnis zu aktivieren:
|
- However, you can install additional packages in your `HOME`. As a first command, you need to activate the current directory:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -156,26 +166,27 @@ starten oder in Julia das environment mit `Pkg.activate("path/to/myproject")` ak
|
|||||||
] activate .
|
] activate .
|
||||||
```
|
```
|
||||||
|
|
||||||
(Man beachte den Punkt!)
|
(Note the dot!)
|
||||||
|
|
||||||
|
|
||||||
Danach können Sie mit `add` im Pkg-Modus auch Pakete installieren:
|
|
||||||
|
|
||||||
|
After that, you can install packages with `add` in the pkg-mode:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| eval: false
|
#| eval: false
|
||||||
] add PaketXY
|
] add PackageXY
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Achtung! Das kann dauern! Viele Pakete haben komplexe Abhängigkeiten und lösen die Installation von weiteren Paketen aus. Viele Pakete werden beim Installieren vorkompiliert. Im REPL sieht man den Installationsfortschritt, im Jupyter-Notebook leider nicht.
|
Warning! This can take a long time! Many packages have complex dependencies and trigger the installation of further packages. Many packages are precompiled during installation. You can see the installation progress in the REPL, but unfortunately not in the Jupyter notebook.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## The Julia JIT _(just in time)_ Compiler: Introspection
|
||||||
|
|
||||||
## Der Julia JIT _(just in time)_ Compiler: Introspection
|
Julia is built on the tools of the _LLVM Compiler Infrastructure Project_.
|
||||||
|
|
||||||
Julia baut auf die Werkzeuge des _LLVM Compiler Infrastructure Projects_ auf.
|
|
||||||
|
|
||||||
:::{.narrow}
|
:::{.narrow}
|
||||||
Stages of Compilation
|
Stages of Compilation
|
||||||
@@ -235,5 +246,3 @@ walk_tree(p)
|
|||||||
```{julia}
|
```{julia}
|
||||||
@code_native f(2,4)
|
@code_native f(2,4)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,73 +2,65 @@
|
|||||||
engine: julia
|
engine: julia
|
||||||
---
|
---
|
||||||
|
|
||||||
```{julia}
|
# Containers
|
||||||
#| error: false
|
|
||||||
#| echo: false
|
|
||||||
#| output: false
|
|
||||||
using InteractiveUtils
|
|
||||||
```
|
|
||||||
|
|
||||||
|
Julia offers a wide selection of container types with largely similar interfaces.
|
||||||
|
We introduce `Tuple`, `Range`, and `Dict` here, and in the next chapter we will cover `Array`, `Vector`, and `Matrix`.
|
||||||
|
|
||||||
# Container
|
These containers are:
|
||||||
|
|
||||||
Julia bietet eine große Auswahl von Containertypen mit weitgehend ähnlichem Interface an.
|
- **iterable:** You can iterate over the elements of the container:
|
||||||
Wir stellen hier `Tuple`, `Range` und `Dict` vor, im nächsten Kapitel dann `Array`, `Vector` und `Matrix`.
|
|
||||||
|
|
||||||
Diese Container sind:
|
|
||||||
|
|
||||||
- **iterierbar:** Man kann über die Elemente des Containers iterieren:
|
|
||||||
```julia
|
```julia
|
||||||
for x ∈ container ... end
|
for x ∈ container ... end
|
||||||
```
|
```
|
||||||
- **indizierbar:** Man kann auf Elemente über ihren Index zugreifen:
|
- **indexable:** You can access elements via their index:
|
||||||
```julia
|
```julia
|
||||||
x = container[i]
|
x = container[i]
|
||||||
```
|
```
|
||||||
und einige sind auch
|
and some are also
|
||||||
|
|
||||||
- **mutierbar**: Man kann Elemente hinzufügen, entfernen und ändern.
|
- **mutable:** You can add, remove, and modify elements.
|
||||||
|
|
||||||
Weiterhin gibt es eine Reihe gemeinsamer Funktionen, z.B.
|
Furthermore, there are several common functions, e.g.,
|
||||||
|
|
||||||
- `length(container)` --- Anzahl der Elemente
|
- `length(container)` --- number of elements
|
||||||
- `eltype(container)` --- Typ der Elemente
|
- `eltype(container)` --- type of elements
|
||||||
- `isempty(container)` --- Test, ob Container leer ist
|
- `isempty(container)` --- test whether container is empty
|
||||||
- `empty!(container)` --- leert Container (nur wenn mutierbar)
|
- `empty!(container)` --- empties container (only if mutable)
|
||||||
|
|
||||||
|
|
||||||
## Tupeln
|
## Tuples
|
||||||
|
|
||||||
Ein Tupel ist ein nicht mutierbarer Container von Elementen. Es ist also nicht möglich, neue Elemente dazuzufügen oder den Wert eines Elements zu ändern.
|
A tuple is an immutable container of elements. It is therefore not possible to add new elements or change the value of an element.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
t = (33, 4.5, "Hello")
|
t = (33, 4.5, "Hello")
|
||||||
|
|
||||||
@show t[2] # indizierbar
|
@show t[2] # indexable
|
||||||
|
|
||||||
for i ∈ t println(i) end # iterierbar
|
for i ∈ t println(i) end # iterable
|
||||||
```
|
```
|
||||||
|
|
||||||
Ein Tupel ist ein **inhomogener** Typ. Jedes Element hat seinen eigenen Typ und das zeigt sich auch im Typ des Tupels:
|
A tuple is an **inhomogeneous** type. Each element has its own type, which is reflected in the tuple's type:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
typeof(t)
|
typeof(t)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Man verwendet Tupel gerne als Rückgabewerte von Funktionen, um mehr als ein Objekt zurückzulieferen.
|
Tuples are frequently used as function return values to return more than one object.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
# Ganzzahldivision und Rest:
|
# Integer division and remainder:
|
||||||
# Quotient und Rest werden den Variablen q und r zugewiesen
|
# quotient and remainder are assigned to variables q and r
|
||||||
|
|
||||||
q, r = divrem(71, 6)
|
q, r = divrem(71, 6)
|
||||||
@show q r;
|
@show q r;
|
||||||
```
|
```
|
||||||
Wie man hier sieht, kann man in bestimmten Konstrukten die Klammern auch weglassen.
|
As you can see here, parentheses can be omitted in certain constructs.
|
||||||
Dieses *implict tuple packing/unpacking* verwendet man auch gerne in Mehrfachzuweisungen:
|
This *implicit tuple packing/unpacking* is also commonly used in multiple assignments:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -80,56 +72,59 @@ x, y, z = 12, 17, 203
|
|||||||
y
|
y
|
||||||
```
|
```
|
||||||
|
|
||||||
Manche Funktionen bestehen auf Tupeln als Argument oder geben immer Tupeln zurück. Dann braucht man manchmal ein Tupel aus einem Element.
|
Some functions require tuples as arguments or always return tuples. Then you sometimes need a tuple with a single element.
|
||||||
|
|
||||||
Das notiert man so:
|
This is written as:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = (13,) # ein 1-Element-Tupel
|
x = (13,) # a 1-element tuple
|
||||||
```
|
```
|
||||||
|
|
||||||
Das Komma - und nicht die Klammern -- macht das Tupel.
|
The comma - not the parentheses - makes the tuple.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x= (13) # kein Tupel
|
x= (13) # not a tuple
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Ranges
|
## Ranges
|
||||||
|
|
||||||
Wir haben *range*-Objekte schon in numerischen `for`-Schleifen verwendet.
|
We have already used *range* objects in numerical `for` loops.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
r = 1:1000
|
r = 1:1000
|
||||||
typeof(r)
|
typeof(r)
|
||||||
```
|
```
|
||||||
Es gibt verschiedene *range*-Typen. Wie man sieht, sind es über den Zahlentyp parametrisierte Typen und `UnitRange` ist z.B. ein *range* mit der Schrittweite 1. Ihre Konstruktoren heißen in der Regel `range()`.
|
There are various *range* types. As you can see, they are parameterized types based on the numeric type, and `UnitRange` is, for example, a *range* with step size 1. Their constructors are usually named `range()`.
|
||||||
|
|
||||||
Der Doppelpunkt ist eine spezielle Syntax.
|
The colon is a special syntax.
|
||||||
|
|
||||||
- `a:b` wird vom Parser umgesetzt zu `range(a, b)`
|
- `a:b` is parsed as `range(a, b)`
|
||||||
- `a:b:c` wird umgesetzt zu `range(a, c, step=b)`
|
- `a:b:c` is parsed as `range(a, c, step=b)`
|
||||||
|
|
||||||
|
|
||||||
*Ranges* sind offensichtlich iterierbar, nicht mutierbar aber indizierbar.
|
|
||||||
|
*Ranges* are obviously iterable, not mutable, but indexable.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
(3:100)[20] # das zwanzigste Element
|
(3:100)[20] # the 20th element
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Wir erinnern an die Semantik der `for`-Schleife: `for i in 1:1000` heißt **nicht**:
|
|
||||||
|
|
||||||
- 'Die Schleifenvariable `i` wird bei jedem Durchlauf um eins erhöht' **sondern**
|
Recall the semantics of the `for` loop: `for i in 1:1000` means **not**:
|
||||||
- 'Der Schleifenvariable werden nacheinander die Werte 1,2,3,...,1000 aus dem Container zugewiesen'.
|
|
||||||
|
|
||||||
Allerdings wäre es sehr ineffektiv, diesen Container tatsächlich explizit anzulegen.
|
- 'The loop variable `i` is incremented by one in each iteration' **but rather**
|
||||||
|
- 'The loop variable is successively assigned the values 1,2,3,...,1000 from the container'.
|
||||||
|
|
||||||
- _Ranges_ sind "lazy" Vektoren, die nie wirklich irgendwo als konkrete Liste abgespeichert werden. Das macht sie als Iteratoren in `for`-Schleifen so nützlich: speichersparend und schnell.
|
However, it would be very inefficient to actually create this container explicitly.
|
||||||
- Sie sind 'Rezepte' oder Generatoren, die auf die Abfrage 'Gib mir dein nächstes Element!' antworten.
|
|
||||||
- Tatsächlich ist der Muttertyp `AbstractRange` ein Subtyp von `AbstractVector`.
|
|
||||||
|
|
||||||
Das Macro `@allocated` gibt aus, wieviel Bytes an Speicher bei der Auswertung eines Ausdrucks alloziert wurden.
|
- _Ranges_ are "lazy" vectors that are never really stored as a concrete list anywhere. This makes them so useful as iterators in `for` loops: memory-efficient and fast.
|
||||||
|
- They are "recipes" or generators that respond to the query "Give me your next element!".
|
||||||
|
- In fact, the supertype `AbstractRange` is a subtype of `AbstractVector`.
|
||||||
|
|
||||||
|
The macro `@allocated` outputs how many bytes of memory were allocated during the evaluation of an expression.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@allocated r = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
|
@allocated r = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
|
||||||
@@ -142,34 +137,35 @@ Das Macro `@allocated` gibt aus, wieviel Bytes an Speicher bei der Auswertung ei
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Zum Umwandeln in einen 'richtigen' Vektor dient die Funktion `collect()`.
|
|
||||||
|
The function `collect()` is used to convert to a "real" vector.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
collect(20:-3:1)
|
collect(20:-3:1)
|
||||||
```
|
```
|
||||||
|
|
||||||
Recht nützlich, z.B. beim Vorbereiten von Daten zum Plotten, ist der *range*-Typ `LinRange`.
|
Quite useful, e.g., when preparing data for plotting, is the *range* type `LinRange`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
LinRange(2, 50, 300)
|
LinRange(2, 50, 300)
|
||||||
```
|
```
|
||||||
`LinRange(start, stop, n)` erzeugt eine äquidistante Liste von `n` Werten von denen der erste und der letzte die vorgegebenen Grenzen sind.
|
`LinRange(start, stop, n)` generates an equidistant list of `n` values where the first and last are the specified limits.
|
||||||
Mit `collect()` kann man bei Bedarf auch daraus den entsprechenden Vektor gewinnen.
|
With `collect()` you can also obtain the corresponding vector if needed.
|
||||||
|
|
||||||
|
|
||||||
## Dictionaries
|
## Dictionaries
|
||||||
|
|
||||||
- _Dictionaries_ (deutsch: "assoziative Liste" oder "Zuordnungstabelle" oder ...) sind spezielle Container.
|
- _Dictionaries_ (German: "associative list" or "lookup table" or ...) are special containers.
|
||||||
- Einträge in einem Vektor `v` sind durch einen Index 1,2,3.... addressierbar: `v[i]`
|
- Entries in a vector `v` are addressable by an index 1,2,3....: `v[i]`
|
||||||
- Einträge in einem _dictionary_ sind durch allgemeinere _keys_ addressierbar.
|
- Entries in a _dictionary_ are addressable by more general _keys_.
|
||||||
- Ein _dictionary_ ist eine Ansammlung von _key-value_-Paaren.
|
- A _dictionary_ is a collection of _key-value_ pairs.
|
||||||
- Damit haben _dictionaries_ in Julia den parametrisierten Typ `Dict{S,T}`, wobei `S` der Typ der _keys_ und `T` der Typ der _values_ ist
|
- Thus, _dictionaries_ in Julia have the parameterized type `Dict{S,T}`, where `S` is the type of _keys_ and `T` is the type of _values_.
|
||||||
|
|
||||||
|
|
||||||
Man kann sie explizit anlegen:
|
They can be created explicitly:
|
||||||
```{julia}
|
```{julia}
|
||||||
# Einwohner 2020 in Millionen, Quelle: wikipedia
|
# Population in 2020 in millions, source: wikipedia
|
||||||
|
|
||||||
EW = Dict("Berlin" => 3.66, "Hamburg" => 1.85,
|
EW = Dict("Berlin" => 3.66, "Hamburg" => 1.85,
|
||||||
"München" => 1.49, "Köln" => 1.08)
|
"München" => 1.49, "Köln" => 1.08)
|
||||||
@@ -180,29 +176,29 @@ EW = Dict("Berlin" => 3.66, "Hamburg" => 1.85,
|
|||||||
typeof(EW)
|
typeof(EW)
|
||||||
```
|
```
|
||||||
|
|
||||||
und mit den _keys_ indizieren:
|
and indexed with the _keys_:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
EW["Berlin"]
|
EW["Berlin"]
|
||||||
```
|
```
|
||||||
|
|
||||||
Das Abfragen eines nicht existierenden _keys_ ist natürlich ein Fehler.
|
Of course, querying a non-existent _key_ is an error.
|
||||||
```{julia}
|
```{julia}
|
||||||
EW["Leipzig"]
|
EW["Leipzig"]
|
||||||
```
|
```
|
||||||
|
|
||||||
Man kann ja auch vorher mal anfragen...
|
You can also ask beforehand...
|
||||||
```{julia}
|
```{julia}
|
||||||
haskey(EW, "Leipzig")
|
haskey(EW, "Leipzig")
|
||||||
```
|
```
|
||||||
|
|
||||||
... oder die Funktion `get(dict, key, default)` benutzen, die bei nicht existierendem Key keinen Fehler wirft sondern das 3. Argument zurückgibt.
|
... or use the function `get(dict, key, default)`, which does not throw an error for non-existent keys but returns the third argument.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show get(EW, "Leipzig", -1) get(EW, "Berlin", -1);
|
@show get(EW, "Leipzig", -1) get(EW, "Berlin", -1);
|
||||||
```
|
```
|
||||||
|
|
||||||
Man kann sich auch alle `keys` und `values` als spezielle Container geben lassen.
|
You can also request all `keys` and `values` as special containers.
|
||||||
```{julia}
|
```{julia}
|
||||||
keys(EW)
|
keys(EW)
|
||||||
```
|
```
|
||||||
@@ -213,24 +209,24 @@ values(EW)
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Man kann über die `keys` iterieren...
|
You can iterate over the `keys`...
|
||||||
```{julia}
|
```{julia}
|
||||||
for i in keys(EW)
|
for i in keys(EW)
|
||||||
n = EW[i]
|
n = EW[i]
|
||||||
println("Die Stadt $i hat $n Millionen Einwohner.")
|
println("The city $i has $n million inhabitants.")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
odere gleich über `key-value`-Paare.
|
or directly over `key-value` pairs.
|
||||||
```{julia}
|
```{julia}
|
||||||
for (stadt, ew) ∈ EW
|
for (stadt, ew) ∈ EW
|
||||||
println("$stadt : $ew Mill.")
|
println("$stadt : $ew Million.")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
### Erweitern und Modifizieren
|
### Extending and Modifying
|
||||||
|
|
||||||
Man kann in ein `Dict` zusätzliche `key-value`-Paare eintragen...
|
You can add additional `key-value` pairs to a `Dict`...
|
||||||
```{julia}
|
```{julia}
|
||||||
EW["Leipzig"] = 0.52
|
EW["Leipzig"] = 0.52
|
||||||
EW["Dresden"] = 0.52
|
EW["Dresden"] = 0.52
|
||||||
@@ -238,42 +234,42 @@ EW
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
und einen `value` ändern.
|
and change a `value`.
|
||||||
```{julia}
|
```{julia}
|
||||||
# Oh, das war bei Leipzig die Zahl von 2010, nicht 2020
|
# Oh, the Leipzig number was from 2010, not 2020
|
||||||
|
|
||||||
EW["Leipzig"] = 0.597
|
EW["Leipzig"] = 0.597
|
||||||
EW
|
EW
|
||||||
```
|
```
|
||||||
|
|
||||||
Ein Paar kann über seinen `key` auch gelöscht werden.
|
A pair can also be deleted via its `key`.
|
||||||
```{julia}
|
```{julia}
|
||||||
delete!(EW, "Dresden")
|
delete!(EW, "Dresden")
|
||||||
```
|
```
|
||||||
|
|
||||||
Zahlreiche Funktionen können mit `Dicts` wie mit anderen Containern arbeiten.
|
Many functions can work with `Dicts` like with other containers.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
maximum(values(EW))
|
maximum(values(EW))
|
||||||
```
|
```
|
||||||
|
|
||||||
### Anlegen eines leeren Dictionaries
|
### Creating an Empty Dictionary
|
||||||
|
|
||||||
Ohne Typspezifikation ...
|
Without type specification ...
|
||||||
```{julia}
|
```{julia}
|
||||||
d1 = Dict()
|
d1 = Dict()
|
||||||
```
|
```
|
||||||
|
|
||||||
und mit Typspezifikation:
|
and with type specification:
|
||||||
```{julia}
|
```{julia}
|
||||||
d2 = Dict{String, Int}()
|
d2 = Dict{String, Int}()
|
||||||
```
|
```
|
||||||
|
|
||||||
### Umwandlung in Vektoren: `collect()`
|
### Conversion to Vectors: `collect()`
|
||||||
|
|
||||||
- `keys(dict)` und `values(dict)` sind spezielle Datentypen.
|
- `keys(dict)` and `values(dict)` are special data types.
|
||||||
- Die Funktion `collect()` macht daraus eine Liste vom Typ `Vector`.
|
- The function `collect()` converts them to a `Vector` type.
|
||||||
- `collect(dict)` liefert eine Liste vom Typ `Vector{Pair{S,T}}`
|
- `collect(dict)` returns a list of type `Vector{Pair{S,T}}`
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -285,55 +281,55 @@ collect(EW)
|
|||||||
collect(keys(EW)), collect(values(EW))
|
collect(keys(EW)), collect(values(EW))
|
||||||
```
|
```
|
||||||
|
|
||||||
### Geordnetes Iterieren über ein Dictionary
|
### Ordered Iteration over a Dictionary
|
||||||
|
|
||||||
Wir sortieren die Keys. Als Strings werden sie alphabetisch sortiert. Mit dem `rev`-Parameter wird rückwärts sortiert.
|
We sort the keys. As strings, they are sorted alphabetically. With the `rev` parameter, sorting is done in reverse order.
|
||||||
```{julia}
|
```{julia}
|
||||||
for k in sort(collect(keys(EW)), rev = true)
|
for k in sort(collect(keys(EW)), rev = true)
|
||||||
n = EW[k]
|
n = EW[k]
|
||||||
println("$k hat $n Millionen Einw. ")
|
println("$k has $n million inhabitants ")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Wir sortieren `collect(dict)`. Das ist ein Vektor von Paaren. Mit `by` definieren wir, wonach zu sortieren ist: nach dem 2. Element des Paares.
|
We sort `collect(dict)`. This is a vector of pairs. With `by` we define what to sort by: the second element of the pair.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
for (k,v) in sort(collect(EW), by = pair -> last(pair), rev=false)
|
for (k,v) in sort(collect(EW), by = pair -> last(pair), rev=false)
|
||||||
println("$k hat $v Mill. EW")
|
println("$k has $v million inhabitants")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
### Eine Anwendung von Dictionaries: Zählen von Häufigkeiten
|
### An Application of Dictionaries: Counting Frequencies
|
||||||
|
|
||||||
Wir machen 'experimentelle Stochastik' mit 2 Würfeln:
|
We do "experimental probability" with 2 dice:
|
||||||
|
|
||||||
Gegeben sei `l`, eine Liste mit den Ergebnissen von 100 000 Pasch-Würfen, also 100 000 Zahlen zwischen 2 und 12.
|
Given `l`, a list with the results of 100,000 double dice rolls, i.e., 100,000 numbers between 2 and 12.
|
||||||
|
|
||||||
Wie häufig sind die Zahlen 2 bis 12?
|
How frequently do the numbers 2 to 12 occur?
|
||||||
|
|
||||||
|
|
||||||
Wir (lassen) würfeln:
|
We (let) roll:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
|
|
||||||
l = rand(1:6, 100_000) .+ rand(1:6, 100_000)
|
l = rand(1:6, 100_000) .+ rand(1:6, 100_000)
|
||||||
```
|
```
|
||||||
|
|
||||||
Wir zählen mit Hilfe eines Dictionaries die Häufigkeiten der Ereignisse. Dazu nehmen wir das Ereignis als `key` und seine Häufigkeit als `value`.
|
We count the frequencies of the events using a dictionary. We take the event as the `key` and its frequency as the `value`.
|
||||||
```{julia}
|
```{julia}
|
||||||
# In diesem Fall könnte man das auch mit einem einfachen Vektor
|
# In this case, one could also solve this with a simple vector.
|
||||||
# lösen. Eine bessere Illustration wäre z.B. Worthäufigkeit in
|
# A better illustration would be, e.g., word frequency in
|
||||||
# einem Text. Dann ist i keine ganze Zahl sondern ein Wort=String
|
# a text. Then i is not an integer but a word=string
|
||||||
|
|
||||||
d = Dict{Int,Int}() # das Dict zum 'reinzählen'
|
d = Dict{Int,Int}() # the dict for counting
|
||||||
|
|
||||||
for i in l # für jedes i wird d[i] erhöht.
|
for i in l # for each i, d[i] is incremented.
|
||||||
d[i] = get(d, i, 0) + 1
|
d[i] = get(d, i, 0) + 1
|
||||||
end
|
end
|
||||||
d
|
d
|
||||||
```
|
```
|
||||||
|
|
||||||
Das Ergebnis:
|
The result:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using Plots
|
using Plots
|
||||||
@@ -341,7 +337,6 @@ using Plots
|
|||||||
plot(collect(keys(d)), collect(values(d)), seriestype=:scatter)
|
plot(collect(keys(d)), collect(values(d)), seriestype=:scatter)
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Das Erklär-Bild dazu:
|
##### The explanatory image:
|
||||||
|
|
||||||
[https://math.stackexchange.com/questions/1204396/why-is-the-sum-of-the-rolls-of-two-dices-a-binomial-distribution-what-is-define](https://math.stackexchange.com/questions/1204396/why-is-the-sum-of-the-rolls-of-two-dices-a-binomial-distribution-what-is-define)
|
[https://math.stackexchange.com/questions/1204396/why-is-the-sum-of-the-rolls-of-two-dices-a-binomial-distribution-what-is-define](https://math.stackexchange.com/questions/1204396/why-is-the-sum-of-the-rolls-of-two-dices-a-binomial-distribution-what-is-define)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
|||||||
engine: julia
|
engine: julia
|
||||||
---
|
---
|
||||||
|
|
||||||
# Funktionen und Operatoren
|
# Functions and Operators
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: false
|
#| error: false
|
||||||
@@ -18,36 +18,36 @@ Base.active_module() = myactive_module()
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Funktionen verarbeiten ihre Argumente zu einem Ergebnis, das sie beim Aufruf zurückliefern.
|
Functions process their arguments to produce a result, which they return when called.
|
||||||
|
|
||||||
## Formen
|
## Forms
|
||||||
|
|
||||||
Funktionen können in verschiedenen Formen definiert werden:
|
Functions can be defined in different forms:
|
||||||
|
|
||||||
I. Als `function ... end`-Block
|
I. As a `function ... end` block
|
||||||
```{julia}
|
```{julia}
|
||||||
function hyp(x,y)
|
function hyp(x,y)
|
||||||
sqrt(x^2+y^2)
|
sqrt(x^2+y^2)
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
II. Als "Einzeiler"
|
II. As a "single-liner"
|
||||||
```{julia}
|
```{julia}
|
||||||
hyp(x, y) = sqrt(x^2 + y^2)
|
hyp(x, y) = sqrt(x^2 + y^2)
|
||||||
```
|
```
|
||||||
III. Als anonyme Funktionen
|
III. As anonymous functions
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
(x, y) -> sqrt(x^2 + y^2)
|
(x, y) -> sqrt(x^2 + y^2)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Block-Form und `return`
|
### Block Form and `return`
|
||||||
|
|
||||||
|
|
||||||
- Mit `return` wird die Abarbeitung der Funktion beendet und zum aufrufenden Kontext zurückgekehrt.
|
- With `return`, function execution is terminated and control returns to the calling context.
|
||||||
- Ohne `return` wird der Wert des letzten Ausdrucks als Funktionswert zurückgegeben.
|
- Without `return`, the value of the last expression is returned as the function value.
|
||||||
|
|
||||||
Die beiden Definitionen
|
The two definitions
|
||||||
|
|
||||||
```julia
|
```julia
|
||||||
function xsinrecipx(x)
|
function xsinrecipx(x)
|
||||||
@@ -57,7 +57,7 @@ function xsinrecipx(x)
|
|||||||
return x * sin(1/x)
|
return x * sin(1/x)
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
und ohne das zweite explizite `return` in der letzten Zeile:
|
and without the second explicit `return` in the last line:
|
||||||
|
|
||||||
```julia
|
```julia
|
||||||
function xsinrecipx(x)
|
function xsinrecipx(x)
|
||||||
@@ -68,11 +68,11 @@ function xsinrecipx(x)
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
sind also äquivalent.
|
are therefore equivalent.
|
||||||
|
|
||||||
|
|
||||||
- Eine Funktion, die "nichts" zurückgibt (_void functions_ in der C-Welt), gibt den Wert `nothing` vom Typ `Nothing` zurück. (So wie ein Objekt vom Typ `Bool` die beiden Werte `true` und `false` haben kann, so kann ein Objekt vom Typ `Nothing` nur einen einzigen Wert, eben `nothing`, annehmen.)
|
- A function that returns "nothing" (_void functions_ in the C world) returns the value `nothing` of type `Nothing`. (Just as an object of type `Bool` can have two values, `true` and `false`, an object of type `Nothing` can only take a single value, namely `nothing`.)
|
||||||
- Eine leere `return`-Anweisung ist äquivalent zu `return nothing`.
|
- An empty `return` statement is equivalent to `return nothing`.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -95,27 +95,27 @@ a
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Einzeiler-Form
|
### Single-liner Form
|
||||||
|
|
||||||
Die Einzeilerform ist eine ganz normale Zuweisung, bei der links eine Funktion steht.
|
The single-liner form is a normal assignment where a function stands on the left side.
|
||||||
|
|
||||||
```julia
|
```julia
|
||||||
hyp(x, y) = sqrt(x^2 + y^2)
|
hyp(x, y) = sqrt(x^2 + y^2)
|
||||||
```
|
```
|
||||||
|
|
||||||
Julia kennt zwei Möglichkeiten, mehrere Anweisungen zu einem Block zusammenzufassen, der an Stelle einer Einzelanweisung stehen kann:
|
Julia knows two ways to combine multiple statements into a block that can stand in place of a single statement:
|
||||||
|
|
||||||
- `begin ... end`-Block
|
- `begin ... end` block
|
||||||
- Eingeklammerte durch Semikolon getrennte Anweisungen.
|
- Parenthesized statements separated by semicolons.
|
||||||
|
|
||||||
In beiden Fällen ist der Wert des Blockes der Wert der letzten Anweisung.
|
In both cases, the value of the block is the value of the last statement.
|
||||||
|
|
||||||
Damit funktioniert auch
|
Thus, the following also works:
|
||||||
```julia
|
```julia
|
||||||
hyp(x, y) = (z = x^2; z += y^2; sqrt(z))
|
hyp(x, y) = (z = x^2; z += y^2; sqrt(z))
|
||||||
```
|
```
|
||||||
|
|
||||||
und
|
and
|
||||||
```julia
|
```julia
|
||||||
hyp(x, y) = begin
|
hyp(x, y) = begin
|
||||||
z = x^2
|
z = x^2
|
||||||
@@ -124,15 +124,15 @@ hyp(x, y) = begin
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
### Anonyme Funktionen
|
### Anonymous Functions
|
||||||
|
|
||||||
Anonyme FUnktionen kann man der Anonymität entreisen, indem man ihnen einen Namen zuweist.
|
Anonymous functions can be "rescued from anonymity" by assigning them a name.
|
||||||
```julia
|
```julia
|
||||||
hyp = (x,y) -> sqrt(x^2 + y^2)
|
hyp = (x,y) -> sqrt(x^2 + y^2)
|
||||||
```
|
```
|
||||||
Ihre eigentliche Anwendung ist aber im Aufruf einer *(higher order)* Funktion, die eine Funktion als Argument erwartet.
|
Their actual application is in calling a *(higher order)* function that expects a function as an argument.
|
||||||
|
|
||||||
Typische Anwendungen sind `map(f, collection)`, welches eine Funktion auf alle Elemente einer Kollektion anwendet. In Julia funktioniert auch `map(f(x,y), collection1, collection2)`:
|
Typical applications are `map(f, collection)`, which applies a function to all elements of a collection. In Julia, `map(f(x,y), collection1, collection2)` also works:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
map( (x,y) -> sqrt(x^2 + y^2), [3, 5, 8], [4, 12, 15])
|
map( (x,y) -> sqrt(x^2 + y^2), [3, 5, 8], [4, 12, 15])
|
||||||
@@ -142,24 +142,24 @@ map( (x,y) -> sqrt(x^2 + y^2), [3, 5, 8], [4, 12, 15])
|
|||||||
map( x->3x^3, 1:8 )
|
map( x->3x^3, 1:8 )
|
||||||
```
|
```
|
||||||
|
|
||||||
Ein weiteres Beispiel ist `filter(test, collection)`, wobei ein Test eine Funktion ist, die ein `Bool` zurückgibt.
|
Another example is `filter(test, collection)`, where a test is a function that returns a `Bool`.
|
||||||
```{julia}
|
```{julia}
|
||||||
filter(x -> ( x%3 == 0 && x%5 == 0), 1:100 )
|
filter(x -> ( x%3 == 0 && x%5 == 0), 1:100 )
|
||||||
```
|
```
|
||||||
|
|
||||||
## Argumentübergabe
|
## Argument Passing
|
||||||
|
|
||||||
|
|
||||||
- Beim Funktionsaufruf werden von den als Funktionsargumente zu übergebenden Objekten keine Kopien gemacht. Die Variablen in der Funktion verweisen auf die Originalobjekte. Julia nennt dieses Konzept _pass_by_sharing_.
|
- When calling a function, no copies are made of the objects passed as function arguments. Variables in the function refer to the original objects. Julia calls this concept _pass_by_sharing_.
|
||||||
- Funktionen können also ihre Argumente wirksam modifizieren, falls es sich um _mutable_ Objekte, wie z.B. `Vector`, `Array` handelt.
|
- Functions can therefore effectively modify their arguments if they are _mutable_ objects, such as `Vector` or `Array`.
|
||||||
- Es ist eine Konvention in Julia, dass die Namen von solchen argumentmodifizierenden Funktionen mit einem Ausrufungszeichen enden. Weiterhin steht dann üblicherweise das Argument, das modifiziert wird, an erster Stelle und es ist auch der Rückgabewert der Funktion.
|
- It is a convention in Julia that the names of such argument-modifying functions end with an exclamation mark. Furthermore, the argument that is modified is usually first and is also the return value of the function.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
V = [1, 2, 3]
|
V = [1, 2, 3]
|
||||||
|
|
||||||
W = fill!(V, 17)
|
W = fill!(V, 17)
|
||||||
# '===' ist Test auf Identität
|
# '===' is test for identity
|
||||||
@show V W V===W; # V und W benennen dasselbe Objekt
|
@show V W V===W; # V and W refer to the same object
|
||||||
```
|
```
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -175,16 +175,16 @@ U = fill_first!(V, 42)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Varianten von Funktionsargumenten
|
## Variants of Function Arguments
|
||||||
|
|
||||||
- Es gibt Positionsargumente (1. Argument, 2. Argument, ....) und _keyword_-Argumente, die beim Aufruf durch ihren Namen angesprochen werden müssen.
|
- There are positional arguments (1st argument, 2nd argument, ...) and _keyword_ arguments, which must be addressed by name when calling.
|
||||||
- Sowohl Positions- als auch _keyword_-Argumente können _default_-Werte haben. Beim Aufruf können diese Argumente weggelassen werden.
|
- Both positional and _keyword_ arguments can have _default_ values. These arguments can be omitted when calling.
|
||||||
- Die Reihenfolge der Deklaration muss sein:
|
- The order of declaration must be:
|
||||||
1. Positionsargumente ohne Defaultwert,
|
1. Positional arguments without default value,
|
||||||
2. Positionsargumente mit Defaultwert,
|
2. Positional arguments with default value,
|
||||||
3. --- Semikolon ---,
|
3. --- semicolon ---,
|
||||||
4. kommagetrennte Liste der Keywordargumente (mit oder ohne Defaultwert)
|
4. comma-separated list of keyword arguments (with or without default value)
|
||||||
- Beim Aufruf können _keyword_-Argumente an beliebigen Stellen in beliebiger Reihenfolge stehen. Man kann sie wieder durch ein Semikolon von den Positionsargumenten abtrennen, muss aber nicht.
|
- When calling, _keyword_ arguments can appear at any position in any order. You can separate them from positional arguments with a semicolon, but you don't have to.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
fa(x, y=42; a) = println("x=$x, y=$y, a=$a")
|
fa(x, y=42; a) = println("x=$x, y=$y, a=$a")
|
||||||
@@ -194,7 +194,7 @@ fa(6, 7; a=4)
|
|||||||
fa(a=-2, 6)
|
fa(a=-2, 6)
|
||||||
```
|
```
|
||||||
|
|
||||||
Eine Funktion nur mit _keyword_-Argumenten wird so deklariert:
|
A function with only _keyword_ arguments is declared as follows:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
fkw(; x=10, y) = println("x=$x, y=$y")
|
fkw(; x=10, y) = println("x=$x, y=$y")
|
||||||
@@ -204,9 +204,9 @@ fkw(y=2)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Funktionen sind ganz normale Objekte
|
## Functions are Normal Objects
|
||||||
|
|
||||||
- Sie können zugewiesen werden
|
- They can be assigned
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -215,11 +215,11 @@ f2(2)
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
- Sie können als Argumente an Funktionen übergeben werden.
|
- They can be passed as arguments to functions.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
# sehr naive numerische Integration
|
# very naive numerical integration
|
||||||
|
|
||||||
function Riemann_integrate(f, a, b; NInter=1000)
|
function Riemann_integrate(f, a, b; NInter=1000)
|
||||||
delta = (b-a)/NInter
|
delta = (b-a)/NInter
|
||||||
@@ -235,7 +235,7 @@ Riemann_integrate(sin, 0, π)
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
- Sie können von Funktionen erzeugt und als Ergebnis `return`t werden.
|
- They can be created by functions and returned as results.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -263,16 +263,16 @@ h(1)
|
|||||||
h(2), h(10)
|
h(2), h(10)
|
||||||
```
|
```
|
||||||
|
|
||||||
Die obige Funktion `generate_add_func()` lässt sich auch kürzer definieren. Der innere Funktionsname `addx()` ist sowieso lokal und außerhalb nicht verfügbar. Also kann man eine anonyme Funktion verwenden.
|
The above function `generate_add_func()` can also be defined more briefly. The inner function name `addx()` is anyway local and not available outside. So one can use an anonymous function.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
generate_add_func(x) = y -> x + y
|
generate_add_func(x) = y -> x + y
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Zusammensetzung von Funktionen: die Operatoren $\circ$ und `|>`
|
## Function Composition: the Operators $\circ$ and `|>`
|
||||||
|
|
||||||
- Die Zusammensetzung _(composition)_ von Funktionen kann auch mit dem Operator $\circ$ (`\circ + Tab`) geschrieben werden
|
- Function composition can also be written with the $\circ$ operator (`\circ + Tab`)
|
||||||
|
|
||||||
$$(f\circ g)(x) = f(g(x))$$
|
$$(f\circ g)(x) = f(g(x))$$
|
||||||
|
|
||||||
@@ -289,11 +289,11 @@ f(.2)
|
|||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show map(uppercase ∘ first, ["ein", "paar", "grüne", "Blätter"]);
|
@show map(uppercase ∘ first, ["one", "a", "green", "leaves"]);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
- Es gibt auch einen Operator, mit dem Funktionen "von rechts" wirken und zusammengesetzt werden können _(piping)_
|
- There is also an operator with which functions can act "from the right" and be composed (_piping_)
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -306,37 +306,37 @@ f(.2)
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
- Natürlich kann man auch diese Operatoren 'broadcasten' (s. @sec-broadcast). Hier wirkt ein Vektor von Funktionen elementweise auf einen Vektor von Argumenten:
|
- Of course, you can also 'broadcast' these operators (see @sec-broadcast). Here a vector of functions acts element-wise on a vector of arguments:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
["a", "list", "of", "strings"] .|> [length, uppercase, reverse, titlecase]
|
["a", "list", "of", "strings"] .|> [length, uppercase, reverse, titlecase]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Die `do`-Notation {#sec-do}
|
## The `do` Notation {#sec-do}
|
||||||
|
|
||||||
Eine syntaktische Besonderheit zur Definition anonymer Funktionen als Argumente anderer Funktionen ist die `do`-Notation.
|
A syntactic peculiarity for defining anonymous functions as arguments of other functions is the `do` notation.
|
||||||
|
|
||||||
Sei `higherfunc(f,a,...)` eine Funktion, deren 1. Argument eine Funktion ist.
|
Let `higherfunc(f,a,...)` be a function whose first argument is a function.
|
||||||
|
|
||||||
Dann kann man `higherfunc()` auch ohne erstes Argument aufrufen und statt dessen die Funktion in einem unmittelbar folgenden `do`-Block definieren:
|
Then you can also call `higherfunc()` without the first argument and instead define the function in an immediately following `do` block:
|
||||||
|
|
||||||
```julia
|
```julia
|
||||||
higherfunc(a, b) do x, y
|
higherfunc(a, b) do x, y
|
||||||
Körper von f(x,y)
|
body of f(x,y)
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Am Beispiel von `Riemann_integrate()` sieht das so aus:
|
Using `Riemann_integrate()` as an example, this looks like this:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
# das ist dasselbe wie Riemann_integrate(x->x^2, 0, 2)
|
# this is the same as Riemann_integrate(x->x^2, 0, 2)
|
||||||
|
|
||||||
Riemann_integrate(0, 2) do x x^2 end
|
Riemann_integrate(0, 2) do x x^2 end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Der Sinn besteht natürlich in der Anwendung mit komplexeren Funktionen, wie diesem aus zwei Teilstücken zusammengesetzten Integranden:
|
The purpose is of course in the application with more complex functions, such as this integrand composed of two parts:
|
||||||
```{julia}
|
```{julia}
|
||||||
r = Riemann_integrate(0, π) do x
|
r = Riemann_integrate(0, π) do x
|
||||||
z1 = sin(x)
|
z1 = sin(x)
|
||||||
@@ -349,12 +349,12 @@ r = Riemann_integrate(0, π) do x
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
## Funktionsartige Objekte
|
## Function-like Objects
|
||||||
|
|
||||||
Durch Definition einer geeigneten Methode für einen Typ kann man beliebige Objekte *callable* machen, d.h., sie anschließend wie Funktionen aufrufen.
|
By defining a suitable method for a type, arbitrary objects can be made *callable*, i.e., callable like functions afterwards.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
# struct speichert die Koeffiziente eines Polynoms 2. Grades
|
# struct stores the coefficients of a 2nd degree polynomial
|
||||||
struct Poly2Grad
|
struct Poly2Grad
|
||||||
a0::Float64
|
a0::Float64
|
||||||
a1::Float64
|
a1::Float64
|
||||||
@@ -365,13 +365,13 @@ p1 = Poly2Grad(2,5,1)
|
|||||||
p2 = Poly2Grad(3,1,-0.4)
|
p2 = Poly2Grad(3,1,-0.4)
|
||||||
```
|
```
|
||||||
|
|
||||||
Die folgende Methode macht diese Struktur `callable`.
|
The following method makes this structure `callable`.
|
||||||
```{julia}
|
```{julia}
|
||||||
function (p::Poly2Grad)(x)
|
function (p::Poly2Grad)(x)
|
||||||
p.a2 * x^2 + p.a1 * x + p.a0
|
p.a2 * x^2 + p.a1 * x + p.a0
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
Jetzt kann man die Objekte, wenn gewünscht, auch wie Funktionen verwenden.
|
Now the objects can, if desired, also be used like functions.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show p2(5) p1(-0.7) p1;
|
@show p2(5) p1(-0.7) p1;
|
||||||
@@ -379,9 +379,9 @@ Jetzt kann man die Objekte, wenn gewünscht, auch wie Funktionen verwenden.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Operatoren und spezielle Formen
|
## Operators and Special Forms
|
||||||
|
|
||||||
- Infix-Operatoren wie `+,*,>,∈,...` sind Funktionen.
|
- Infix operators like `+,*,>,∈,...` are functions.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -399,7 +399,7 @@ f = +
|
|||||||
f(3, 7)
|
f(3, 7)
|
||||||
```
|
```
|
||||||
|
|
||||||
- Auch Konstruktionen wie `x[i]`, `a.x`, `[x; y]` werden vom Parser zu Funktionsaufrufen umgewandelt.
|
- Even constructions like `x[i]`, `a.x`, `[x; y]` are converted by the parser to function calls.
|
||||||
|
|
||||||
:::{.narrow}
|
:::{.narrow}
|
||||||
|
|
||||||
@@ -410,53 +410,53 @@ f(3, 7)
|
|||||||
| a.x | getproperty(a, :x) |
|
| a.x | getproperty(a, :x) |
|
||||||
| a.x = z | setproperty!(a, :x, z) |
|
| a.x = z | setproperty!(a, :x, z) |
|
||||||
| [x; y;...] | vcat(x, y, ...) |
|
| [x; y;...] | vcat(x, y, ...) |
|
||||||
:Spezielle Formen [(Auswahl)](https://docs.julialang.org/en/v1/manual/functions/#Operators-With-Special-Names)
|
:Special Forms [(selection)](https://docs.julialang.org/en/v1/manual/functions/#Operators-With-Special-Names)
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
(Der Doppelpunkt vor einer Variablen macht diese zu einem Symbol.)
|
(The colon before a variable makes it into a symbol.)
|
||||||
|
|
||||||
:::{.callout-note}
|
:::{.callout-note}
|
||||||
Für diese Funktionen kann man eigene Methoden implementieren. Zum Beispiel könnten bei einem eigenen Typ das Setzen eines Feldes (`setproperty!()`) die Gültigkeit des Wertes prüfen oder weitere Aktionen veranlassen.
|
For these functions, one can implement one's own methods. For example, for a custom type, setting a field (`setproperty!()`) could check the validity of the value or trigger further actions.
|
||||||
|
|
||||||
Prinzipiell können `get/setproperty` auch Dinge tun, die gar nichts mit einem tatsächlich vorhandenen Feld der Struktur zu tun haben.
|
In principle, `get/setproperty` can also do things that have nothing to do with an actually existing field of the structure.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Update-Form
|
## Update Form
|
||||||
|
|
||||||
Alle arithmetischen Infix-Operatoren haben eine update-Form: Der Ausdruck
|
All arithmetic infix operators have an update form: The expression
|
||||||
```julia
|
```julia
|
||||||
x = x ⊙ y
|
x = x ⊙ y
|
||||||
```
|
```
|
||||||
kann auch geschrieben werden als
|
can also be written as
|
||||||
```julia
|
```julia
|
||||||
x ⊙= y
|
x ⊙= y
|
||||||
```
|
```
|
||||||
|
|
||||||
Beide Formen sind semantisch äquivalent. Insbesondere wird in beiden Formen der Variablen `x` ein auf der rechten Seite geschaffenes neues Objekt zugewiesen.
|
Both forms are semantically equivalent. In particular, in both forms, a new object created on the right side is assigned to the variable `x`.
|
||||||
|
|
||||||
Ein Speicherplatz- und Zeit-sparendes __in-place-update__ eines Arrays/Vektors/Matrix ist möglich entweder durch explizite Indizierung
|
Memory- and time-saving __in-place-update__ of an array/vector/matrix is possible either through explicit indexing
|
||||||
```julia
|
```julia
|
||||||
for i in eachindex(x)
|
for i in eachindex(x)
|
||||||
x[i] += y[i]
|
x[i] += y[i]
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
oder durch die dazu semantisch äquivalente _broadcast_-Form (s. @sec-broadcast):
|
or through the semantically equivalent _broadcast_ form (see @sec-broadcast):
|
||||||
```julia
|
```julia
|
||||||
x .= x .+ y
|
x .= x .+ y
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Vorrang und Assoziativität von Operatoren {#sec-vorrang}
|
## Operator Precedence and Associativity {#sec-vorrang}
|
||||||
|
|
||||||
Zu berechnende Ausdrücke
|
Expressions to be computed
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
-2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2
|
-2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2
|
||||||
```
|
```
|
||||||
|
|
||||||
werden vom Parser in eine Baumstruktur überführt.
|
are converted by the parser into a tree structure.
|
||||||
```{julia}
|
```{julia}
|
||||||
using TreeView
|
using TreeView
|
||||||
|
|
||||||
@@ -464,75 +464,75 @@ walk_tree(Meta.parse("-2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2"))
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
- Die Auswertung solcher Ausdrücke wird durch
|
- The evaluation of such expressions is regulated by
|
||||||
- Vorrang _(precedence)_ und
|
- precedence and
|
||||||
- Assoziativität geregelt.
|
- associativity.
|
||||||
- 'Vorrang' definiert, welche Operatoren stärker binden im Sinne von "Punktrechnung geht vor Strichrechnung".
|
- 'Precedence' defines which operators bind more strongly in the sense of "multiplication and division before addition and subtraction".
|
||||||
- 'Assoziativität' bestimmt die Auswertungsreihenfolge bei gleichen oder gleichrangigen Operatoren.
|
- 'Associativity' determines the evaluation order for operators of equal or same rank.
|
||||||
- [Vollständige Dokumentation](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity)
|
- [Complete documentation](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity)
|
||||||
|
|
||||||
### Assoziativität
|
### Associativity
|
||||||
|
|
||||||
Sowohl Addition und Subtraktion als auch Multiplikation und Divison sind jeweils gleichrangig und linksassoziativ, d.h. es wird von links ausgewertet.
|
Both addition and subtraction as well as multiplication and division are each of equal rank and left-associative, i.e., they are evaluated from left to right.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
200/5/2 # wird von links ausgewertet als (200/5)/2
|
200/5/2 # evaluated left to right as (200/5)/2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
200/2*5 # wird von links ausgewertet als (200/2)*5
|
200/2*5 # evaluated left to right as (200/2)*5
|
||||||
```
|
```
|
||||||
|
|
||||||
Zuweisungen wie `=`, `+=`, `*=`,... sind gleichrangig und rechtsassoziativ.
|
Assignments like `=`, `+=`, `*=`,... are of equal rank and right-associative.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 1
|
x = 1
|
||||||
y = 10
|
y = 10
|
||||||
|
|
||||||
# wird von rechts ausgewertet: x += (y += (z = (a = 20)))
|
# evaluated right to left: x += (y += (z = (a = 20)))
|
||||||
|
|
||||||
x += y += z = a = 20
|
x += y += z = a = 20
|
||||||
|
|
||||||
@show x y z a;
|
@show x y z a;
|
||||||
```
|
```
|
||||||
|
|
||||||
Natürlich kann man die Assoziativität in Julia auch abfragen. Die entsprechenden Funktionen werden nicht explizit aus dem `Base`-Modul exportiert, deshalb muss man den Modulnamen beim Aufruf angeben.
|
Of course, you can also query the associativity in Julia. The corresponding functions are not explicitly exported from the `Base` module, so the module name must be specified when calling.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
for i in (:/, :+=, :(=), :^)
|
for i in (:/, :+=, :(=), :^)
|
||||||
a = Base.operator_associativity(i)
|
a = Base.operator_associativity(i)
|
||||||
println("Operation $i is $(a)-assoziative")
|
println("Operation $i is $(a)-associative")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Also ist der Potenzoperator rechtsassoziativ.
|
So the power operator is right-associative.
|
||||||
```{julia}
|
```{julia}
|
||||||
2^3^2 # rechtsassoziativ, = 2^(3^2)
|
2^3^2 # right-associative, = 2^(3^2)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Vorrang
|
### Precedence
|
||||||
|
|
||||||
- Julia ordnet den Operatoren Vorrangstufen von 1 bis 17 zu:
|
- Julia assigns operator precedence levels from 1 to 17:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
for i in (:+, :-, :*, :/, :^, :(=))
|
for i in (:+, :-, :*, :/, :^, :(=))
|
||||||
p = Base.operator_precedence(i)
|
p = Base.operator_precedence(i)
|
||||||
println("Vorrang von $i = $p")
|
println("Precedence of $i = $p")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
- 11 ist kleiner als 12, also geht 'Punktrechnung vor Strichrechnung'
|
- 11 is less than 12, so 'multiplication and division before addition and subtraction'
|
||||||
- Der Potenz-Operator `^` hat eine höhere _precedence_.
|
- The power operator `^` has a higher _precedence_.
|
||||||
- Zuweisungen haben die kleinste _precedence_
|
- Assignments have the smallest _precedence_
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
# Zuweisung hat kleinsten Vorrang, daher Auswertung als x = (3 < 4)
|
# assignment has smallest precedence, therefore evaluation as x = (3 < 4)
|
||||||
|
|
||||||
x = 3 < 4
|
x = 3 < 4
|
||||||
x
|
x
|
||||||
@@ -540,11 +540,11 @@ x
|
|||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
(y = 3) < 4 # Klammern schlagen natürlich jeden Vorrang
|
(y = 3) < 4 # parentheses当然 override any precedence
|
||||||
y
|
y
|
||||||
```
|
```
|
||||||
|
|
||||||
Nochmal zum Beispiel vom Anfang von @sec-vorrang:
|
Once more to the example from the beginning of @sec-vorrang:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
-2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2
|
-2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2
|
||||||
@@ -557,43 +557,43 @@ for i ∈ (:^, :+, :/, :(==), :&&, :>, :|| )
|
|||||||
println(Base.operator_precedence(i))
|
println(Base.operator_precedence(i))
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
Nach diesen Vorrangregeln wird der Beispielausdruck also wie folgt ausgewertet:
|
According to these precedence rules, the example expression is evaluated as follows:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
((-(2^3)+((500/2)/10)==8) && (13 > (7 + 1))) || (9 < 2)
|
((-(2^3)+((500/2)/10)==8) && (13 > (7 + 1))) || (9 < 2)
|
||||||
```
|
```
|
||||||
(Das entspricht natürlich dem oben gezeigten *parse-tree*)
|
(This of course corresponds to the *parse-tree* shown above)
|
||||||
|
|
||||||
Es gilt also für den Vorrang:
|
So the precedence is:
|
||||||
|
|
||||||
> Potenz > Multiplikation/Division > Addition/Subtraktion > Vergleiche > logisches && > logisches || > Zuweisung
|
> Power > Multiplication/Division > Addition/Subtraction > Comparisons > logical && > logical || > assignment
|
||||||
|
|
||||||
Damit wird ein Ausdruck wie
|
Thus, an expression like
|
||||||
```julia
|
```julia
|
||||||
a = x <= y + z && x > z/2
|
a = x <= y + z && x > z/2
|
||||||
```
|
```
|
||||||
sinnvoll ausgewertet als `a = ((x <= (y+z)) && (x < (z/2)))`
|
is sensibly evaluated as `a = ((x <= (y+z)) && (x < (z/2)))`
|
||||||
|
|
||||||
|
|
||||||
- Eine Besonderheit sind noch
|
- A special case is still
|
||||||
|
|
||||||
- unäre Operatoren, also insbesondere `+` und `-` als Vorzeichen
|
- unary operators, in particular `+` and `-` as signs
|
||||||
- _juxtaposition_, also Zahlen direkt vor Variablen oder Klammern ohne `*`-Symbol
|
- _juxtaposition_, i.e., numbers directly before variables or parentheses without `*` symbol
|
||||||
|
|
||||||
Beide haben Vorrang noch vor Multiplikation und Division.
|
Both have precedence even before multiplication and division.
|
||||||
|
|
||||||
:::{.callout-important}
|
:::{.callout-important}
|
||||||
Damit ändert sich die Bedeutung von Ausdrücken, wenn man _juxtaposition_ anwendet:
|
Therefore, the meaning of expressions changes when one applies _juxtaposition_:
|
||||||
```{julia}
|
```{julia}
|
||||||
1/2*π, 1/2π
|
1/2*π, 1/2π
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
- Im Vergleich zum Potenzoperator `^` gilt (s. [https://discourse.julialang.org/t/confused-about-operator-precedence-for-2-3x/8214/7](https://discourse.julialang.org/t/confused-about-operator-precedence-for-2-3x/8214/7) ):
|
- Compared to the power operator `^` (see [https://discourse.julialang.org/t/confused-about-operator-precedence-for-2-3x/8214/7](https://discourse.julialang.org/t/confused-about-operator-precedence-for-2-3x/8214/7) ):
|
||||||
|
|
||||||
> Unary operators, including juxtaposition, bind tighter than ^ on the right but looser on the left.
|
> Unary operators, including juxtaposition, bind tighter than ^ on the right but looser on the left.
|
||||||
|
|
||||||
Beispiele:
|
Examples:
|
||||||
```{julia}
|
```{julia}
|
||||||
-2^2 # -(2^2)
|
-2^2 # -(2^2)
|
||||||
```
|
```
|
||||||
@@ -615,28 +615,26 @@ x = 5
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
- Funktionsanwendung `f(...)` hat Vorrang vor allen Operatoren
|
- Function application `f(...)` has precedence over all operators
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
sin(x)^2 === (sin(x))^2 # nicht sin(x^2)
|
sin(x)^2 === (sin(x))^2 # not sin(x^2)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Zusätzliche Operatoren
|
### Additional Operators
|
||||||
|
|
||||||
Der [Julia-Parser](https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm#L13-L31) definiert für zahlreiche Unicode-Zeichen einen Vorrang auf Vorrat, so dass diese Zeichen von Paketen und selbstgeschriebenem Code als Operatoren benutzt werden können.
|
The [Julia parser](https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm#L13-L31) assigns precedence to numerous Unicode characters in advance, so that these characters can be used as operators by packages and self-written code.
|
||||||
|
|
||||||
So haben z.B.
|
Thus, for example,
|
||||||
```julia
|
```julia
|
||||||
∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛
|
∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛
|
||||||
```
|
```
|
||||||
|
|
||||||
den Vorrang 12 wie Multiplikation/Division (und sind wie diese linksassoziativ)
|
have precedence 12 like multiplication/division (and are left-associative like these)
|
||||||
und z.B.
|
and for example
|
||||||
```julia
|
```julia
|
||||||
⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗
|
⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗
|
||||||
```
|
```
|
||||||
haben den Vorrang 11 wie Addition/Subtraktion.
|
have precedence 11 like addition/subtraction.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,43 +9,44 @@ engine: julia
|
|||||||
using InteractiveUtils
|
using InteractiveUtils
|
||||||
```
|
```
|
||||||
|
|
||||||
# Erste Miniprogramme
|
# First Small Programs
|
||||||
|
|
||||||
|
|
||||||
## Was sollte man zum Programmieren können?
|
## What Should One Be Able to Do for Programming?
|
||||||
|
|
||||||
|
|
||||||
- **Denken in Algorithmen:**
|
- **Thinking in algorithms:**
|
||||||
Welche Schritte sind zur Lösung des Problems nötig? Welche Daten müssen gespeichert, welche Datenstrukturen angelegt werden? Welche Fälle können auftreten und müssen erkannt und behandelt werden?
|
What steps are required to solve the problem? What data must be stored, what data structures must be created? What cases can occur and must be recognized and handled?
|
||||||
- **Umsetzung des Algorithmus in ein Programm:**
|
- **Implementation of the algorithm into a program:**
|
||||||
Welche Datenstrukturen, Konstrukte, Funktionen... stellt die Programmiersprache bereit?
|
What data structures, constructs, functions... does the programming language provide?
|
||||||
- **Formale Syntax:**
|
- **Formal syntax:**
|
||||||
Menschen verstehen 'broken English'; Computer verstehen kein 'broken C++' oder 'broken Julia'. Die Syntax muss beherrscht werden.
|
Humans understand 'broken English'; computers don't understand 'broken C++' or 'broken Julia'. The syntax must be mastered.
|
||||||
- **„Ökosystem“ der Sprache:**
|
- **The "ecosystem" of the language:**
|
||||||
Wie führe ich meinen Code aus? Wie funktionieren die Entwicklungsumgebungen? Welche Optionen versteht der Compiler? Wie installiere ich Zusatzbibliotheken? Wie lese ich Fehlermeldungen? Wo kann ich mich informieren?
|
How do I run my code? How do the development environments work? What options does the compiler understand? How do I install additional libraries? How do I read error messages? Where can I get information?
|
||||||
- **die Kunst des Debugging:**
|
- **The art of debugging:**
|
||||||
Programmieranfänger sind oft glücklich, wenn sie alle Syntaxfehler eliminiert haben und das Programm endlich 'durchläuft'. Bei komplexeren Programmen fängt die Arbeit jetzt erst an, denn nun muss getestet und die Fehler im Algorithmus gefunden und behoben werden.
|
Programming beginners are often happy when they have eliminated all syntax errors and the program finally 'runs'. For more complex programs, the work only just begins, as testing and finding and fixing errors in the algorithm must now be done.
|
||||||
- **Gefühl für die Effizienz und Komplexität von Algorithmen**
|
- **Sense of the efficiency and complexity of algorithms**
|
||||||
- **Besonderheiten der Computerarithmetik**, insbesondere der Gleitkommazahlen
|
- **Specifics of computer arithmetic**, especially floating point numbers
|
||||||
|
|
||||||
Das erschließt sich nicht alles auf einmal. Haben Sie Geduld mit sich und 'spielen' Sie mit der Sprache.
|
These cannot all be mastered at once. Be patient with yourself and 'play' with the language.
|
||||||
|
|
||||||
|
The following should serve as a small inspiration.
|
||||||
|
|
||||||
Das Folgende soll eine kleine Anregung dazu sein.
|
|
||||||
|
|
||||||
## Project Euler
|
## Project Euler
|
||||||
|
|
||||||
Eine hübsche Quelle für Programmieraufgaben mit mathematischem Charakter und sehr unterschiedlichen Schwierigkeitsgraden ist [Project Euler](https://projecteuler.net/).
|
A nice source for programming tasks with mathematical character and very different levels of difficulty is [Project Euler](https://projecteuler.net/).
|
||||||
Die Aufgaben sind so gestaltet, dass keinerlei Eingaben notwendig und das gesuchte Ergebnis eine einzige Zahl ist. So kann man sich voll auf das Programmieren des Algorithmus konzentrieren.
|
The tasks are designed so that no inputs are necessary and the desired result is a single number. This allows you to fully concentrate on programming the algorithm.
|
||||||
|
|
||||||
---------
|
---------
|
||||||
|
|
||||||
### Beispiel 1
|
### Example 1
|
||||||
|
|
||||||
::::::{.content-hidden unless-format="xxx"}
|
::::::::{.content-hidden unless-format="xxx"}
|
||||||
|
|
||||||
https://github.com/luckytoilet/projecteuler-solutions/blob/master/Solutions.md
|
https://github.com/luckytoilet/projecteuler-solutions/blob/master/Solutions.md
|
||||||
https://math.stackexchange.com/questions/3370978/iterating-sum-of-squares-of-decimal-digits-of-an-integer-how-big-can-it-grow
|
https://math.stackexchange.com/questions/3370978/iterating-sum-of-squares-of-decimal-digits-of-an-integer-how-big-can-it-grow
|
||||||
aufg. 92
|
Aufg. 92
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
@@ -58,36 +59,36 @@ Find the sum of all the multiples of 3 or 5 below 1000.
|
|||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
1. Algorithmus:
|
1. Algorithm:
|
||||||
- Teste alle natürlichen Zahlen <1000 auf Teilbarkeit durch 3 oder durch 5 und
|
- Test all natural numbers <1000 for divisibility by 3 or 5 and
|
||||||
- summiere die teilbaren Zahlen auf.
|
- sum the divisible numbers.
|
||||||
|
|
||||||
2. Umsetzung:
|
2. Implementation:
|
||||||
|
|
||||||
Wie liefert Julia den Rest der Ganzzahldivision? Solche Funktionen heißen typischerweise `rem()` (für *remainder*) oder `mod()`. [Nachlesen in der Doku](https://docs.julialang.org/en/v1/base/math/#Base.rem) oder ausprobieren von `?rem` und `?mod` in der Julia-REPL zeigt, dass es beides gibt. Der Unterschied liegt in der Behandlung negativer ganzer Zahlen. Für natürliche Zahlen `n,m` liefern `mod(n,m)` und `rem(n,m)` dasselbe und letzteres hat auch noch die Infix-Form `n % m`.
|
How does Julia provide the remainder of integer division? Functions like this are typically called `rem()` (for *remainder*) or `mod()`. [Look it up in the documentation](https://docs.julialang.org/en/v1/base/math/#Base.rem) or try `?rem` and `?mod` in the Julia REPL shows that there are both. The difference lies in the treatment of negative integers. For natural numbers `n,m`, `mod(n,m)` and `rem(n,m)` give the same result, and the latter also has the infix form `n % m`.
|
||||||
|
|
||||||
Wie testet man eine Reihe von Werten durch und summiert auf? Da gibt es ein Standardmuster: `for`-Schleife und Akkumulatorvariable:
|
How does one test a sequence of values and sum them up? There is a standard pattern: `for` loop and accumulator variable:
|
||||||
|
|
||||||
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
||||||
|
|
||||||
## Eine Lösungsvariante:
|
## One possible solution:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
s = 0 # Akkumulatorvariable initialisieren
|
s = 0 # initialize accumulator variable
|
||||||
for i in 1:999 # Schleife
|
for i in 1:999 # loop
|
||||||
if i % 3 == 0 || i % 5 == 0 # Test
|
if i % 3 == 0 || i % 5 == 0 # test
|
||||||
s += i # Zu Akkumulator addieren
|
s += i # add to accumulator
|
||||||
end # Ende Test
|
end # end test
|
||||||
end # Ende Schleife
|
end # end loop
|
||||||
println(" Die Antwort ist: $s") # Ausgabe des Ergebnisses
|
println(" The answer is: $s") # output result
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Natürlich geht das auch etwas kürzer:
|
Of course, this can also be done a bit shorter:
|
||||||
|
|
||||||
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
||||||
|
|
||||||
## Noch eine Lösungsvariante:
|
## Another solution:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
sum([i for i in 1:999 if i%3==0||i%5==0])
|
sum([i for i in 1:999 if i%3==0||i%5==0])
|
||||||
@@ -98,7 +99,7 @@ sum([i for i in 1:999 if i%3==0||i%5==0])
|
|||||||
|
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
### Beispiel 2
|
### Example 2
|
||||||
|
|
||||||
|
|
||||||
::: {.callout-note icon=false .titlenormal}
|
::: {.callout-note icon=false .titlenormal}
|
||||||
@@ -115,41 +116,41 @@ Therefore any chain that arrives at 1 or 89 will become stuck in an endless loop
|
|||||||
How many starting numbers below ten million will arrive at 89?
|
How many starting numbers below ten million will arrive at 89?
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Programme kann man [*top-down* und *bottom-up*](https://de.wikipedia.org/wiki/Top-Down-_und_Bottom-Up-Design) entwickeln.
|
Programs can be developed [*top-down* and *bottom-up*](https://en.wikipedia.org/wiki/Top-down_and_bottom-up_design).
|
||||||
*Top-down* würde hier wohl bedeuten: „Wir fangen mit einer Schleife `for i = 1:9999999` an.“ Der andere Weg führt über einzeln testbare Komponenten und ist oft zielführender. (Und ab einer gewissen Projektgröße nähert man sich sowieso von 'top' und 'bottom' gleichzeitig dem Ziel.)
|
*Top-down* would probably mean here: "We start with a loop `for i = 1:9999999`." The other way leads over individually testable components and is often more effective. (And with a certain project size, one approaches the goal from both 'top' and 'bottom' simultaneously.)
|
||||||
|
|
||||||
##### Funktion Nr. 1
|
##### Function No. 1
|
||||||
Es soll untersucht werden, wie sich die Zahlen unter dem wiederholten Berechnen der 'Quadratquersumme' (Summe der Quadrate der Ziffern) verhalten. Also sollte man eine Funktion schreiben und testen, die diese 'Quadratquersumme' berechnet.
|
It should be investigated how numbers behave under repeated calculation of the 'square digit sum' (sum of squares of digits). Therefore, one should write and test a function that calculates this 'square digit sum'.
|
||||||
|
|
||||||
|
|
||||||
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
||||||
|
|
||||||
## `q2sum(n)` berechnet die Summe der Quadrate der Ziffern von n im Dezimalsystem:
|
## `q2sum(n)` calculates the sum of the squares of the digits of n in the decimal system:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| output: false
|
#| output: false
|
||||||
function q2sum(n)
|
function q2sum(n)
|
||||||
s = 0 # Akkumulator für die Summe
|
s = 0 # accumulator for the sum
|
||||||
while n > 9 # solange noch mehrstellig...
|
while n > 9 # as long as still multi-digit...
|
||||||
q, r = divrem(n, 10) # berechne Ganzzahlquotient und Rest bei Division durch 10
|
q, r = divrem(n, 10) # calculate integer quotient and remainder of division by 10
|
||||||
s += r^2 # addiere quadrierte Ziffer zum Akkumulator
|
s += r^2 # add squared digit to accumulator
|
||||||
n = q # mache weiter mit der durch 10 geteilten Zahl
|
n = q # continue with the number divided by 10
|
||||||
end
|
end
|
||||||
s += n^2 # addiere das Quadrat der letzten Ziffer
|
s += n^2 # add the square of the last digit
|
||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
... und das testen wir jetzt natürlich:
|
... and let's test it now:
|
||||||
```{julia}
|
```{julia}
|
||||||
for i in [1, 7, 33, 111, 321, 1000, 73201]
|
for i in [1, 7, 33, 111, 321, 1000, 73201]
|
||||||
j = q2sum(i)
|
j = q2sum(i)
|
||||||
println("Quadratquersumme von $i = $j")
|
println("Square digit sum of $i = $j")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Im Sinne der Aufgabe wenden wir die Funktion wiederholt an:
|
In the spirit of the task, we apply the function repeatedly:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
n = 129956799
|
n = 129956799
|
||||||
@@ -158,48 +159,48 @@ for i in 1:14
|
|||||||
println(n)
|
println(n)
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
... und haben hier einen der '89er Zyklen' getroffen.
|
... and we have here hit one of the '89-cycles'.
|
||||||
|
|
||||||
|
|
||||||
#### Funktion Nr. 2
|
#### Function No. 2
|
||||||
|
|
||||||
Wir müssen testen, ob die wiederholte Anwendung der Funktion `q2sum()` schließlich zu **1** führt oder in diesem **89er**-Zyklus endet.
|
We need to test whether repeated application of the function `q2sum()` finally leads to **1** or ends in this **89**-cycle.
|
||||||
|
|
||||||
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
||||||
|
|
||||||
## `q2test(n)` ermittelt, ob wiederholte Quadratquersummenbildung in den 89er-Zyklus führt:
|
## `q2test(n)` determines whether repeated square digit sum calculation leads to the 89-cycle:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| output: false
|
#| output: false
|
||||||
function q2test(n)
|
function q2test(n)
|
||||||
while n !=1 && n != 89 # solange wir nicht bei 1 oder 89 angekommen sind....
|
while n !=1 && n != 89 # as long as we have not reached 1 or 89....
|
||||||
n = q2sum(n) # wiederholen
|
n = q2sum(n) # repeat
|
||||||
end
|
end
|
||||||
if n==1 return false end # keine 89er-Zahl
|
if n==1 return false end # not an 89-number
|
||||||
return true # 89er-Zahl gefunden
|
return true # 89-number found
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
... und damit können wir die Aufgabe lösen:
|
... and with this, we can solve the task:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
c = 0 # mal wieder ein Akkumulator
|
c = 0 # once again an accumulator
|
||||||
for i = 1 : 10_000_000 - 1 # so kann man in Julia Tausenderblöcke zur besseren Lesbarkeit abtrennen
|
for i = 1 : 10_000_000 - 1 # this is how you can separate thousands for better readability in Julia
|
||||||
if q2test(i) # q2test() gibt einen Boolean zurück, kein weiterer Test nötig
|
if q2test(i) # q2test() returns a boolean, no further test needed
|
||||||
c += 1 # 'if x == true' ist redundant, 'if x' reicht völlig
|
c += 1 # 'if x == true' is redundant, 'if x' is perfectly sufficient
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
println("$c numbers below ten million arrive at 89.")
|
println("$c numbers below ten million arrive at 89.")
|
||||||
```
|
```
|
||||||
|
|
||||||
Zahlen, bei denen die iterierte Quadratquersummenbildung bei 1 endet, heißen übrigens [fröhliche Zahlen](https://de.wikipedia.org/wiki/Fr%C3%B6hliche_Zahl) und wir haben gerade die Anzahl der traurigen Zahlen kleiner als 10.000.000 berechnet.
|
Numbers for which the iterative square digit sum calculation ends at 1 are called [happy numbers](https://en.wikipedia.org/wiki/Happy_number), and we have just calculated the number of sad numbers less than 10,000,000.
|
||||||
|
|
||||||
Hier nochmal das vollständige Programm:
|
Here is the complete program again:
|
||||||
|
|
||||||
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
||||||
## unsere Lösung von Project Euler No 92:
|
## our solution to Project Euler No 92:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
function q2sum(n)
|
function q2sum(n)
|
||||||
|
|||||||
104
chapters/Pi2.qmd
104
chapters/Pi2.qmd
@@ -9,20 +9,26 @@ engine: julia
|
|||||||
using InteractiveUtils
|
using InteractiveUtils
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```{julia}
|
||||||
|
#| error: false
|
||||||
|
#| echo: false
|
||||||
|
#| output: false
|
||||||
|
flush(stdout)
|
||||||
|
```
|
||||||
|
|
||||||
# Ein Beispiel zur Stabilität von Gleitkommaarithmetik
|
# Example of Floating-Point Arithmetic Stability
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Berechnung von $\pi$ nach Archimedes
|
## Calculation of $\pi$ according to Archimedes
|
||||||
|
|
||||||
Eine untere Schranke für $2\pi$, den Umfang des Einheitskreises, erhält man durch die
|
A lower bound for $2\pi$, the circumference of the unit circle, is obtained by the
|
||||||
Summe der Seitenlängen eines dem Einheitskreis eingeschriebenen regelmäßigen $n$-Ecks.
|
sum of the side lengths of a regular $n$-gon inscribed in the unit circle.
|
||||||
Die Abbildung links zeigt, wie man beginnend mit einem Viereck der Seitenlänge $s_4=\sqrt{2}$ die Eckenzahl iterativ verdoppelt.
|
The figure on the left shows how one can iteratively double the number of vertices starting from a square with side length $s_4=\sqrt{2}$.
|
||||||
|
|
||||||
:::{.narrow}
|
:::{.narrow}
|
||||||
|
|
||||||
| Abb. 1 | Abb.2 |
|
| Fig. 1 | Fig. 2 |
|
||||||
| :-: | :-: |
|
| :-: | :-: |
|
||||||
|  |  |
|
|  |  |
|
||||||
: {tbl-colwidths="[57,43]"}
|
: {tbl-colwidths="[57,43]"}
|
||||||
@@ -30,51 +36,49 @@ Summe der Seitenlängen eines dem Einheitskreis eingeschriebenen regelmäßigen
|
|||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
Die zweite Abbildung zeigt die Geometrie der Eckenverdoppelung.
|
The second figure shows the geometry of the vertex doubling.
|
||||||
|
|
||||||
Mit
|
With
|
||||||
$|\overline{AC}|= s_{n},\quad |\overline{AB}|= |\overline{BC}|= s_{2n},\quad |\overline{MN}| =a, \quad |\overline{NB}| =1-a,$ liefert Pythagoras für die Dreiecke $MNA$ und
|
$|\overline{AC}|= s_{n},\quad |\overline{AB}|= |\overline{BC}|= s_{2n},\quad |\overline{MN}| =a, \quad |\overline{NB}| =1-a,$ the Pythagorean theorem applied to triangles $MNA$ and
|
||||||
$NBA$ jeweils
|
$NBA$ respectively yields
|
||||||
$$
|
$$
|
||||||
a^2 + \left(\frac{s_{n}}{2}\right)^2 = 1\qquad\text{bzw.} \qquad
|
a^2 + \left(\frac{s_{n}}{2}\right)^2 = 1\qquad\text{resp.} \qquad
|
||||||
(1-a)^2 + \left(\frac{s_{n}}{2}\right)^2 = s_{2n}^2
|
(1-a)^2 + \left(\frac{s_{n}}{2}\right)^2 = s_{2n}^2
|
||||||
$$
|
$$
|
||||||
Elimination von $a$ liefert die Rekursion
|
Elimination of $a$ gives the recursion
|
||||||
$$
|
$$
|
||||||
s_{2n} = \sqrt{2-\sqrt{4-s_n^2}} \qquad\text{mit Startwert}\qquad
|
s_{2n} = \sqrt{2-\sqrt{4-s_n^2}} \qquad\text{with initial value}\qquad
|
||||||
s_4=\sqrt{2}
|
s_4=\sqrt{2}
|
||||||
$$
|
$$
|
||||||
für die Länge $s_n$ **einer** Seite des eingeschriebenen regelmäßigen
|
for the length $s_n$ **of one** side of the inscribed regular
|
||||||
$n$-Ecks.
|
$n$-gon.
|
||||||
|
|
||||||
|
|
||||||
Die Folge $(n\cdot s_n)$
|
The sequence $(n\cdot s_n)$
|
||||||
konvergiert monoton von unten gegen den
|
converges monotonically from below to the
|
||||||
Grenzwert $2\pi$:
|
limit $2\pi$:
|
||||||
$$
|
$$
|
||||||
n\, s_n \rightarrow 2\pi % \qquad\text{und} \qquad {n c_n}\downarrow 2\pi
|
n\, s_n \rightarrow 2\pi % \qquad\text{and} \qquad {n c_n}\downarrow 2\pi
|
||||||
$$
|
$$
|
||||||
Der relative Fehler der Approximation von 2π durch ein $n$-Eck ist:
|
The relative error of the approximation of 2π by an $n$-gon is:
|
||||||
$$
|
$$
|
||||||
\epsilon_n = \left| \frac{n\, s_n-2 \pi}{2\pi} \right|
|
\epsilon_n = \left| \frac{n\, s_n-2 \pi}{2\pi} \right|
|
||||||
$$
|
$$
|
||||||
|
|
||||||
|
|
||||||
## Zwei Iterationsvorschriften^[nach: Christoph Überhuber, „Computer-Numerik“ Bd. 1, Springer 1995, Kap. 2.3]
|
## Two Iteration Formulas^[by: Christoph Überhuber, "Computer-Numerik" Vol. 1, Springer 1995, Chap. 2.3]
|
||||||
Die Gleichung
|
The equation
|
||||||
$$
|
$$
|
||||||
s_{2n} = \sqrt{2-\sqrt{4-s_n^2}}\qquad \qquad \textrm{(Iteration A)}
|
s_{2n} = \sqrt{2-\sqrt{4-s_n^2}}\qquad \qquad \text{(Iteration A)}
|
||||||
$$
|
$$
|
||||||
ist mathematisch äquivalent zu
|
is mathematically equivalent to
|
||||||
$$
|
$$
|
||||||
s_{2n} = \frac{s_n}{\sqrt{2+\sqrt{4-s_n^2}}} \qquad \qquad \textrm{(Iteration B)}
|
s_{2n} = \frac{s_n}{\sqrt{2+\sqrt{4-s_n^2}}} \qquad \qquad \text{(Iteration B)}
|
||||||
$$
|
$$
|
||||||
|
|
||||||
(Bitte nachrechnen!)
|
(Please verify!)
|
||||||
|
|
||||||
|
However, Iteration A is ill-conditioned and numerically unstable, as the following code demonstrates. The output shows the respective approximation for π.
|
||||||
|
|
||||||
Allerdings ist Iteration A schlecht konditioniert und numerisch instabil, wie der folgende Code zeigt. Ausgegeben wird die jeweils berechnete Näherung für π.
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using Printf
|
using Printf
|
||||||
@@ -82,16 +86,16 @@ using Printf
|
|||||||
iterationA(s) = sqrt(2 - sqrt(4 - s^2))
|
iterationA(s) = sqrt(2 - sqrt(4 - s^2))
|
||||||
iterationB(s) = s / sqrt(2 + sqrt(4 - s^2))
|
iterationB(s) = s / sqrt(2 + sqrt(4 - s^2))
|
||||||
|
|
||||||
s_B = s_A = sqrt(2) # Startwert
|
s_B = s_A = sqrt(2) # initial value
|
||||||
|
|
||||||
ϵ(x) = abs(x - 2π)/2π # rel. Fehler
|
ϵ(x) = abs(x - 2π)/2π # rel. error
|
||||||
|
|
||||||
ϵ_A = Float64[] # Vektoren für den Plot
|
ϵ_A = Float64[] # vectors for the plot
|
||||||
ϵ_B = Float64[]
|
ϵ_B = Float64[]
|
||||||
is = Float64[]
|
is = Float64[]
|
||||||
|
|
||||||
@printf """ approx. Wert von π
|
@printf """ approx. value of π
|
||||||
n-Eck Iteration A Iteration B
|
n-gon Iteration A Iteration B
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for i in 3:35
|
for i in 3:35
|
||||||
@@ -106,13 +110,13 @@ for i in 3:35
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Während Iteration B sich stabilisiert bei einem innerhalb der Maschinengenauigkeit korrekten Wert für π, wird Iteration A schnell instabil. Ein Plot der relativen Fehler $\epsilon_i$ bestätigt das:
|
While Iteration B stabilizes at a value correct within machine precision, Iteration A quickly becomes unstable. A plot of the relative errors $\epsilon_i$ confirms this:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using PlotlyJS
|
using PlotlyJS
|
||||||
|
|
||||||
layout = Layout(xaxis_title="Iterationsschritte", yaxis_title="rel. Fehler",
|
layout = Layout(xaxis_title="Iteration steps", yaxis_title="rel. error",
|
||||||
yaxis_type="log", yaxis_exponentformat="power",
|
yaxis_type="log", yaxis_exponentformat="power",
|
||||||
xaxis_tick0=2, xaxis_dtick=2)
|
xaxis_tick0=2, xaxis_dtick=2)
|
||||||
|
|
||||||
@@ -121,18 +125,16 @@ plot([scatter(x=is, y=ϵ_A, mode="markers+lines", name="Iteration A", yscale=:lo
|
|||||||
layout)
|
layout)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Stability and Cancellation
|
||||||
|
|
||||||
|
At $i=26$, Iteration B reaches a relative error on the order of machine epsilon:
|
||||||
## Stabilität und Auslöschung
|
|
||||||
|
|
||||||
Bei $i=26$ erreicht Iteration B einen relativen Fehler in der Größe des Maschinenepsilons:
|
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
ϵ_B[22:28]
|
ϵ_B[22:28]
|
||||||
```
|
```
|
||||||
|
|
||||||
Weitere Iterationen verbessern das Ergebnis nicht mehr. Sie stabilisieren sich bei einem relativen Fehler von etwa 2.5 Maschinenepsilon:
|
Further iterations do not improve the result. It stabilizes at a relative error of approximately 2.5 machine epsilons:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -140,18 +142,18 @@ Weitere Iterationen verbessern das Ergebnis nicht mehr. Sie stabilisieren sich b
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Die Form Iteration A ist instabil. Bereits bei $i=16$ beginnt der relative Fehler wieder zu wachsen.
|
Iteration A is unstable. Already at $i=16$ the relative error begins to grow again.
|
||||||
|
|
||||||
Ursache ist eine typische Auslöschung. Die Seitenlängen $s_n$ werden sehr schnell klein. Damit ist
|
The cause is a typical cancellation effect. The side lengths $s_n$ become very small very quickly. Thus
|
||||||
$a_n=\sqrt{4-s_n^2}$ nur noch wenig kleiner als 2 und bei der Berechnung von $s_{2n}=\sqrt{2-a_n}$ tritt ein typischer Auslöschungseffekt auf.
|
$a_n=\sqrt{4-s_n^2}$ is only slightly smaller than 2, and when computing $s_{2n}=\sqrt{2-a_n}$ a typical cancellation effect occurs.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
setprecision(80) # precision für BigFloat
|
setprecision(80) # precision for BigFloat
|
||||||
|
|
||||||
s = sqrt(BigFloat(2))
|
s = sqrt(BigFloat(2))
|
||||||
|
|
||||||
@printf " a = √(4-s^2) als BigFloat und als Float64\n\n"
|
@printf " a = √(4-s^2) as BigFloat and as Float64\n\n"
|
||||||
|
|
||||||
for i = 3:44
|
for i = 3:44
|
||||||
s = iterationA(s)
|
s = iterationA(s)
|
||||||
@@ -164,15 +166,13 @@ end
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Man sieht die Abnahme der Zahl der signifikanten Ziffern. Man sieht auch, dass eine Verwendung von `BigFloat` mit einer Mantissenlänge von hier 80 Bit das Einsetzen des Auslöschungseffekts nur etwas hinaussschieben kann.
|
One sees the decrease in the number of significant digits. One also sees that using `BigFloat` with a mantissa length of 80 bits here only slightly delays the onset of the cancellation effect.
|
||||||
|
|
||||||
**Gegen instabile Algorithmen helfen in der Regel nur bessere, stabile Algorithmen und nicht genauere Maschinenzahlen!**
|
**Countermeasures against unstable algorithms usually require better, stable algorithms, not more precise machine numbers!**
|
||||||
|
|
||||||
:::{.content-hidden unless-format="xxx"}
|
:::{.content-hidden unless-format="xxx"}
|
||||||
|
|
||||||
Offensichtlich tritt bei der Berechnung von $2-a_n$ bereits relativ früh
|
Clearly, the computation of $2-a_n$ already shows a decrease in the number of significant digits (cancellation) relatively early,
|
||||||
eine Abnahme der Anzahl der signifikanten Ziffern (Auslöschung) auf,
|
before the computation of $a_n=\sqrt{4-s_n^2}$ itself leads to an unusable result due to cancellation.
|
||||||
bevor schließlich bei der Berechnung von $a_n=\sqrt{4-s_n^2}$
|
|
||||||
selbst schon Auslöschung zu einem unbrauchbaren Ergebnis führt.
|
|
||||||
|
|
||||||
:::
|
:::
|
||||||
@@ -1,28 +1,28 @@
|
|||||||
# Entwicklungsumgebungen
|
# Development Environments
|
||||||
|
|
||||||
Für diesen Kurs werden wir die webbasierte Entwicklungsumgebung [Jupyterhub](https://de.wikipedia.org/wiki/Project_Jupyter) verwenden. Sie steht allen Teilnehmerïnnen für die Dauer des Kurses zur Verfügung.
|
For this course, we will use the web-based development environment [Jupyterhub](https://en.wikipedia.org/wiki/Project_Jupyter). It is available to all participants for the duration of the course.
|
||||||
|
|
||||||
Für langfristiges Arbeiten empfiehlt sich eine eigene Installation.
|
For long-term work, a personal installation is recommended.
|
||||||
|
|
||||||
|
|
||||||
## Installation auf eigenem Rechner (Linux/MacOS/MS Windows)
|
## Installation on Personal Computer (Linux/MacOS/MS Windows)
|
||||||
|
|
||||||
1. Julia mit dem Installations- und Update-Manager **juliaup** installieren: <https://github.com/JuliaLang/juliaup/>
|
1. Install Julia with the installation and update manager **juliaup**: <https://github.com/JuliaLang/juliaup/>
|
||||||
2. als Editor/IDE **Visual Studio Code** installieren: <https://code.visualstudio.com/>
|
2. Install **Visual Studio Code** as editor/IDE: <https://code.visualstudio.com/>
|
||||||
3. im VS Code Editor die **Julia language extension** installieren: <https://www.julia-vscode.org/docs/stable/gettingstarted/>
|
3. Install the **Julia language extension** in VS Code: <https://www.julia-vscode.org/docs/stable/gettingStarted/>
|
||||||
|
|
||||||
Einstieg:
|
Entry point:
|
||||||
|
|
||||||
- In VS Code eine neue Datei mit der Endung `.jl` anlegen
|
- Create a new file with the extension `.jl` in VS Code
|
||||||
- Julia-Code schreiben
|
- Write Julia code
|
||||||
- `Shift-Enter` oder `Ctrl-Enter` am Ende einer Anweisung oder eines Blocks startet eine Julia-REPL, Code wird in die REPL kopiert und ausgeführt
|
- `Shift-Enter` or `Ctrl-Enter` at the end of a statement or block starts a Julia-REPL, code is copied to the REPL and executed
|
||||||
- [Tastenbelegungen für VS Code](https://code.visualstudio.com/docs/getstarted/keybindings#_keyboard-shortcuts-reference)
|
- [Key bindings for VS Code](https://code.visualstudio.com/docs/getstarted/keybindings#_keyboard-shortcuts-reference)
|
||||||
und [für Julia in VS Code](https://www.julia-vscode.org/docs/stable/userguide/keybindings/)
|
and [for Julia in VS Code](https://www.julia-vscode.org/docs/stable/userguide/keybindings/)
|
||||||
|
|
||||||
|
|
||||||
### Die Julia-REPL
|
### The Julia-REPL
|
||||||
|
|
||||||
Wenn man Julia direkt startet, wird die [Julia-REPL](https://docs.julialang.org/en/v1/stdlib/REPL/) (*read-eval-print* Schleife) gestartet, in der man interaktiv mit Julia arbeiten kann.
|
When Julia is started directly, the [Julia-REPL](https://docs.julialang.org/en/v1/stdlib/REPL/) (*read-eval-print* loop) starts, where one can work interactively with Julia.
|
||||||
|
|
||||||
|
|
||||||
```default
|
```default
|
||||||
@@ -39,36 +39,34 @@ $ julia
|
|||||||
julia>
|
julia>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Arbeiten auf dem [Jupyterhub-Webserver](https://misun103.mathematik.uni-leipzig.de/)
|
## Working on the [Jupyterhub Webserver](https://misun103.mathematik.uni-leipzig.de/)
|
||||||
|
|
||||||
### Jupyterhub & Jupyter
|
### Jupyterhub & Jupyter
|
||||||
|
|
||||||
- [Jupyterhub](https://de.wikipedia.org/wiki/Project_Jupyter) ist ein Multi-User-Server für Jupyter.
|
- [Jupyterhub](https://de.wikipedia.org/wiki/Project_Jupyter) is a multi-user server for Jupyter.
|
||||||
- Jupyter ist eine web-basierte interaktive Programmierumgebung, die
|
- Jupyter is a web-based interactive programming environment that
|
||||||
- ursprünglich in und für Python geschrieben, inzwischen eine
|
- was originally written for and in Python, but now supports many programming languages
|
||||||
Vielzahl von Programmiersprachen nutzen kann.
|
- In Jupyter, one works with so-called *notebooks*. These are structured text files (JSON), recognizable by the file extension `*.ipynb`.
|
||||||
- In Jupyter bearbeitet man sogenannte *notebooks*. Das sind strukturiere Textdateien (JSON), erkennbar an der Dateiendung
|
|
||||||
`*.ipynb`.
|
|
||||||
|
|
||||||
Unser Jupyterhub-Server: <https://misun103.mathematik.uni-leipzig.de/>
|
Our Jupyterhub server: <https://misun103.mathematik.uni-leipzig.de/>
|
||||||
|
|
||||||
Nach dem Einloggen in Jupyterhub erscheint ein Dateimanager:
|
After logging into Jupyterhub, a file manager appears:
|
||||||
|
|
||||||
::: {.content-visible when-format="html"}
|
::: {.content-visible when-format="html"}
|
||||||

|

|
||||||
:::
|
:::
|
||||||
|
|
||||||
::: {.content-visible when-format="pdf"}
|
::: {.content-visible when-format="pdf"}
|
||||||
{width=50%}
|
{width=50%}
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
Mit diesem kann man:
|
This can be used to:
|
||||||
|
|
||||||
- vorhandene *notebooks* öffnen,
|
- open existing *notebooks*,
|
||||||
- neue *notebooks* anlegen,
|
- create new *notebooks*,
|
||||||
- Dateien, z.B. *notebooks*, vom lokalen Rechner hochladen,
|
- upload files, e.g. *notebooks*, from the local computer,
|
||||||
- die Sitzung mit `Logout` beenden (bitte nicht vergessen!).
|
- end the session with `Logout` (please don't forget!).
|
||||||
|
|
||||||
### Jupyter notebooks
|
### Jupyter notebooks
|
||||||
|
|
||||||
@@ -82,29 +80,29 @@ Mit diesem kann man:
|
|||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
*Notebooks* bestehen aus Zellen. Zellen können
|
*Notebooks* consist of cells. Cells can contain
|
||||||
|
|
||||||
- Code oder
|
- code or
|
||||||
- Text/Dokumentation (Markdown)
|
- text/documentation (Markdown)
|
||||||
|
|
||||||
enthalten. In Textzellen kann die Auszeichnungssprache [Markdown](https://de.wikipedia.org/wiki/Markdown) zur Formatierung und LaTeX für mathematische Gleichungen verwendet werden.
|
In text cells, the markup language [Markdown](https://en.wikipedia.org/wiki/Markdown) can be used for formatting and LaTeX for mathematical equations.
|
||||||
|
|
||||||
::: {.callout-tip }
|
::: {.callout-tip }
|
||||||
Bitte die Punkte `User Interface Tour` und `Keyboard Shortcuts` im `Help`-Menü anschauen!
|
Please check the `User Interface Tour` and `Keyboard Shortcuts` points in the `Help` menu!
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Die Zelle, die man gerade bearbeitet, kann im `command mode` oder `edit mode` sein.
|
The cell currently being worked on can be in `command mode` or `edit mode`.
|
||||||
|
|
||||||
:::{.narrow}
|
:::{.narrow}
|
||||||
|
|
||||||
| | *Command mode* | *Edit mode* |
|
| | *Command mode* | *Edit mode* |
|
||||||
|:-------|:---------------:|:-----------:|
|
|:-------|:---------------:|:-----------:|
|
||||||
| Mode aktivieren | `ESC` | Doppelklick oder `Enter` in Zelle |
|
| Activate mode | `ESC` | Double-click or `Enter` in cell |
|
||||||
| neue Zelle | `b` | `Alt-Enter` |
|
| New cell | `b` | `Alt-Enter` |
|
||||||
| Zelle löschen | `dd` | |
|
| Delete cell | `dd` | |
|
||||||
| Notebook speichern | `s` | `Ctrl-s` |
|
| Save notebook | `s` | `Ctrl-s` |
|
||||||
| Notebook umbenennen | `Menu -> File -> Rename` | `Menu -> File -> Rename` |
|
| Rename notebook | `Menu -> File -> Rename` | `Menu -> File -> Rename` |
|
||||||
| Notebook schließen | `Menu -> File -> Close & Halt` | `Menu -> File -> Close & Halt` |
|
| Close notebook | `Menu -> File -> Close & Halt` | `Menu -> File -> Close & Halt` |
|
||||||
| *run cell* | `Ctrl-Enter` | `Ctrl-Enter` |
|
| *run cell* | `Ctrl-Enter` | `Ctrl-Enter` |
|
||||||
| *run cell, move to next cell* | `Shift-Enter` | `Shift-Enter` |
|
| *run cell, move to next cell* | `Shift-Enter` | `Shift-Enter` |
|
||||||
| *run cell, insert new cell below* | `Alt-Enter` | `Alt-Enter` |
|
| *run cell, insert new cell below* | `Alt-Enter` | `Alt-Enter` |
|
||||||
@@ -118,29 +116,27 @@ Die Zelle, die man gerade bearbeitet, kann im `command mode` oder `edit mode` se
|
|||||||
:::
|
:::
|
||||||
|
|
||||||
::: {.content-visible when-format="pdf"}
|
::: {.content-visible when-format="pdf"}
|
||||||
{width=50%}
|
{width=50%}
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
|
When a cell is "working", its cell number becomes a `*` and
|
||||||
|
the `kernel busy` indicator (solid black dot at the top right next to the
|
||||||
|
Julia version) appears. If this takes too long (an *infinite loop*
|
||||||
|
is quickly programmed), then
|
||||||
|
|
||||||
Wenn eine Zelle \"arbeitet\", wird ihre Zellen-Nummer zu einem `*` und
|
- click `Menu -> Kernel -> Interrupt`; if this is ineffective,
|
||||||
die `kernel busy`-Anzeige (Voller schwarzer Punkt oben rechts neben der
|
- click `Menu -> Kernel -> Restart`.
|
||||||
Julia-Version) erscheint. Falls das zu lange dauert (ein *infinite loop*
|
|
||||||
ist schnell programmiert), dann
|
|
||||||
|
|
||||||
- `Menu -> Kernel -> Interrupt` anklicken; falls das wirkungslos ist,
|
|
||||||
- `Menu -> Kernel -> Restart` anklicken.
|
|
||||||
|
|
||||||
|
|
||||||
::: {.callout-important }
|
::: {.callout-important }
|
||||||
Nach einem `kernel restart` müssen alle Zellen, die weiterhin benötigte Definitionen,
|
After a `kernel restart`, all cells containing required definitions,
|
||||||
`using`-Anweisungen etc enthalten, wieder ausgeführt werden.
|
`using` statements, etc. must be executed again.
|
||||||
|
|
||||||
|
|
||||||
**Am Ende der Arbeit bitte immer:**
|
**At the end of work, please always:**
|
||||||
|
|
||||||
- `Menu -> File -> Save & Checkpoint`
|
- `Menu -> File -> Save & Checkpoint`
|
||||||
- `Menu -> File -> Close & Halt`
|
- `Menu -> File -> Close & Halt`
|
||||||
- `Logout`
|
- `Logout`
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ using InteractiveUtils
|
|||||||
|
|
||||||
# First Contact
|
# First Contact
|
||||||
|
|
||||||
Dieses Kapitel soll beim 'Loslegen' helfen. Es läßt viele Details weg und die Codebeispiele sind oft eher suboptimal.
|
This chapter helps you get started. It omits many details and the code examples are often rather suboptimal.
|
||||||
|
|
||||||
|
|
||||||
## Julia als Taschenrechner
|
## Julia as a Calculator
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| eval: true
|
#| eval: true
|
||||||
@@ -36,28 +36,28 @@ function Tab(s)
|
|||||||
return # return nothing, since broadcast println produces empty vector
|
return # return nothing, since broadcast println produces empty vector
|
||||||
end
|
end
|
||||||
|
|
||||||
▷ = |>
|
▶ = |>
|
||||||
|
|
||||||
# IJulia.set_verbose(true)
|
# IJulia.set_verbose(true)
|
||||||
```
|
```
|
||||||
|
|
||||||
Berechne $\qquad 12^{1/3} + \frac{3\sqrt{2}}{\sin(0.5)-\cos(\frac{\pi}{4})\log(3)}+ e^5$
|
Compute $\qquad 12^{1/3} + \frac{3\sqrt{2}}{\sin(0.5)-\cos(\frac{\pi}{4})\log(3)}+ e^5$
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
12^(1/3) + 3sqrt(2) / (sin(.5) - cos(pi/4)*log(3)) + exp(5)
|
12^(1/3) + 3sqrt(2) / (sin(.5) - cos(pi/4)*log(3)) + exp(5)
|
||||||
```
|
```
|
||||||
|
|
||||||
Man beachte:
|
Note that:
|
||||||
|
|
||||||
- Potenzen schreibt man `a^b`.
|
- Powers are written as `a^b`.
|
||||||
- Die Konstante `pi` ist vordefiniert.
|
- The constant `pi` is predefined.
|
||||||
- `log()` ist der natürliche Logarithmus.
|
- `log()` is the natural logarithm.
|
||||||
- Das Multiplikationszeichen `a*b` kann nach einer Zahl weggelassen werden, wenn eine Variable, Funktion oder Klammer folgt.
|
- The multiplication sign `a*b` can be omitted after a number if followed by a variable, function, or parenthesis.
|
||||||
|
|
||||||
|
|
||||||
## Die wichtigsten Tasten: `Tab` und `?` {#sec-tab}
|
## The most important keys: `Tab` and `?` {#sec-tab}
|
||||||
|
|
||||||
Man drücke beim Programmieren immer wieder die Tabulatortaste, sobald 2...3 Buchstaben eines Wortes getippt sind. Es werden dann mögliche Ergänzungen angezeigt bzw. ergänzt, wenn die Ergänzung eindeutig ist. Das spart Zeit und bildet ungemein:
|
When programming, repeatedly press the Tab key as soon as 2...3 letters of a word have been typed. Potential completions are then displayed or completed if the completion is unique. This saves time and is extremely helpful:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
lo = "lo" #| hide_line
|
lo = "lo" #| hide_line
|
||||||
@@ -69,7 +69,7 @@ pri = "pri" #| hide_line
|
|||||||
pri ▷ Tab
|
pri ▷ Tab
|
||||||
```
|
```
|
||||||
|
|
||||||
Die eingebaute Julia-Hilfe `?name` zu allen Funktionen und Konstrukten ist sehr umfassend. Hier ein eher kurzes Beispiel:
|
The built-in Julia help `?name` for all functions and constructs is very comprehensive. Here is a rather short example:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
?for
|
?for
|
||||||
@@ -103,101 +103,101 @@ julia> for i in [1, 4, 0]
|
|||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
## Variablen und Zuweisungen
|
## Variables and Assignments
|
||||||
|
|
||||||
Variablen entstehen durch Zuweisung *(assignment)* mit dem Zuweisungsoperator `=` . Danach können sie in weiteren Anweisungen verwendet werden.
|
Variables are created through assignment with the assignment operator `=` . Afterward, they can be used in further statements.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 1 + sqrt(5)
|
x = 1 + sqrt(5)
|
||||||
y = x / 2
|
y = x / 2
|
||||||
```
|
```
|
||||||
|
|
||||||
Im interaktiven Betrieb zeigt Julia das Ergebnis der letzten Operation an.
|
In interactive mode, Julia displays the result of the last operation.
|
||||||
|
|
||||||
:::{.callout-note .titlenormal}
|
:::{.callout-note .titlenormal}
|
||||||
Zuweisungen sind keine mathematischen Gleichungen. Die Semantik des Zuweisungsoperators (Gleichheitszeichens) ist:
|
Assignments are not mathematical equations. The semantics of the assignment operator (equals sign) is:
|
||||||
|
|
||||||
- berechne die rechte Seite und
|
- Compute the right side and
|
||||||
- weise das Ergebnis der linken Seite zu.
|
- Assign the result to the left side.
|
||||||
|
|
||||||
Ausdrücke wie `x + y = sin(2)` sind daher unzulässig. Links darf nur ein Variablenname stehen.
|
Expressions like `x + y = sin(2)` are therefore invalid. Only a variable name may appear on the left side.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
## Datentypen
|
## Data types
|
||||||
|
|
||||||
Julia ist eine [stark typisierte](https://de.wikipedia.org/wiki/Starke_Typisierung) Sprache. Alle Objekte haben einen Typ.
|
Julia is a [strongly typed](https://en.wikipedia.org/wiki/Strong_and_weak_typing) language. All objects have a type.
|
||||||
So gibt es unter anderem die Basistypen
|
Among other things, there are the basic types
|
||||||
|
|
||||||
- Ganze Zahlen *(integers)*,
|
- Integers,
|
||||||
- Gleitkommazahlen *(floating point numbers)*,
|
- Floating-point numbers,
|
||||||
- Zeichenketten *(strings)* und
|
- Strings and
|
||||||
- Wahrheitswerte *(booleans)*.
|
- Booleans.
|
||||||
|
|
||||||
Den Typ einer Variablen kann man mit der Funktion `typeof()` ermitteln.
|
The type of a variable can be determined using the `typeof()` function.
|
||||||
```{julia}
|
```{julia}
|
||||||
#| warning: true
|
#| warning: true
|
||||||
#| error: true
|
#| error: true
|
||||||
for x ∈ (42, 12.0, 3.3e4, "Hallo!", true)
|
for x ∈ (42, 12.0, 3.3e4, "Hello!", true)
|
||||||
println("x = ", x, " ..... Typ: ", typeof(x))
|
println("x = ", x, " ..... Type: ", typeof(x))
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
Die Standard-Gleitkommazahl hat eine Länge von 64 Bit, entspricht also einer `double` in C/C++/Java.
|
The standard floating-point number has a length of 64 bits, which corresponds to a `double` in C/C++/Java.
|
||||||
|
|
||||||
Julia ist eine [dynamisch typisierte](https://de.wikipedia.org/wiki/Dynamische_Typisierung) Sprache.
|
Julia is a [dynamically typed](https://en.wikipedia.org/wiki/Dynamic_typing) language.
|
||||||
Variablen haben keinen Typ. Sie sind typlose Referenzen (Zeiger) auf Objekte.
|
Variables have no type. They are typeless references (pointers) to objects.
|
||||||
Wenn man vom „Typ einer Variablen“ spricht, meint man den Typ des Objektes, das der Variablen gerade zugewiesen ist.
|
When one speaks of the "type of a variable", one means the type of the object currently assigned to the variable.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = sqrt(2)
|
x = sqrt(2)
|
||||||
|
|
||||||
println( typeof(x), " - Wert von x = $x" )
|
println( typeof(x), " - Value of x = $x" )
|
||||||
|
|
||||||
x = "Jetzt bin ich keine Gleitkommazahl mehr!"
|
x = "Now I'm no longer a floating-point number!"
|
||||||
|
|
||||||
println( typeof(x), " - Wert von x = $x" )
|
println( typeof(x), " - Value of x = $x" )
|
||||||
```
|
```
|
||||||
|
|
||||||
## Druckanweisungen
|
## Print statements
|
||||||
Die Funktion `println()` unterscheidet sich von `print()` dadurch, dass sie am Ende einen Zeilenvorschub ausgibt.
|
The `println()` function differs from `print()` in that it outputs a line break at the end.
|
||||||
```{julia}
|
```{julia}
|
||||||
print(y)
|
print(y)
|
||||||
print("...die Zeile geht weiter...")
|
print("...the line continues...")
|
||||||
print("immernoch...")
|
print("still...")
|
||||||
println(y)
|
println(y)
|
||||||
println("Neue Zeile")
|
println("New line")
|
||||||
println("Neue Zeile")
|
println("New line")
|
||||||
```
|
```
|
||||||
Beide Funkionen können als Argument eine Liste von *strings* und Variablen bekommen. Man kann Variablen auch in *strings* einbetten, indem man dem Variablennamen ein Dollarzeichen voranstellt *(string interpolation)*.
|
Both functions can accept a list of *strings* and variables as arguments. Variables can also be embedded in *strings* by prefixing the variable name with a dollar sign *(string interpolation)*.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 23
|
x = 23
|
||||||
y = 3x + 5
|
y = 3x + 5
|
||||||
zz = "Fertig!"
|
zz = "Done!"
|
||||||
println("x= ", x, " ...und y= ", y, "...", zz) # 1. Variante
|
println("x= ", x, " ...and y= ", y, "...", zz) # 1. variant
|
||||||
println("x= $x ...und y= $y...$zz") # Variante mit string interpolation
|
println("x= $x ...and y= $y...$zz") # variant with string interpolation
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
:::{.callout-note .titlenormal collapse=true icon=false }
|
:::{.callout-note .titlenormal collapse=true icon=false }
|
||||||
## Wenn man ein Dollarzeichen drucken will...
|
## If you want to print a dollar sign...
|
||||||
|
|
||||||
muss man einen *backslash* voranstellen. Wenn man einen *backslash* drucken will, muss man ihn verdoppeln.
|
you must prepend a *backslash*. If you want to print a *backslash*, you must double it.
|
||||||
```{julia}
|
```{julia}
|
||||||
println("Ein Dollar: 1\$ und drei backslashs: \\\\\\ ")
|
println("One dollar: 1\$ and three backslashes: \\\\\\ ")
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Funktionen
|
## Functions
|
||||||
Funktionsdefinitionen beginnen mit dem Schlüsselwort `function` und enden mit dem Schlüsselwort `end`. In der Regel haben sie eine oder mehrere Argumente und geben beim Aufruf ein berechnetes Objekt mit der `return`-Anweisung zurück.
|
Function definitions begin with the keyword `function` and end with the keyword `end`. Typically, they have one or more arguments and return a computed object with the `return` statement on calling.
|
||||||
```{julia}
|
```{julia}
|
||||||
function hypotenuse(a, b) # heute besonders umständlich
|
function hypotenuse(a, b) # particularly cumbersome today
|
||||||
c2 = a^2 + b^2
|
c2 = a^2 + b^2
|
||||||
c = sqrt(c2)
|
c = sqrt(c2)
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
Nach ihrer Definition kann die Funktion benutzt (aufgerufen) werden. Die in der Definition verwendeten Variablen `a,b,c,c2` sind lokale Variablen und stehen außerhalb der Funktionsdefinition nicht zur Verfügung.
|
After their definition, the function can be used (called). The variables `a,b,c,c2` used in the definition are local variables and are not available outside the function definition.
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: true
|
#| error: true
|
||||||
x = 3
|
x = 3
|
||||||
@@ -206,72 +206,72 @@ println("z = $z")
|
|||||||
println("c = $c")
|
println("c = $c")
|
||||||
```
|
```
|
||||||
|
|
||||||
Sehr einfache Funktionen können auch als Einzeiler definiert werden.
|
Very simple functions can also be defined as single-line functions.
|
||||||
```{julia}
|
```{julia}
|
||||||
hypotenuse(a, b) = sqrt(a^2+b^2)
|
hypotenuse(a, b) = sqrt(a^2+b^2)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
Tests liefern einen Wahrheitswert zurück.
|
Tests return a Boolean value.
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 3^2
|
x = 3^2
|
||||||
x < 2^3
|
x < 2^3
|
||||||
```
|
```
|
||||||
Neben den üblichen arithmetischen Vergleichen `==, !=, <, <= ,> ,>=`
|
In addition to the usual arithmetic comparisons `==, !=, <, <= ,> ,>=`
|
||||||
gibt es noch viele andere Tests. Natürlich kann man das Ergebnis eines Tests auch einer Variablen zuweisen, welche dann vom Typ `Bool` ist. Die logischen Operatoren `&&`, `||` und Negation `!` können in Tests verwendet werden.
|
there are many other tests. Of course, the result of a test can also be assigned to a variable, which is then of type `Bool`. The logical operators `&&`, `||` and negation `!` can be used in tests.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
test1 = "Auto" in ["Fahrrad", "Auto", "Bahn"]
|
test1 = "Car" in ["Bicycle", "Car", "Train"]
|
||||||
test2 = x == 100 || !(x <= 30 && x > 8)
|
test2 = x == 100 || !(x <= 30 && x > 8)
|
||||||
test3 = startswith("Lampenschirm", "Lamp")
|
test3 = startswith("lampshade", "Lamp")
|
||||||
println("$test1 $test2 $test3")
|
println("$test1 $test2 $test3")
|
||||||
```
|
```
|
||||||
|
|
||||||
## Verzweigungen
|
|
||||||
Verzweigungen (bedingte Anweisungen) haben die Form
|
## Branches
|
||||||
|
Branches (conditional statements) have the form
|
||||||
|
|
||||||
```default
|
```default
|
||||||
if <Test>
|
if <test>
|
||||||
<Anweisung1>
|
<statement1>
|
||||||
<Anweisung2>
|
<statement2>
|
||||||
...
|
...
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
An `else` branch and `elseif` branches are possible.
|
||||||
Ein `else`-Zweig und `elseif`-Zweige sind möglich.
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = sqrt(100)
|
x = sqrt(100)
|
||||||
|
|
||||||
if x > 20
|
if x > 20
|
||||||
println("Seltsam!")
|
println("Strange!")
|
||||||
else
|
else
|
||||||
println("OK")
|
println("OK")
|
||||||
y = x + 3
|
y = x + 3
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Einrückungen verbessern die Lesbarkeit, sind aber fakultativ. Zeilenumbrüche trennen Anweisungen. Das ist auch durch Semikolon möglich. Obiger Codeblock ist für Julia identisch zu folgender Zeile:
|
Indentation improves readability but is optional. Line breaks separate statements. This can also be done with semicolons. The above code block is identical to the following line for Julia:
|
||||||
```{julia}
|
```{julia}
|
||||||
# Bitte nicht so programmieren! Sie werden es bereuen!
|
# Please don't program like this! You will regret it!
|
||||||
x=sqrt(100); if x > 20 println("Seltsam!") else println("OK"); y = x + 3 end
|
x=sqrt(100); if x > 20 println("Strange!") else println("OK"); y = x + 3 end
|
||||||
```
|
```
|
||||||
|
|
||||||
Es wird dringend empfohlen, von Anfang an den eigenen Code übersichtlich mit sauberen Einrückungen zu formatieren!
|
It is strongly recommended to format your own code from the beginning with clear indentation!
|
||||||
|
|
||||||
|
|
||||||
## Einfache `for`-Schleifen
|
## Simple `for` loops
|
||||||
|
|
||||||
zum wiederholten Abarbeiten von Anweisungen haben die Form
|
for repeated execution of statements have the form
|
||||||
```default
|
```default
|
||||||
for <Zähler> = Start:Ende
|
for <counter> = start:end
|
||||||
<Anweisung1>
|
<statement1>
|
||||||
<Anweisung2>
|
<statement2>
|
||||||
...
|
...
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
Beispiel:
|
Example:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
sum = 0
|
sum = 0
|
||||||
@@ -281,9 +281,10 @@ end
|
|||||||
sum
|
sum
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Arrays
|
## Arrays
|
||||||
1-dimensionale Arrays (Vektoren) sind eine einfache Form von Containern. Man kann sie mit echigen Klammern anlegen
|
1-dimensional arrays (vectors) are a simple form of containers. They can be created with square brackets
|
||||||
und auf die Elemente per Index zugreifen. Die Indizierung beginnt mit 1.
|
and accessed by index. Indexing starts at 1.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
v = [12, 33.2, 17, 19, 22]
|
v = [12, 33.2, 17, 19, 22]
|
||||||
@@ -298,17 +299,18 @@ v[1] = v[4] + 10
|
|||||||
v
|
v
|
||||||
```
|
```
|
||||||
|
|
||||||
Man kann leere Vektoren anlegen und sie verlängern.
|
Empty vectors can be created and extended.
|
||||||
```{julia}
|
```{julia}
|
||||||
v = [] # leerer Vektor
|
v = [] # empty vector
|
||||||
push!(v, 42)
|
push!(v, 42)
|
||||||
push!(v, 13)
|
push!(v, 13)
|
||||||
v
|
v
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
:::{.callout-note icon="false" .titlenormal collapse="true" font-variant-ligatures="no-contextual" }
|
:::{.callout-note icon="false" .titlenormal collapse="true" font-variant-ligatures="no-contextual" }
|
||||||
|
|
||||||
## Nachtrag: wie die Wirkung der Tab-Taste auf dieser Seite simuliert wurde...
|
## Postscript: how the effect of the Tab key was simulated on this page...
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using REPL
|
using REPL
|
||||||
|
|||||||
@@ -2,7 +2,18 @@
|
|||||||
engine: julia
|
engine: julia
|
||||||
---
|
---
|
||||||
|
|
||||||
# Maschinenzahlen
|
```{julia}
|
||||||
|
#| error: false
|
||||||
|
#| echo: false
|
||||||
|
#| output: false
|
||||||
|
using InteractiveUtils
|
||||||
|
import QuartoNotebookWorker
|
||||||
|
Base.stdout = QuartoNotebookWorker.with_context(stdout)
|
||||||
|
myactive_module() = Main.Notebook
|
||||||
|
Base.active_module() = myactive_module()
|
||||||
|
```
|
||||||
|
|
||||||
|
# Machine Numbers
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: false
|
#| error: false
|
||||||
@@ -18,24 +29,24 @@ for x ∈ ( 3, 3.3e4, Int16(20), Float32(3.3e4), UInt16(9) )
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ganze Zahlen *(integers)*
|
## Integer Numbers *(integers)*
|
||||||
|
|
||||||
Ganze Zahlen werden grundsätzlich als Bitmuster fester Länge gespeichert. Damit ist der Wertebereich endlich.
|
Integer numbers are fundamentally stored as bit patterns of fixed length. Therefore, the value range is finite.
|
||||||
**Innerhalb dieses Wertebereichs** sind Addition, Subtraktion, Multiplikation und die Ganzzahldivision mit Rest
|
**Within this value range** addition, subtraction, multiplication, and integer division with remainder
|
||||||
exakte Operationen ohne Rundungsfehler.
|
are exact operations without rounding errors.
|
||||||
|
|
||||||
Ganze Zahlen gibt es in den zwei Sorten `Signed` (mit Vorzeichen) und `Unsigned`, die man als Maschinenmodelle für ℤ bzw. ℕ auffassen kann.
|
Integer numbers come in two types: `Signed` (with sign) and `Unsigned`, which can be viewed as machine models for ℤ and ℕ respectively.
|
||||||
|
|
||||||
|
|
||||||
### *Unsigned integers*
|
### *Unsigned integers*
|
||||||
```{julia}
|
```{julia}
|
||||||
subtypes(Unsigned)
|
subtypes(Unsigned)
|
||||||
```
|
```
|
||||||
UInts sind Binärzahlen mit n=8, 16, 32, 64 oder 128 Bits Länge und einem entsprechenden Wertebereich von
|
UInts are binary numbers with n=8, 16, 32, 64, or 128 bits length and the corresponding value range of
|
||||||
$$
|
$$
|
||||||
0 \le x < 2^n
|
0 \le x < 2^n
|
||||||
$$
|
$$
|
||||||
Sie werden im *scientific computing* eher selten verwendet. Bei hardwarenaher Programmierung dienen sie z.B. dem Umgang mit Binärdaten und Speicheradressen. Deshalb werden sie von Julia standardmäßig auch als Hexadezimalzahlen (mit Präfix `0x` und Ziffern `0-9a-f`) dargestellt.
|
They are used relatively rarely in *scientific computing*. In hardware-proximate programming, they are e.g. used for handling binary data and memory addresses. Therefore, Julia displays them by default as hexadecimal numbers (with prefix `0x` and digits `0-9a-f`).
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 0x0033efef
|
x = 0x0033efef
|
||||||
@@ -50,51 +61,51 @@ z = UInt(32)
|
|||||||
```{julia}
|
```{julia}
|
||||||
subtypes(Signed)
|
subtypes(Signed)
|
||||||
```
|
```
|
||||||
*Integers* haben den Wertebereich
|
*Integers* have the value range
|
||||||
$$
|
$$
|
||||||
-2^{n-1} \le x < 2^{n-1}
|
-2^{n-1} \le x < 2^{n-1}
|
||||||
$$
|
$$
|
||||||
|
|
||||||
|
|
||||||
In Julia sind ganze Zahlen standardmäßig 64 Bit groß:
|
In Julia, integer numbers are 64-bit by default:
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 42
|
x = 42
|
||||||
typeof(x)
|
typeof(x)
|
||||||
```
|
```
|
||||||
Sie haben daher den Wertebereich:
|
Therefore, they have the value range:
|
||||||
$$
|
$$
|
||||||
-9.223.372.036.854.775.808 \le x \le 9.223.372.036.854.775.807
|
-9.223.372.036.854.775.808 \le x \le 9.223.372.036.854.775.807
|
||||||
$$
|
$$
|
||||||
|
|
||||||
32-Bit-Integers haben den Wertebereich
|
32-bit integers have the value range
|
||||||
$$
|
$$
|
||||||
-2.147.483.648 \le x \le 2.147.483.647
|
-2.147.483.648 \le x \le 2.147.483.647
|
||||||
$$
|
$$
|
||||||
Der Maximalwert $2^{31}-1$ is zufällig gerade eine Mersenne-Primzahl:
|
The maximum value $2^{31}-1$ is conveniently a Mersenne prime:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using Primes
|
using Primes
|
||||||
isprime(2^31-1)
|
isprime(2^31-1)
|
||||||
```
|
```
|
||||||
|
|
||||||
Negative Zahlen werden im Zweierkomplement dargestellt:
|
Negative numbers are represented in two's complement:
|
||||||
|
|
||||||
$x \Rightarrow -x$ entspricht: _flip all bits, then add 1_
|
$x \Rightarrow -x$ corresponds to: _flip all bits, then add 1_
|
||||||
|
|
||||||
Das sieht so aus:
|
This looks like this:
|
||||||
|
|
||||||
::: {.content-visible when-format="html"}
|
::: {.content-visible when-format="html"}
|
||||||
{width=50%}
|
{width=50%}
|
||||||
:::
|
:::
|
||||||
|
|
||||||
::: {.content-visible when-format="pdf"}
|
::: {.content-visible when-format="pdf"}
|
||||||
{width=50%}
|
{width=50%}
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Das höchstwertige Bit zeigt das Vorzeichen an. Sein „Umkippen“ entspricht allerdings nicht der Operation `x → -x`.
|
The most significant bit indicates the sign. However, its "flipping" does not correspond to the operation `x → -x`.
|
||||||
|
|
||||||
:::{.callout-important}
|
:::{.callout-important}
|
||||||
Die gesamte Ganzzahlarithmetik ist eine __Arithmetik modulo $2^n$__
|
All integer arithmetic is __arithmetic modulo $2^n$__
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 2^62 - 10 + 2^62
|
x = 2^62 - 10 + 2^62
|
||||||
@@ -102,11 +113,11 @@ x = 2^62 - 10 + 2^62
|
|||||||
```{julia}
|
```{julia}
|
||||||
x + 20
|
x + 20
|
||||||
```
|
```
|
||||||
Keine Fehlermeldung, keine Warnung! Ganzzahlen fester Länge liegen nicht auf einer Geraden, sondern auf einem Kreis!
|
No error message, no warning! Fixed-length integers do not lie on a line, but on a circle!
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Schauen wir uns ein paar *Integers* an:
|
Let's look at a few *integers*:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -119,7 +130,7 @@ for i in (1, 2, 7, -7, 2^50, -1, Int16(7), Int8(7))
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Julia hat Funktionen, die über die Datentypen informieren (*introspection*):
|
Julia has functions that provide type information (*introspection*):
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -134,36 +145,36 @@ typemin(UInt64), typemax(UInt64), BigInt(typemax(UInt64))
|
|||||||
typemin(Int8), typemax(Int8)
|
typemin(Int8), typemax(Int8)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Arithmetik ganzer Zahlen
|
## Integer Arithmetic
|
||||||
|
|
||||||
#### Addition, Multiplikation
|
#### Addition, Multiplication
|
||||||
Die Operationen `+`,`-`,`*` haben die übliche exakte Arithmetik **modulo $2^{64}$**.
|
The operations `+`,`-`,`*` have the usual exact arithmetic **modulo $2^{64}$**.
|
||||||
|
|
||||||
#### Potenzen `a^b`
|
#### Powers `a^b`
|
||||||
|
|
||||||
- Potenzen `a^n` werden für natürliche Exponenten `n` ebenfalls modulo $2^{64}$ exakt berechnet.
|
- Powers `a^n` are computed exactly modulo $2^{64}$ for natural exponents `n`.
|
||||||
- Für negative Exponenten ist das Ergebnis eine Gleitkommazahl.
|
- For negative exponents, the result is a floating-point number.
|
||||||
- `0^0` ist [selbstverständlich](https://en.wikipedia.org/wiki/Zero_to_the_power_of_zero#cite_note-T4n3B-4) gleich 1.
|
- `0^0` is [naturally](https://en.wikipedia.org/wiki/Zero_to_the_power_of_zero#cite_note-T4n3B-4) equal to 1.
|
||||||
```{julia}
|
```{julia}
|
||||||
(-2)^63, 2^64, 3^(-3), 0^0
|
(-2)^63, 2^64, 3^(-3), 0^0
|
||||||
```
|
```
|
||||||
- Für natürliche Exponenten wird [*exponentiation by squaring*](https://de.wikipedia.org/wiki/Bin%C3%A4re_Exponentiation) verwendet, so dass z.B. `x^23` nur 7 Multiplikationen benötigt:
|
- For natural exponents, [*exponentiation by squaring*](https://de.wikipedia.org/wiki/Bin%C3%A4re_Exponentiation) is used, so for example `x^23` requires only 7 multiplications:
|
||||||
$$
|
$$
|
||||||
x^{23} = \left( \left( (x^2)^2 \cdot x \right)^2 \cdot x \right)^2 \cdot x
|
x^{23} = \left( \left( (x^2)^2 \cdot x \right)^2 \cdot x \right)^2 \cdot x
|
||||||
$$
|
$$
|
||||||
|
|
||||||
#### Division
|
#### Division
|
||||||
|
|
||||||
- Division `/` erzeugt eine Gleitkommazahl.
|
- Division `/` produces a floating-point number.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 40/5
|
x = 40/5
|
||||||
```
|
```
|
||||||
#### Ganzzahldivision und Rest
|
#### Integer Division and Remainder
|
||||||
|
|
||||||
- Die Funktionen `div(a,b)`, `rem(a,b)` und `divrem(a,b)` berechnen den Quotient der Ganzzahldivision, den dazugehörigen Rest *(remainder)* bzw. beides als Tupel.
|
- The functions `div(a,b)`, `rem(a,b)`, and `divrem(a,b)` compute the quotient of integer division, the corresponding remainder, or both as a tuple.
|
||||||
- Für `div(a,b)` gibt es die Operatorform `a ÷ b` (Eingabe: `\div<TAB>`) und für `rem(a,b)` die Operatorform `a % b`.
|
- For `div(a,b)` there is the operator form `a ÷ b` (input: `\div<TAB>`), and for `rem(a,b)` the operator form `a % b`.
|
||||||
- Standardmäßig wird bei der Division „zur Null hin gerundet“, wodurch der dazugehörige Rest dasselbe Vorzeichen wie der Dividend `a` trägt:
|
- By default, division is "rounded toward zero", so the corresponding remainder has the same sign as the dividend `a`:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show divrem( 27, 4)
|
@show divrem( 27, 4)
|
||||||
@@ -172,9 +183,9 @@ x = 40/5
|
|||||||
@show ( 27 ÷ -4, 27 % -4);
|
@show ( 27 ÷ -4, 27 % -4);
|
||||||
```
|
```
|
||||||
|
|
||||||
- Eine von `RoundToZero` abweichende Rundungsregel kann bei den Funktionen als optionales 3. Argument angegeben werden.
|
- A rounding rule other than `RoundToZero` can be specified as the third optional argument for the functions.
|
||||||
- `?RoundingMode` zeigt die möglichen Rundungsregeln an.
|
- `?RoundingMode` shows the possible rounding modes.
|
||||||
- Für die Rundungsregel `RoundDown` („in Richtung minus unendlich"), wodurch der dazugehörige Rest dasselbe Vorzeichen wie der Divisor `b` bekommt, gibt es auch die Funktionen `fld(a,b)` *(floored division)* und `mod(a,b)`:
|
- For the rounding rule `RoundDown` ("toward minus infinity"), so that the corresponding remainder has the same sign as the divisor `b`, there are also the functions `fld(a,b)` *(floored division)* and `mod(a,b)`:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show divrem(-27, 4, RoundDown)
|
@show divrem(-27, 4, RoundDown)
|
||||||
@@ -182,47 +193,47 @@ x = 40/5
|
|||||||
@show (fld( 27, -4), mod( 27, -4));
|
@show (fld( 27, -4), mod( 27, -4));
|
||||||
```
|
```
|
||||||
|
|
||||||
Für alle Rundungsregeln gilt:
|
For all rounding modes holds:
|
||||||
```
|
```
|
||||||
div(a, b, RoundingMode) * b + rem(a, b, RoundingMode) = a
|
div(a, b, RoundingMode) * b + rem(a, b, RoundingMode) = a
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Der Datentyp `BigInt`
|
#### The `BigInt` Type
|
||||||
|
|
||||||
Der Datentyp `BigInt` ermöglicht Ganzzahlen beliebiger Länge. Der benötigte Speicher wird dynamisch allokiert.
|
The `BigInt` type allows arbitrary-length integers. The required memory is dynamically allocated.
|
||||||
|
|
||||||
Numerische Konstanten haben automatisch einen ausreichend großen Typ:
|
Numeric constants automatically have a sufficiently large type:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
z = 10
|
z = 10
|
||||||
@show typeof(z)
|
@show typeof(z)
|
||||||
z = 10_000_000_000_000_000 # 10 Billiarden
|
z = 10_000_000_000_000_000 # 10 quadrillion
|
||||||
@show typeof(z)
|
@show typeof(z)
|
||||||
z = 10_000_000_000_000_000_000 # 10 Trillionen
|
z = 10_000_000_000_000_000_000 # 10 quintillion
|
||||||
@show typeof(z)
|
@show typeof(z)
|
||||||
z = 10_000_000_000_000_000_000_000_000_000_000_000_000_000 # 10 Sextilliarden
|
z = 10_000_000_000_000_000_000_000_000_000_000_000_000_000 # 10 sextillion
|
||||||
@show typeof(z);
|
@show typeof(z);
|
||||||
```
|
```
|
||||||
|
|
||||||
Meist wird man allerdings den Datentyp `BigInt` explizit anfordern müssen, damit nicht modulo $2^{64}$ gerechnet wird:
|
Usually, one must explicitly request the `BigInt` type to avoid modulo $2^{64}$ arithmetic:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show 3^300 BigInt(3)^300;
|
@show 3^300 BigInt(3)^300;
|
||||||
```
|
```
|
||||||
|
|
||||||
*Arbitrary precision arithmetic* kostet einiges an Speicherplatz und Rechenzeit.
|
*Arbitrary precision arithmetic* comes at a cost of significant memory and computation time.
|
||||||
|
|
||||||
Wir vergleichen den Zeit- und Speicherbedarf bei der Aufsummation von 10 Millionen Ganzzahlen als `Int64` und als `BigInt`.
|
We compare the time and memory requirements for summing 10 million integers as `Int64` and as `BigInt`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
# 10^7 Zufallszahlen, gleichverteilt zwischen -10^7 und 10^7
|
# 10^7 random numbers, uniformly distributed between -10^7 and 10^7
|
||||||
vec_int = rand(-10^7:10^7, 10^7)
|
vec_int = rand(-10^7:10^7, 10^7)
|
||||||
|
|
||||||
# Dieselben Zahlen als BigInts
|
# The same numbers as BigInts
|
||||||
vec_bigint = BigInt.(vec_int)
|
vec_bigint = BigInt.(vec_int)
|
||||||
```
|
```
|
||||||
|
|
||||||
Einen ersten Eindruck vom Zeit- und Speicherbedarf gibt das `@time`-Macro:
|
An initial impression of the time and memory requirements is provided by the `@time` macro:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@time x = sum(vec_int)
|
@time x = sum(vec_int)
|
||||||
@@ -233,7 +244,7 @@ Einen ersten Eindruck vom Zeit- und Speicherbedarf gibt das `@time`-Macro:
|
|||||||
@show x typeof(x);
|
@show x typeof(x);
|
||||||
```
|
```
|
||||||
|
|
||||||
Durch die Just-in-Time-Compilation von Julia ist die einmalige Ausführung einer Funktion wenig aussagekräftig. Das Paket `BenchmarkTools` stellt u.a. das Macro `@benchmark` bereit, das eine Funktion mehrfach aufruft und die Ausführungszeiten als Histogramm darstellt.
|
Due to Julia's just-in-time compilation, a single execution of a function is not very informative. The `BenchmarkTools` package provides the `@benchmark` macro, which calls a function multiple times and displays the execution times as a histogram.
|
||||||
|
|
||||||
:::{.ansitight}
|
:::{.ansitight}
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -247,13 +258,11 @@ using BenchmarkTools
|
|||||||
@benchmark sum($vec_bigint)
|
@benchmark sum($vec_bigint)
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
Die `BigInt`-Addition ist mehr als 30 mal langsamer.
|
The `BigInt` addition is more than 30 times slower.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
:::{.content-hidden unless-format="xxx"}
|
:::{.content-hidden unless-format="xxx"}
|
||||||
Die folgende Funktion soll die Summe aller Zahlen von 1 bis n mit der Arithmetik des Datentyps T berechnen.
|
The following function should compute the sum of all numbers from 1 to n using arithmetic of type T.
|
||||||
Auf Grund der *type promotion rules* reicht es für `T ≥ Int64` dazu aus, die Akkumulatorvariable mit einer Zahl vom Typ T zu initialisieren.
|
Due to the *type promotion rules*, it is sufficient for `T ≥ Int64` to initialize the accumulator variable with a number of type T.
|
||||||
```{julia}
|
```{julia}
|
||||||
function mysum(n, T)
|
function mysum(n, T)
|
||||||
s = T(0)
|
s = T(0)
|
||||||
@@ -264,7 +273,7 @@ function mysum(n, T)
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Einen ersten Eindruck vom Zeit- und Speicherbedarf gibt das `@time`-Macro:
|
An initial impression of the time and memory requirements is provided by the `@time` macro:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@time x = mysum(10_000_000, Int64)
|
@time x = mysum(10_000_000, Int64)
|
||||||
@@ -276,7 +285,7 @@ Einen ersten Eindruck vom Zeit- und Speicherbedarf gibt das `@time`-Macro:
|
|||||||
@show x typeof(x);
|
@show x typeof(x);
|
||||||
```
|
```
|
||||||
|
|
||||||
Durch die Just-in-Time-Compilation von Julia ist die einmalige Ausführung einer Funktion wenig aussagekräftig. Das Paket `BenchmarkTools` stellt u.a. das Macro `@benchmark` bereit, das eine Funktion mehrfach aufruft und die Ausführungszeiten als Histogramm darstellt.
|
Due to Julia's just-in-time compilation, a single execution of a function is not very informative. The `BenchmarkTools` package provides the `@benchmark` macro, which calls a function multiple times and displays the execution times as a histogram.
|
||||||
|
|
||||||
:::{.ansitight}
|
:::{.ansitight}
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -292,85 +301,84 @@ using BenchmarkTools
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Die Berechnung von $\sum_{n=1}^{10000000} n$ dauert auf meinem PC mit den Standard-64bit-Integern im Schnitt 2 Nanosekunden, in *arbitrary precision arithmetic* über eine Sekunde, wobei auch noch fast 500MB Speicher allokiert werden.
|
The computation of $\sum_{n=1}^{10000000} n$ takes on my PC an average of 2 nanoseconds with standard 64-bit integers and over one second in *arbitrary precision arithmetic*, during which nearly 500MB of memory is also allocated.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
## Gleitkommazahlen
|
## Floating-Point Numbers
|
||||||
|
|
||||||
Aus _floating point numbers_ kann man im Deutschen **[Gleit|Fließ]--[Komma|Punkt]--Zahlen** machen
|
From _floating point numbers_, one can form German **[Gleit|Fließ]--[Komma|Punkt]--Zahlen**, and indeed all 4 variants appear in the literature.
|
||||||
und tatsächlich kommen alle 4 Varianten in der Literatur vor.
|
|
||||||
|
|
||||||
In der Numerischen Mathematik spricht man auch gerne von **Maschinenzahlen**.
|
In numerical mathematics, one also often speaks of **machine numbers**.
|
||||||
|
|
||||||
|
|
||||||
### Grundidee
|
### Basic Idea
|
||||||
|
|
||||||
- Eine „feste Anzahl von Vor- und Nachkommastellen“ ist für viele Probleme ungeeignet.
|
- A "fixed number of digits before and after the decimal point" is unsuitable for many problems.
|
||||||
- Eine Trennung zwischen „gültigen Ziffern“ und Größenordnung (Mantisse und Exponent) wie in der wissenschaftlichen Notation ist wesentlich flexibler.
|
- A separation between "significant digits" and magnitude (mantissa and exponent), as in scientific notation, is much more flexible.
|
||||||
$$ 345.2467 \times 10^3\qquad 34.52467\times 10^4\qquad \underline{3.452467\times 10^5}\qquad 0.3452467\times 10^6\qquad 0.03452467\times 10^7$$
|
$$ 345.2467 \times 10^3\qquad 34.52467\times 10^4\qquad \underline{3.452467\times 10^5}\qquad 0.3452467\times 10^6\qquad 0.03452467\times 10^7$$
|
||||||
- Zur Eindeutigkeit muss man eine dieser Formen auswählen. In der mathematischen Analyse von Maschinenzahlen wählt man oft die Form, bei der die erste Nachkommastelle ungleich Null ist. Damit gilt für die Mantisse $m$:
|
- For uniqueness, one must choose one of these forms. In the mathematical analysis of machine numbers, one often chooses the form where the first digit after the decimal point is nonzero. Thus, for the mantissa $m$:
|
||||||
$$
|
$$
|
||||||
1 > m \ge (0.1)_b = b^{-1},
|
1 > m \ge (0.1)_b = b^{-1},
|
||||||
$$
|
$$
|
||||||
wobei $b$ die gewählte Basis des Zahlensystems bezeichnet.
|
where $b$ denotes the base of the number system.
|
||||||
- Wir wählen im Folgenden die Form, die der tatsächlichen Implementation auf dem Computer entspricht und legen fest:
|
- We choose the form that corresponds to the actual implementation on the computer and specify:
|
||||||
Die Darstellung mit genau einer Ziffer ungleich Null vor dem Komma ist die __Normalisierte Darstellung__. Damit gilt
|
The representation with exactly one nonzero digit before the decimal point is the __normalized representation__. Thus,
|
||||||
$$
|
$$
|
||||||
(10)_b = b> m \ge 1.
|
(10)_b = b> m \ge 1.
|
||||||
$$
|
$$
|
||||||
- Bei Binärzahlen `1.01101` ist diese Ziffer immer gleich Eins und man kann auf das Abspeichern dieser Ziffer verzichten. Diese tatsächlich abgespeicherte (gekürzte) Mantisse bezeichnen wir mit $M$, so dass
|
- For binary numbers `1.01101`, this digit is always equal to one, and one can omit storing this digit. This actually stored (shortened) mantissa we denote by $M$, so that
|
||||||
$$m = 1 + M$$
|
$$m = 1 + M$$
|
||||||
gilt.
|
holds.
|
||||||
|
|
||||||
|
|
||||||
:::{.callout-note }
|
:::{.callout-note }
|
||||||
|
|
||||||
## Maschinenzahlen
|
## Machine Numbers
|
||||||
|
|
||||||
Die Menge der Maschinenzahlen $𝕄(b, p, e_{min}, e_{max})$ ist charakterisiert durch die verwendete Basis $b$, die Mantissenlänge $p$ und den Wertebereich des Exponenten $\{e_{min}, ... ,e_{max}\}$.
|
The set of machine numbers $𝕄(b, p, e_{min}, e_{max})$ is characterized by the base $b$ used, the mantissa length $p$, and the value range of the exponent $\{e_{min}, ... ,e_{max}\}$.
|
||||||
|
|
||||||
In unserer Konvention hat die Mantisse einer normalisierten Maschinenzahl eine Ziffer (der Basis $b$) ungleich Null vor dem Komma und $p-1$ Nachkommastellen.
|
In our convention, the mantissa of a normalized machine number has one digit (of base $b$) nonzero before the decimal point and $p-1$ digits after the decimal point.
|
||||||
|
|
||||||
Wenn $b=2$ ist, braucht man daher nur $p-1$ Bits zur Speicherung der Mantisse normalisierter Gleitkommazahlen.
|
If $b=2$, one needs only $p-1$ bits to store the mantissa of normalized floating-point numbers.
|
||||||
|
|
||||||
Der Standard IEEE 754, der von der Mahrzahl der modernen Prozessoren und Programmiersprachen implementiert wird, definiert
|
The IEEE 754 standard, implemented by most modern processors and programming languages, defines
|
||||||
|
|
||||||
- `Float32` als $𝕄(2, 24, -126, 127 )$ und
|
- `Float32` as $𝕄(2, 24, -126, 127 )$ and
|
||||||
- `Float64` als $𝕄(2, 53, -1022, 1023 ).$
|
- `Float64` as $𝕄(2, 53, -1022, 1023 ).$
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### Aufbau von `Float64` nach [Standard IEEE 754](https://de.wikipedia.org/wiki/IEEE_754)
|
### Structure of `Float64` according to [IEEE 754 standard](https://de.wikipedia.org/wiki/IEEE_754)
|
||||||
|
|
||||||
|
|
||||||
::: {.content-visible when-format="html"}
|
::: {.content-visible when-format="html"}
|
||||||
![Aufbau einer `Float64` (Quelle:^[Quelle: <a href="https://commons.wikimedia.org/wiki/File:IEEE_754_Double_Floating_Point_Format.svg">Codekaizen</a>, <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via Wikimedia Commons ])
|
![Structure of a `Float64` (source:^[Source: <a href="https://commons.wikimedia.org/wiki/File:IEEE_754_Double_Floating_Point_Format.svg">Codekaizen</a>, <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via Wikimedia Commons ])
|
||||||
](../images/1024px-IEEE_754_Double_Floating_Point_Format.png)
|
](../images/1024px-IEEE_754_Double_Floating_Point_Format.png)
|
||||||
:::
|
:::
|
||||||
|
|
||||||
::: {.content-visible when-format="pdf"}
|
::: {.content-visible when-format="pdf"}
|
||||||
{width="70%"}
|
](../images/1024px-IEEE_754_Double_Floating_Point_Format.png){width="70%"}
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
- 1 Vorzeichenbit $S$
|
- 1 sign bit $S$
|
||||||
- 11 Bits für den Exponenten, also $0\le E \le 2047$
|
- 11 bits for the exponent, thus $0\le E \le 2047$
|
||||||
- die Werte $E=0$ und $E=(11111111111)_2=2047$ sind reserviert für die Codierung von Spezialwerten wie
|
- The values $E=0$ and $E=(11111111111)_2=2047$ are reserved for encoding special values such as
|
||||||
$\pm0, \pm\infty$, NaN _(Not a Number)_ und denormalisierte Zahlen.
|
$\pm0, \pm\infty$, NaN _(Not a Number)_ and subnormal numbers.
|
||||||
- 52 Bits für die (gekürzte) Mantisse $M,\quad 0\le M<1$, das entspricht etwa 16 Dezimalstellen
|
- 52 bits for the (shortened) mantissa $M,\quad 0\le M<1$, corresponding to approximately 16 decimal digits
|
||||||
- Damit wird folgende Zahl dargestellt:
|
- Thus, the following number is represented:
|
||||||
$$ x=(-1)^S \cdot(1+M)\cdot 2^{E-1023}$$
|
$$ x=(-1)^S \cdot(1+M)\cdot 2^{E-1023}$$
|
||||||
|
|
||||||
Ein Beispiel:
|
An example:
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 27.56640625
|
x = 27.56640625
|
||||||
bitstring(x)
|
bitstring(x)
|
||||||
```
|
```
|
||||||
Das geht auch schöner:
|
This can be done more nicely:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
function printbitsf64(x::Float64)
|
function printbitsf64(x::Float64)
|
||||||
@@ -383,7 +391,7 @@ end
|
|||||||
|
|
||||||
printbitsf64(x)
|
printbitsf64(x)
|
||||||
```
|
```
|
||||||
und wir können S (in blau),E (grün) und M (rot) ablesen:
|
and we can read S (blue), E (green), and M (red):
|
||||||
$$
|
$$
|
||||||
\begin{aligned}
|
\begin{aligned}
|
||||||
S &= 0\\
|
S &= 0\\
|
||||||
@@ -394,15 +402,15 @@ x &=(-1)^S \cdot(1+M)\cdot 2^{E-1023}
|
|||||||
$$
|
$$
|
||||||
|
|
||||||
|
|
||||||
... und damit die Zahl rekonstruieren:
|
... and thus reconstruct the number:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = (1 + 1/2 + 1/8 + 1/16 + 1/32 + 1/256 + 1/4096) * 2^4
|
x = (1 + 1/2 + 1/8 + 1/16 + 1/32 + 1/256 + 1/4096) * 2^4
|
||||||
```
|
```
|
||||||
|
|
||||||
- Die Maschinenzahlen 𝕄 bilden eine endliche, diskrete Untermenge von ℝ. Es gibt eine kleinste und eine größte Maschinenzahl und abgesehen davon haben alle x∈𝕄 einen Vorgänger und Nachfolger in 𝕄.
|
- The machine numbers 𝕄 form a finite, discrete subset of ℝ. There is a smallest and a largest machine number, and apart from these, all x∈𝕄 have a predecessor and successor in 𝕄.
|
||||||
- Was ist der Nachfolger von x in 𝕄? Dazu setzen wir das kleinste Mantissenbit von 0 auf 1.
|
- What is the successor of x in 𝕄? To do this, we set the smallest mantissa bit from 0 to 1.
|
||||||
- Die Umwandlung eines Strings aus Nullen und Einsen in die entsprechende Maschinenzahl ist z.B. so möglich:
|
- Converting a string of zeros and ones into the corresponding machine number is possible e.g. as follows:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -410,13 +418,13 @@ ux = parse(UInt64, "010000000011101110010001000000000000000000000000000000000000
|
|||||||
reinterpret(Float64, ux)
|
reinterpret(Float64, ux)
|
||||||
```
|
```
|
||||||
|
|
||||||
Das kann man in Julia allerdings auch einfacher haben:
|
However, Julia can do this more simply:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
y = nextfloat(x)
|
y = nextfloat(x)
|
||||||
```
|
```
|
||||||
|
|
||||||
Der Vorgänger von x ist:
|
The predecessor of x is:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
z = prevfloat(x)
|
z = prevfloat(x)
|
||||||
@@ -426,32 +434,30 @@ printbitsf64(z)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Machine Epsilon
|
||||||
|
|
||||||
|
- The distance between `1` and its successor `nextfloat(1)` is called [**machine epsilon**](https://en.wikipedia.org/wiki/Machine_epsilon).
|
||||||
## Maschinenepsilon
|
- For `Float64` with a mantissa length of 52 bits, $\epsilon=2^{-52}$.
|
||||||
|
|
||||||
- Den Abstand zwischen `1` und dem Nachfolger `nextfloat(1)` nennt man [**Maschinenepsilon**](https://en.wikipedia.org/wiki/Machine_epsilon).
|
|
||||||
- Für `Float64` mit einer Mantissenlänge von 52 Bit ist $\epsilon=2^{-52}$.
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show nextfloat(1.) - 1 2^-52 eps(Float64);
|
@show nextfloat(1.) - 1 2^-52 eps(Float64);
|
||||||
```
|
```
|
||||||
|
|
||||||
- Das Maschinenepsilon ist ein Maß für den relativen Abstand zwischen den Maschinenzahlen und quantifiziert die Aussage: „64-Bit-Gleitkommazahlen haben eine Genauigkeit von etwa 16 Dezimalstellen.“
|
- Machine epsilon is a measure of the relative distance between machine numbers and quantifies the statement: "64-bit floating-point numbers have a precision of approximately 16 decimal digits."
|
||||||
- Das Maschinenepsilon ist etwas völlig anderes als die kleinste positive Gleitkommazahl:
|
- Machine epsilon is something completely different from the smallest positive floating-point number:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
floatmin(Float64)
|
floatmin(Float64)
|
||||||
```
|
```
|
||||||
|
|
||||||
- Ein Teil der Literatur verwendet eine andere Definition des Maschinenepsilons, die halb so groß ist.
|
- Part of the literature uses a different definition of machine epsilon, which is half as large.
|
||||||
$$
|
$$
|
||||||
\epsilon' = \frac{\epsilon}{2}\approx 1.1\times 10^{-16}
|
\epsilon' = \frac{\epsilon}{2}\approx 1.1\times 10^{-16}
|
||||||
$$
|
$$
|
||||||
ist der maximale relative Fehler, der beim Runden einer reellen Zahl auf die nächste Maschinenzahl entstehen kann.
|
is the maximum relative error that can occur when rounding a real number to the nearest machine number.
|
||||||
- Da Zahlen aus dem Intervall $(1-\epsilon',1+\epsilon']$ auf die Maschinenzahl $1$ gerundet werden, kann man $\epsilon'$ auch definieren als: *die größte Zahl, für die in der Maschinenzahlarithmetik noch gilt: $1+\epsilon' = 1$.*
|
- Since numbers in the interval $(1-\epsilon',1+\epsilon']$ are rounded to the machine number $1$, one can also define $\epsilon'$ as: *the largest number for which in machine arithmetic still holds: $1+\epsilon' = 1$.*
|
||||||
|
|
||||||
Auf diese Weise kann man das Maschinenepsilon auch berechnen:
|
In this way, one can also compute machine epsilon:
|
||||||
|
|
||||||
:::{.ansitight}
|
:::{.ansitight}
|
||||||
|
|
||||||
@@ -464,7 +470,7 @@ end
|
|||||||
Eps
|
Eps
|
||||||
```
|
```
|
||||||
|
|
||||||
oder als Bitmuster:
|
or as a bit pattern:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
Eps=1
|
Eps=1
|
||||||
@@ -478,19 +484,19 @@ Eps
|
|||||||
:::
|
:::
|
||||||
|
|
||||||
:::{.callout-note}
|
:::{.callout-note}
|
||||||
## Die Menge der (normalisierten) Maschinenzahlen
|
## The Set of (normalized) Machine Numbers
|
||||||
|
|
||||||
- Im Intervall $[1,2)$ liegen $2^{52}$ äquidistante Maschinenzahlen.
|
- In the interval $[1,2)$ there are $2^{52}$ equidistant machine numbers.
|
||||||
- Danach erhöht sich der Exponent um 1 und die Mantisse $M$ wird auf 0 zurückgesetzt. Damit enthält das Intervall $[2,4)$ wiederum $2^{52}$ äquidistante Maschinenzahlen, ebenso das Intervall $[4,8)$ bis hin zu $[2^{1023}, 2^{1024})$.
|
- After that, the exponent increases by 1 and the mantissa $M$ is reset to 0. Thus, the interval $[2,4)$ again contains $2^{52}$ equidistant machine numbers, as does the interval $[4,8)$ up to $[2^{1023}, 2^{1024})$.
|
||||||
- Ebenso liegen in den Intervallen $\ [\frac{1}{2},1), \ [\frac{1}{4},\frac{1}{2}),...$ je $2^{52}$ äquidistante Maschinenzahlen, bis hinunter zu $[2^{-1022}, 2^{-1021})$.
|
- Likewise, in the intervals $\ [\frac{1}{2},1), \ [\frac{1}{4},\frac{1}{2}),...$ there are $2^{52}$ equidistant machine numbers each, down to $[2^{-1022}, 2^{-1021})$.
|
||||||
- Dies bildet die Menge $𝕄_+$ der positiven Maschinenzahlen und es ist
|
- This forms the set $𝕄_+$ of positive machine numbers, and it is
|
||||||
$$
|
$$
|
||||||
𝕄 = -𝕄_+ \cup \{0\} \cup 𝕄_+
|
𝕄 = -𝕄_+ \cup \{0\} \cup 𝕄_+
|
||||||
$$
|
$$
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Die größte und die kleinste positive normalisiert darstellbare Gleitkommazahl eines Gleitkommatyps kann man abfragen:
|
The largest and smallest positive representable normalized floating-point numbers of a floating-point type can be queried:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show floatmax(Float64)
|
@show floatmax(Float64)
|
||||||
@@ -502,37 +508,35 @@ printbitsf64(floatmin(Float64))
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Rounding to Machine Numbers
|
||||||
|
|
||||||
|
- The mapping rd: ℝ $\rightarrow$ 𝕄 should round to the nearest representable number.
|
||||||
## Runden auf Maschinenzahlen
|
- Standard rounding mode: _round to nearest, ties to even_
|
||||||
|
If one lands exactly in the middle between two machine numbers *(tie)*, one chooses the one whose last mantissa bit is 0.
|
||||||
- Die Abbildung rd: ℝ $\rightarrow$ 𝕄 soll zur nächstgelegenen darstellbaren Zahl runden.
|
- Justification: this way, in 50% of the cases one rounds up and in 50% down, thus avoiding a "statistical drift" in longer calculations.
|
||||||
- Standardrundungsregel: _round to nearest, ties to even_
|
- It holds:
|
||||||
Wenn man genau die Mitte zwischen zwei Maschinenzahlen trifft *(tie)*, wählt man die, deren letztes Mantissenbit 0 ist.
|
|
||||||
- Begründung: damit wird statistisch in 50% der Fälle auf- und in 50% der Fälle abgerundet und so ein „statistischer Drift“ bei längeren Rechnungen vermieden.
|
|
||||||
- Es gilt:
|
|
||||||
$$
|
$$
|
||||||
\frac{|x-\text{rd}(x)|}{|x|} \le \frac{1}{2} \epsilon
|
\frac{|x-\text{rd}(x)|}{|x|} \le \frac{1}{2} \epsilon
|
||||||
$$
|
$$
|
||||||
|
|
||||||
|
|
||||||
## Maschinenzahlarithmetik
|
## Machine Number Arithmetic
|
||||||
|
|
||||||
Die Maschinenzahlen sind als Untermenge von ℝ nicht algebraisch abgeschlossen. Schon die Summe zweier Maschinenzahlen wird in der Regel keine Maschinenzahl sein.
|
The machine numbers, as a subset of ℝ, are not algebraically closed. Even the sum of two machine numbers will generally not be a machine number.
|
||||||
|
|
||||||
:::{.callout-important}
|
:::{.callout-important}
|
||||||
Der Standard IEEE 754 fordert, dass die Maschinenzahlarithmetik das *gerundete exakte Ergebnis* liefert:
|
The IEEE 754 standard requires that machine number arithmetic produces the *rounded exact result*:
|
||||||
|
|
||||||
Das Resultat muss gleich demjenigen sein, das bei einer exakten Ausführung der entsprechenden Operation mit anschließender Rundung entsteht.
|
The result must be equal to the one that would result from an exact execution of the corresponding operation followed by rounding.
|
||||||
$$
|
$$
|
||||||
a \oplus b = \text{rd}(a + b)
|
a \oplus b = \text{rd}(a + b)
|
||||||
$$
|
$$
|
||||||
Analoges muss für die Implemetierung der Standardfunktionen wie
|
The same must hold for the implementation of standard functions such as
|
||||||
wie `sqrt()`, `log()`, `sin()` ... gelten: Sie liefern ebenfalls die Maschinenzahl, die dem exakten Ergebnis am nächsten kommt.
|
`sqrt()`, `log()`, `sin()` ...: they also return the machine number closest to the exact result.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
Die Arithmetik ist *nicht assoziativ*:
|
Arithmetic is *not associative*:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
1 + 10^-16 + 10^-16
|
1 + 10^-16 + 10^-16
|
||||||
@@ -542,7 +546,7 @@ Die Arithmetik ist *nicht assoziativ*:
|
|||||||
1 + (10^-16 + 10^-16)
|
1 + (10^-16 + 10^-16)
|
||||||
```
|
```
|
||||||
|
|
||||||
Im ersten Fall (ohne Klammern) wird von links nach rechts ausgewertet:
|
In the first case (without parentheses), evaluation proceeds from left to right:
|
||||||
$$
|
$$
|
||||||
\begin{aligned}
|
\begin{aligned}
|
||||||
1 \oplus 10^{-16} \oplus 10^{-16} &=
|
1 \oplus 10^{-16} \oplus 10^{-16} &=
|
||||||
@@ -553,7 +557,7 @@ $$
|
|||||||
\end{aligned}
|
\end{aligned}
|
||||||
$$
|
$$
|
||||||
|
|
||||||
Im zweiten Fall erhält man:
|
In the second case, one obtains:
|
||||||
$$
|
$$
|
||||||
\begin{aligned}
|
\begin{aligned}
|
||||||
1 \oplus \left(10^{-16} \oplus 10^{-16}\right) &=
|
1 \oplus \left(10^{-16} \oplus 10^{-16}\right) &=
|
||||||
@@ -564,7 +568,7 @@ $$
|
|||||||
$$
|
$$
|
||||||
|
|
||||||
|
|
||||||
Es sei auch daran erinnert, dass sich selbst „einfache“ Dezimalbrüche häufig nicht exakt als Maschinenzahlen darstellen lassen:
|
One should also be reminded that even "simple" decimal fractions often cannot be represented exactly as machine numbers:
|
||||||
|
|
||||||
$$
|
$$
|
||||||
\begin{aligned}
|
\begin{aligned}
|
||||||
@@ -573,13 +577,12 @@ $$
|
|||||||
\end{aligned}
|
\end{aligned}
|
||||||
$$
|
$$
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
printbitsf64(0.1)
|
printbitsf64(0.1)
|
||||||
printbitsf64(0.3)
|
printbitsf64(0.3)
|
||||||
```
|
```
|
||||||
|
|
||||||
Folge:
|
Consequence:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
0.1 + 0.1 == 0.2
|
0.1 + 0.1 == 0.2
|
||||||
@@ -593,7 +596,7 @@ Folge:
|
|||||||
0.2 + 0.1
|
0.2 + 0.1
|
||||||
```
|
```
|
||||||
|
|
||||||
Bei der Ausgabe einer Maschinenzahl muss der Binärbruch in einen Dezimalbruch entwickelt werden. Man kann sich auch mehr Stellen dieser Dezimalbruchentwicklung anzeigen lassen:
|
When outputting a machine number, the binary fraction must be converted to a decimal fraction. One can also display more digits of this decimal fraction expansion:
|
||||||
```{julia}
|
```{julia}
|
||||||
using Printf
|
using Printf
|
||||||
@printf("%.30f", 0.1)
|
@printf("%.30f", 0.1)
|
||||||
@@ -602,12 +605,12 @@ using Printf
|
|||||||
```{julia}
|
```{julia}
|
||||||
@printf("%.30f", 0.3)
|
@printf("%.30f", 0.3)
|
||||||
```
|
```
|
||||||
Die Binärbruch-Mantisse einer Maschinenzahl kann eine lange oder sogar unendlich-periodische Dezimalbruchentwicklung haben. Dadurch
|
The binary fraction mantissa of a machine number can have a long or even infinitely periodic decimal expansion. Therefore,
|
||||||
sollte man sich nicht eine „höheren Genauigkeit“ suggerieren lassen!
|
one should not be misled into thinking there is "higher precision"!
|
||||||
|
|
||||||
:::{.callout-important}
|
:::{.callout-important}
|
||||||
Moral: wenn man `Float`s auf Gleichheit testen will, sollte man fast immer eine dem Problem angemessene realistische Genauigkeit `epsilon` festlegen und
|
Moral: when testing `Float`s for equality, one should almost always define a realistic accuracy `epsilon` appropriate to the problem and
|
||||||
darauf testen:
|
test:
|
||||||
|
|
||||||
```julia
|
```julia
|
||||||
epsilon = 1.e-10
|
epsilon = 1.e-10
|
||||||
@@ -618,23 +621,22 @@ end
|
|||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Normalisierte und Denormalisierte Maschinenzahlen
|
## Normalized and Subnormal Machine Numbers
|
||||||
|
|
||||||
Die Lücke zwischen Null und der kleinsten normalisierten Maschinenzahl $2^{-1022} \approx 2.22\times 10^{-308}$
|
The gap between zero and the smallest normalized machine number $2^{-1022} \approx 2.22\times 10^{-308}$
|
||||||
ist mit denormalisierten Maschinenzahlen besiedelt.
|
is filled with subnormal machine numbers.
|
||||||
|
|
||||||
Zum Verständnis nehmen wir ein einfaches Modell:
|
For understanding, let's take a simple model:
|
||||||
|
|
||||||
- Sei 𝕄(10,4,±5) die Menge der Maschinenzahlen zur Basis 10 mit 4 Mantissenstellen (eine vor dem Komma, 3 Nachkommastellen) und dem Exponentenbereich -5 ≤ E ≤ 5.
|
- Let 𝕄(10,4,±5) be the set of machine numbers to base 10 with 4 mantissa digits (one before the decimal point, 3 after) and the exponent range -5 ≤ E ≤ 5.
|
||||||
- Dann ist die normalisierte Darstellung (Vorkommastelle ungleich 0)
|
- Then the normalized representation (nonzero leading digit)
|
||||||
von z.B. 1234.0 gleich 1.234e3 und von 0.00789 gleich 7.890e-3.
|
of e.g. 1234.0 is 1.234e3 and of 0.00789 is 7.890e-3.
|
||||||
- Es ist wichtig, dass die Maschinenzahlen bei jedem Rechenschritt normalisiert gehalten werden. Nur so wird die Mantissenlänge voll ausgenutzt und die Genauigkeit ist maximal.
|
- It is important that machine numbers are kept normalized at every computation step. Only then is the mantissa length fully utilized and the accuracy is maximum.
|
||||||
- Die kleinste positive normalisierte Zahl in unserem Modell ist `x = 1.000e-5`. Schon `x/2` müsste auf 0 gerundet werden.
|
- The smallest positive normalized number in our model is `x = 1.000e-5`. Already `x/2` would have to be rounded to 0.
|
||||||
- Hier erweist es sich für viele Anwendungen als günstiger, auch denormalisierte *(subnormal)* Zahlen zuzulassen und `x/2` als `0.500e-5` oder `x/20` als `0.050e-5` darzustellen.
|
- Here, for many applications, it is advantageous to allow also subnormal *(subnormal)* numbers and represent `x/2` as `0.500e-5` or `x/20` as `0.050e-5`.
|
||||||
- Dieser *gradual underflow* ist natürlich mit einem Verlust an gültigen Stellen und damit Genauigkeit verbunden.
|
- This *gradual underflow* is当然 associated with a loss of valid digits and thus accuracy.
|
||||||
|
|
||||||
|
In the `Float` data type, such *subnormal values* are represented by an exponent field in which all bits are equal to zero:
|
||||||
Im `Float`-Datentyp werden solche *subnormal values* dargestellt durch ein Exponentenfeld, in dem alle Bits gleich Null sind:
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| echo: false
|
#| echo: false
|
||||||
@@ -647,7 +649,7 @@ flush(stdout)
|
|||||||
```{julia}
|
```{julia}
|
||||||
using Printf
|
using Printf
|
||||||
|
|
||||||
x = 2 * floatmin(Float64) # 2*kleinste normalisierte Gleitkommazahl > 0
|
x = 2 * floatmin(Float64) # 2*smallest normalized floating-point number > 0
|
||||||
|
|
||||||
while x != 0
|
while x != 0
|
||||||
x /= 2
|
x /= 2
|
||||||
@@ -657,9 +659,9 @@ end
|
|||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Spezielle Werte
|
## Special Values
|
||||||
|
|
||||||
Die Gleitkommaarithmetik kennt einige spezielle Werte, z.B.
|
Floating-point arithmetic knows some special values, e.g.
|
||||||
```{julia}
|
```{julia}
|
||||||
nextfloat(floatmax(Float64))
|
nextfloat(floatmax(Float64))
|
||||||
```
|
```
|
||||||
@@ -671,23 +673,22 @@ for x ∈ (NaN, Inf, -Inf, -0.0)
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
- Ein Exponentenüberlauf *(overflow)* führt zum Ergebnis `Inf` oder `-Inf`.
|
- An exponent overflow *(overflow)* leads to the result `Inf` or `-Inf`.
|
||||||
```{julia}
|
```{julia}
|
||||||
2/0, -3/0, floatmax(Float64) * 1.01, exp(1300)
|
2/0, -3/0, floatmax(Float64) * 1.01, exp(1300)
|
||||||
```
|
```
|
||||||
- Damit kann weitergerechnet werden:
|
- One can continue calculating with it:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
-Inf + 20, Inf/30, 23/-Inf, sqrt(Inf), Inf * 0, Inf - Inf
|
-Inf + 20, Inf/30, 23/-Inf, sqrt(Inf), Inf * 0, Inf - Inf
|
||||||
```
|
```
|
||||||
- `NaN` *(Not a Number)* steht für das Resultat einer Operation, das undefiniert ist. Alle weiteren Operationen mit `NaN` ergeben ebenfalls `NaN`.
|
- `NaN` *(Not a Number)* stands for the result of an operation that is undefined. All further operations with `NaN` also result in `NaN`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
0/0, Inf - Inf, 2.3NaN, sqrt(NaN)
|
0/0, Inf - Inf, 2.3NaN, sqrt(NaN)
|
||||||
```
|
```
|
||||||
|
- Since `NaN` represents an undefined value, it is not equal to anything, not even to itself. This is sensible, because if two variables `x` and `y` are computed as `NaN`, one should not conclude that they are equal.
|
||||||
- Da `NaN` einen undefinierten Wert repräsentiert, ist es zu nichts gleich, nichtmal zu sich selbst. Das ist sinnvoll, denn wenn zwei Variablen `x` und `y` als `NaN` berechnet wurden, sollte man nicht schlußfolgern, dass sie gleich sind.
|
- There is therefore a boolean function `isnan()` to test for `NaN`.
|
||||||
- Zum Testen auf `NaN` gibt es daher die boolsche Funktion `isnan()`.
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 0/0
|
x = 0/0
|
||||||
@@ -695,18 +696,18 @@ y = Inf - Inf
|
|||||||
@show x==y NaN==NaN isfinite(NaN) isinf(NaN) isnan(x) isnan(y);
|
@show x==y NaN==NaN isfinite(NaN) isinf(NaN) isnan(x) isnan(y);
|
||||||
```
|
```
|
||||||
|
|
||||||
- Es gibt eine „minus Null“. Sie signalisiert einen Exponentenunterlauf *(underflow)* einer betragsmäßig zu klein gewordenen *negativen* Größe.
|
- There is a "minus zero". It signals an exponent underflow *(underflow)* of a magnitude that has become too small *negative* quantity.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show 23/-Inf -2/exp(1200) -0.0==0.0;
|
@show 23/-Inf -2/exp(1200) -0.0==0.0;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Mathematische Funktionen
|
## Mathematical Functions
|
||||||
|
|
||||||
Julia verfügt über die [üblichen mathematischen Funktionen](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Rounding-functions)
|
Julia has the [usual mathematical functions](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Rounding-functions)
|
||||||
`sqrt, exp, log, log2, log10, sin, cos,..., asin, acos,..., sinh,..., gcd, lcm, factorial,...,abs, max, min,...`,
|
`sqrt, exp, log, log2, log10, sin, cos,..., asin, acos,..., sinh,..., gcd, lcm, factorial,...,abs, max, min,...`,
|
||||||
|
|
||||||
darunter z.B. die [Rundungsfunktionen](https://de.wikipedia.org/wiki/Abrundungsfunktion_und_Aufrundungsfunktion)
|
including e.g. the [rounding functions](https://de.wikipedia.org/wiki/Abrundungsfunktion_und_Aufrundungsfunktion)
|
||||||
|
|
||||||
- `floor(T,x)` = $\lfloor x \rfloor$
|
- `floor(T,x)` = $\lfloor x \rfloor$
|
||||||
- `ceil(T,x)` = $\lceil x \rceil$
|
- `ceil(T,x)` = $\lceil x \rceil$
|
||||||
@@ -719,19 +720,19 @@ floor(3.4), floor(Int64, 3.5), floor(Int64, -3.5)
|
|||||||
ceil(3.4), ceil(Int64, 3.5), ceil(Int64, -3.5)
|
ceil(3.4), ceil(Int64, 3.5), ceil(Int64, -3.5)
|
||||||
```
|
```
|
||||||
|
|
||||||
Es sei noch hingewiesen auf `atan(y, x)`, den [Arkustangens mit 2 Argumenten](https://de.wikipedia.org/wiki/Arctan2), Er ist in anderen Programmiersprachen oft als Funktion mit eigenem Namen *atan2* implementiert.
|
Also worth noting is `atan(y, x)`, the [two-argument arctangent](https://de.wikipedia.org/wiki/Arctan2). In other programming languages, it is often implemented as a function with its own name *atan2*.
|
||||||
Dieser löst das Problem der Umrechnung von kartesischen in Polarkoordinaten ohne lästige Fallunterscheidung.
|
This solves the problem of converting from Cartesian to polar coordinates without awkward case distinctions.
|
||||||
|
|
||||||
- `atan(y,x)` ist Winkel der Polarkoordinaten von (x,y) im Intervall $(-\pi,\pi]$. Im 1. und 4. Quadranten ist er also gleich `atan(y/x)`
|
- `atan(y,x)` is the angle of the polar coordinates of (x,y) in the interval $(-\pi,\pi]$. In the 1st and 4th quadrants, it is therefore equal to `atan(y/x)`
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
atan(3, -2), atan(-3, 2), atan(-3/2)
|
atan(3, -2), atan(-3, 2), atan(-3/2)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Umwandlung Strings $\Longleftrightarrow$ Zahlen
|
## Conversion Strings $\Longleftrightarrow$ Numbers
|
||||||
|
|
||||||
Die Umwandlung ist mit den Funktionen `parse()` und `string()` möglich.
|
Conversion is possible with the functions `parse()` and `string()`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
parse(Int64, "1101", base=2)
|
parse(Int64, "1101", base=2)
|
||||||
@@ -749,7 +750,7 @@ string(1/7)
|
|||||||
string(77, base=16)
|
string(77, base=16)
|
||||||
```
|
```
|
||||||
|
|
||||||
Zur Umwandlung der numerischen Typen ineinander kann man die Typnamen verwenden. Typenamen sind auch Konstruktoren:
|
For conversion of numerical types into each other, one can use the type names. Type names are also constructors:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -768,7 +769,7 @@ y = Float64(z)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Literatur
|
## Literature
|
||||||
|
|
||||||
- D. Goldberg, [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://www.validlab.com/goldberg/paper.pdf)
|
- D. Goldberg, [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://www.validlab.com/goldberg/paper.pdf)
|
||||||
- C. Vuik, [Some Disasters caused by numerical errors](http://ta.twi.tudelft.nl/users/vuik/wi211/disasters.html)
|
- C. Vuik, [Some Disasters caused by numerical errors](http://ta.twi.tudelft.nl/users/vuik/wi211/disasters.html)
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
engine: julia
|
engine: julia
|
||||||
---
|
---
|
||||||
|
|
||||||
# Ein Fallbeispiel: Der parametrisierte Datentyp PComplex
|
# A Case Study: The Parametric Data Type PComplex
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: false
|
#| error: false
|
||||||
@@ -18,14 +18,14 @@ Base.active_module() = myactive_module()
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Wir wollen als neuen numerischen Typen **komplexe Zahlen in Polardarstellung $z=r e^{i\phi}=(r,ϕ)$** einführen.
|
We want to introduce a new numeric type **complex numbers in polar representation $z=r e^{i\phi}=(r,\phi)$**.
|
||||||
|
|
||||||
- Der Typ soll sich in die Typhierarchie einfügen als Subtyp von 'Number'.
|
- The type should integrate into the type hierarchy as a subtype of 'Number'.
|
||||||
- $r$ und $\phi$ sollen Gleitkommazahlen sein. (Im Unterschied zu komplexen Zahlen in 'kartesischen' Koordinaten hat eine Einschränkung auf ganzzahlige Werte von r oder ϕ mathematisch wenig Sinn.)
|
- $r$ and $\phi$ should be floating point numbers. (Unlike complex numbers in 'Cartesian' coordinates, restricting to integer values of r or $\phi$ makes little mathematical sense.)
|
||||||
|
|
||||||
## Die Definition von `PComplex`
|
## The Definition of `PComplex`
|
||||||
|
|
||||||
Ein erster Versuch könnte so aussehen:
|
A first attempt could look like this:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
struct PComplex1{T <: AbstractFloat} <: Number
|
struct PComplex1{T <: AbstractFloat} <: Number
|
||||||
@@ -40,25 +40,25 @@ z2 = PComplex1{Float32}(12, 13)
|
|||||||
|
|
||||||
:::{.callout-warning collapse="true" .titlenormal}
|
:::{.callout-warning collapse="true" .titlenormal}
|
||||||
##
|
##
|
||||||
Es ist nicht möglich, in einer Julia-Session eine einmal definierte `struct` später umzudefinieren. Daher verwende ich verschiedene Namen. Eine andere Möglichkeit ist z.B. die Verwendung von [`ProtoStructs.jl`](https://juliahub.com/ui/Packages/General/ProtoStructs).
|
It is not possible to redefine a `struct` once it has been defined in a Julia session. Therefore, I use different names. Another possibility is, for example, the use of [`ProtoStructs.jl`](https://juliahub.com/ui/Packages/General/ProtoStructs).
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Julia stellt automatisch *default constructors* zur Verfügung:
|
Julia automatically provides *default constructors*:
|
||||||
|
|
||||||
- den Konstruktor `PComplex1`, bei dem der Typ `T` von den übergebenen Argumenten abgeleitet wird und
|
- the constructor `PComplex1`, where the type `T` is inferred from the passed arguments, and
|
||||||
- Konstruktoren `PComplex{Float64},...` mit expliziter Typangabe. Hier wird versucht, die Argumente in den angeforderten Typ zu konvertieren.
|
- constructors `PComplex{Float64},...` with explicit type specification. Here, the arguments are attempted to be converted to the requested type.
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
Wir wollen nun, dass der Konstruktor noch mehr tut.
|
We now want the constructor to do even more.
|
||||||
In der Polardarstellung soll $0\le r$ und $0\le \phi<2\pi$ gelten.
|
In the polar representation, we want $0\le r$ and $0\le \phi<2\pi$ to hold.
|
||||||
|
|
||||||
Wenn die übergebenen Argumente das nicht erfüllen, sollten sie entsprechend umgerechnet werden.
|
If the passed arguments do not satisfy this, they should be recalculated accordingly.
|
||||||
|
|
||||||
Dazu definieren wir einen _inner constructor_, der den _default constructor_ ersetzt.
|
To this end, we define an _inner constructor_ that replaces the _default constructor_.
|
||||||
|
|
||||||
- Ein _inner constructor_ ist eine Funktion innerhalb der `struct`-Definition.
|
- An _inner constructor_ is a function within the `struct` definition.
|
||||||
- In einem _inner constructor_ kann man die spezielle Funktion `new` verwenden, die wie der _default constructor_ wirkt.
|
- In an _inner constructor_, one can use the special function `new`, which acts like the _default constructor_.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -73,18 +73,17 @@ struct PComplex{T <: AbstractFloat} <: Number
|
|||||||
end
|
end
|
||||||
if r==0 ϕ=0 end # normalize r=0 case to phi=0
|
if r==0 ϕ=0 end # normalize r=0 case to phi=0
|
||||||
ϕ = mod(ϕ, 2π) # map phi into interval [0,2pi)
|
ϕ = mod(ϕ, 2π) # map phi into interval [0,2pi)
|
||||||
new(r, ϕ) # new() ist special function,
|
new(r, ϕ) # new() is special function,
|
||||||
end # available only inside inner constructors
|
end # available only inside inner constructors
|
||||||
|
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| echo: false
|
#| echo: false
|
||||||
#| output: false
|
#| output: false
|
||||||
|
|
||||||
#=
|
#=
|
||||||
in den ganzen quarto-runs wollen wir hier noch das default-show benutzen
|
in the whole quarto-runs we want to use the default show here
|
||||||
=#
|
=#
|
||||||
zz = @which Base.show(stdout, PComplex{Float64}(2.,3.))
|
zz = @which Base.show(stdout, PComplex{Float64}(2.,3.))
|
||||||
if zz.module != Base
|
if zz.module != Base
|
||||||
@@ -94,9 +93,9 @@ end
|
|||||||
```{julia}
|
```{julia}
|
||||||
z1 = PComplex{Float64}(-3.3, 7π+1)
|
z1 = PComplex{Float64}(-3.3, 7π+1)
|
||||||
```
|
```
|
||||||
Für die explizite Angabe eines *inner constructors* müssen wir allerdings einen Preis zahlen: Die sonst von Julia bereitgestellten *default constructors* fehlen.
|
For the explicit specification of an *inner constructor*, we have to pay a price: The *default constructors* provided by Julia are missing.
|
||||||
|
|
||||||
Den Konstruktor, der ohne explizite Typangabe in geschweiften Klammern auskommt und den Typ der Argumente übernimmt, wollen wir gerne auch haben:
|
The constructor without explicit type specification in curly braces, which takes over the type of the arguments, is also desired:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
PComplex(r::T, ϕ::T) where {T<:AbstractFloat} = PComplex{T}(r,ϕ)
|
PComplex(r::T, ϕ::T) where {T<:AbstractFloat} = PComplex{T}(r,ϕ)
|
||||||
@@ -105,43 +104,43 @@ z2 = PComplex(2.0, 0.3)
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Eine neue Schreibweise
|
## A New Notation
|
||||||
|
|
||||||
Julia verwendet `//` als Infix-Konstruktor für den Typ `Rational`. Sowas Schickes wollen wir auch.
|
Julia uses `//` as an infix constructor for the type `Rational`. We want something equally nice.
|
||||||
|
|
||||||
In der Elektronik/Elektrotechnik werden [Wechselstromgrößen durch komplexe Zahlen beschrieben.](https://de.wikipedia.org/wiki/Komplexe_Wechselstromrechnung). Dabei ist eine Darstellung komplexer Zahlen durch "Betrag" und "Phase" üblich und sie wird gerne in der sogenannten [Versor-Form](https://de.wikipedia.org/wiki/Versor) (engl. *phasor*) dargestellt:
|
In electronics/electrical engineering, [AC quantities are described by complex numbers.](https://en.wikipedia.org/wiki/Phasor_analysis) A representation of complex numbers by "magnitude" and "phase" is common and is often represented in so-called [phasor form](https://en.wikipedia.org/wiki/Phasor):
|
||||||
$$
|
$$
|
||||||
z= r\enclose{phasorangle}{\phi} = 3.4\;\enclose{phasorangle}{45^\circ}
|
z= r\enclose{phasorangle}{\phi} = 3.4\;\enclose{phasorangle}{45^\circ}
|
||||||
$$
|
$$
|
||||||
wobei man in der Regel den Winkel in Grad notiert.
|
where the angle is usually noted in degrees.
|
||||||
|
|
||||||
:::{.callout-note .titlenormal collapse="true"}
|
:::{.callout-note .titlenormal collapse="true"}
|
||||||
|
|
||||||
## Mögliche Infix-Operatoren in Julia
|
## Possible Infix Operators in Julia
|
||||||
|
|
||||||
In Julia ist eine große Anzahl von Unicode-Zeichen reserviert für die Verwendung als Operatoren. Die definitive Liste ist im [Quellcode des Parsers.](https://github.com/JuliaLang/julia/blob/eaa2c58aeb12f27c1d8c116ab111773a4fc4495f/src/julia-parser.scm#L13-L31)
|
In Julia, a large number of Unicode characters are reserved for use as operators. The definitive list is in the [parser source code.](https://github.com/JuliaLang/julia/blob/eaa2c58aeb12f27c1d8c116ab111773a4fc4495f/src/julia-parser.scm#L13-L31)
|
||||||
|
|
||||||
Auf Details werden wir in einem späteren Kapitel noch eingehen.
|
Details will be discussed in a later chapter.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Das Winkel-Zeichen `∠` steht leider nicht als Operatorsymbol zur Verfügung. Wir weichen aus auf `⋖`. Das kann in Julia als als `\lessdot<tab>` eingegeben werden.
|
The angle bracket symbol `∠` is not available as an operator symbol. We use `⋖` as an alternative. This can be entered in Julia as `\lessdot<tab>`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
⋖(r::Real, ϕ::Real) = PComplex(r, π*ϕ/180)
|
⋖(r::Real, ϕ::Real) = PComplex(r, π*ϕ/180)
|
||||||
|
|
||||||
z3 = 2. ⋖ 90.
|
z3 = 2. ⋖ 90.
|
||||||
```
|
```
|
||||||
(Die Typ-Annotation -- `Real` statt `AbstractFloat` -- ist ein Vorgriff auf kommende weitere Konstruktoren. Im Moment funktioniert der Operator `⋖` erstmal nur mit `Float`s.)
|
(The type annotation -- `Real` instead of `AbstractFloat` -- is a preview of further constructors to come. For now, the operator `⋖` only works with `Float`s.)
|
||||||
|
|
||||||
|
|
||||||
Natürlich wollen wir auch die Ausgabe so schön haben. Details dazu findet man in der [Dokumentation](https://docs.julialang.org/en/v1/manual/types/#man-custom-pretty-printing).
|
Of course, we also want the output to look nice. Details can be found in the [documentation](https://docs.julialang.org/en/v1/manual/types/#man-custom-pretty-printing).
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
using Printf
|
using Printf
|
||||||
|
|
||||||
function Base.show(io::IO, z::PComplex)
|
function Base.show(io::IO, z::PComplex)
|
||||||
# wir drucken die Phase in Grad, auf Zehntelgrad gerundet,
|
# we print the phase in degrees, rounded to tenths of a degree,
|
||||||
p = z.ϕ * 180/π
|
p = z.ϕ * 180/π
|
||||||
sp = @sprintf "%.1f" p
|
sp = @sprintf "%.1f" p
|
||||||
print(io, z.r, "⋖", sp, '°')
|
print(io, z.r, "⋖", sp, '°')
|
||||||
@@ -151,22 +150,22 @@ end
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Methoden für `PComplex`
|
## Methods for `PComplex`
|
||||||
|
|
||||||
Damit unser Typ ein anständiges Mitglied der von `Number` abstammenden Typfamilie wird, brauchen wir allerdings noch eine ganze Menge mehr. Es müssen Arithmetik, Vergleichsoperatoren, Konvertierungen usw. definiert werden.
|
For our type to be a proper member of the family of types derived from `Number`, we need a whole lot more. Arithmetic, comparison operators, conversions, etc. must be defined.
|
||||||
|
|
||||||
|
|
||||||
Wir beschränken uns auf Multiplikation und Quadratwurzeln.
|
We limit ourselves to multiplication and square roots.
|
||||||
|
|
||||||
|
|
||||||
:::{.callout-note collapse="true"}
|
:::{.callout-note collapse="true"}
|
||||||
## Module
|
## Modules
|
||||||
|
|
||||||
- Um die `methods` der existierenden Funktionen und Operationen zu ergänzen, muss man diese mit ihrem 'vollen Namen' ansprechen.
|
- To add to the `methods` of existing functions and operations, one must address them with their 'full name'.
|
||||||
- Alle Objekte gehören zu einem Namensraum oder `module`.
|
- All objects belong to a namespace or `module`.
|
||||||
- Die meisten Basisfunktionen gehören zum Modul `Base`, welches standardmäßig immer ohne explizites `using ...` geladen wird.
|
- Most basic functions belong to the module `Base`, which is always loaded without explicit `using ...` by default.
|
||||||
- Solange man keine eigenen Module definiert, sind die eigenen Definitionen im Modul `Main`.
|
- As long as one does not define own modules, own definitions are in the module `Main`.
|
||||||
- Das Macro `@which`, angewendet auf einen Namen, zeigt an, in welchem Modul der Name definiert wurde.
|
- The macro `@which`, applied to a name, shows in which module the name is defined.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
f(x) = 3x^3
|
f(x) = 3x^3
|
||||||
@@ -176,7 +175,7 @@ f(x) = 3x^3
|
|||||||
```{julia}
|
```{julia}
|
||||||
wp = @which +
|
wp = @which +
|
||||||
ws = @which(sqrt)
|
ws = @which(sqrt)
|
||||||
println("Modul für Addition: $wp, Modul für sqrt: $ws")
|
println("Module for addition: $wp, Module for sqrt: $ws")
|
||||||
```
|
```
|
||||||
|
|
||||||
:::
|
:::
|
||||||
@@ -190,7 +189,7 @@ qwurzel(z::PComplex) = PComplex(sqrt(z.r), z.ϕ / 2)
|
|||||||
#| output: false
|
#| output: false
|
||||||
|
|
||||||
#=
|
#=
|
||||||
damit das length(methods(sqrt)) klappt
|
to make length(methods(sqrt)) work
|
||||||
=#
|
=#
|
||||||
if hasmethod(sqrt, (PComplex,))
|
if hasmethod(sqrt, (PComplex,))
|
||||||
zz = @which Base.sqrt(PComplex{Float64}(1.,1.))
|
zz = @which Base.sqrt(PComplex{Float64}(1.,1.))
|
||||||
@@ -198,12 +197,12 @@ if hasmethod(sqrt, (PComplex,))
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Die Funktion `sqrt()` hat schon einige Methoden:
|
The function `sqrt()` already has some methods:
|
||||||
```{julia}
|
```{julia}
|
||||||
length(methods(sqrt))
|
length(methods(sqrt))
|
||||||
```
|
```
|
||||||
|
|
||||||
Jetzt wird es eine Methode mehr:
|
Now it will have one more method:
|
||||||
```{julia}
|
```{julia}
|
||||||
Base.sqrt(z::PComplex) = qwurzel(z)
|
Base.sqrt(z::PComplex) = qwurzel(z)
|
||||||
|
|
||||||
@@ -214,26 +213,26 @@ length(methods(sqrt))
|
|||||||
sqrt(z2)
|
sqrt(z2)
|
||||||
```
|
```
|
||||||
|
|
||||||
und nun zur Multiplikation:
|
and now for multiplication:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
Base.:*(x::PComplex, y::PComplex) = PComplex(x.r * y.r, x.ϕ + y.ϕ)
|
Base.:*(x::PComplex, y::PComplex) = PComplex(x.r * y.r, x.ϕ + y.ϕ)
|
||||||
|
|
||||||
@show z1 * z2;
|
@show z1 * z2;
|
||||||
```
|
```
|
||||||
(Da das Operatorsymbol kein normaler Name ist, muss der Doppelpunkt bei der Zusammensetzung mit `Base.` sein.)
|
(Since the operator symbol is not a normal name, the colon must be with `Base.` in the composition.)
|
||||||
|
|
||||||
Wir können allerdings noch nicht mit anderen numerischen Typen multiplizieren. Dazu könnte man nun eine Vielzahl von entsprechenden Methoden definieren. Julia stellt *für numerische Typen* noch einen weiteren Mechanismus zur Verfügung, der das etwas vereinfacht.
|
We can, however, not yet multiply with other numeric types. One could now define a large number of corresponding methods. Julia provides one more mechanism for *numeric types* that simplifies this somewhat.
|
||||||
|
|
||||||
|
|
||||||
## Typ-Promotion und Konversion
|
## Type Promotion and Conversion
|
||||||
|
|
||||||
In Julia kann man bekanntlich die verschiedensten numerischen Typen nebeneinander verwenden.
|
In Julia, one can naturally use the most diverse numeric types side by side.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
1//3 + 5 + 5.2 + 0xff
|
1//3 + 5 + 5.2 + 0xff
|
||||||
```
|
```
|
||||||
Wenn man in die zahlreichen Methoden schaut, die z.B. für `+` und `*` definiert sind, findet man u.a. eine Art 'catch-all-Definition'
|
If one looks at the numerous methods defined, for example, for `+` and `*`, one finds among them a kind of 'catch-all definition'
|
||||||
|
|
||||||
```julia
|
```julia
|
||||||
+(x::Number, y::Number) = +(promote(x,y)...)
|
+(x::Number, y::Number) = +(promote(x,y)...)
|
||||||
@@ -242,15 +241,15 @@ Wenn man in die zahlreichen Methoden schaut, die z.B. für `+` und `*` definiert
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
(Die 3 Punkte sind der splat-Operator, der das von promote() zurückgegebene Tupel wieder in seine Bestandteile zerlegt.)
|
(The 3 dots are the splat operator, which decomposes the tuple returned by promote() back into its components.)
|
||||||
|
|
||||||
Da die Methode mit den Typen `(Number, Number)` sehr allgemein ist, wird sie erst verwendet, wenn spezifischere Methoden nicht greifen.
|
Since the method with the types `(Number, Number)` is very general, it is only used when more specific methods do not apply.
|
||||||
|
|
||||||
Was passiert hier?
|
What happens here?
|
||||||
|
|
||||||
### Die Funktion `promote(x,y,...)`
|
### The Function `promote(x,y,...)`
|
||||||
|
|
||||||
Diese Funktion versucht, alle Argumente in einen gemeinsamen Typen umzuwandeln, der alle Werte (möglichst) exakt darstellen kann.
|
This function attempts to convert all arguments to a common type that can represent all values (as precisely as possible).
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
promote(12, 34.555, 77/99, 0xff)
|
promote(12, 34.555, 77/99, 0xff)
|
||||||
@@ -261,15 +260,15 @@ z = promote(BigInt(33), 27)
|
|||||||
@show z typeof(z);
|
@show z typeof(z);
|
||||||
```
|
```
|
||||||
|
|
||||||
Die Funktion `promote()` verwendet dazu zwei Helfer, die Funktionen
|
The function `promote()` uses two helpers, the functions
|
||||||
`promote_type(T1, T2)` und `convert(T, x)`
|
`promote_type(T1, T2)` and `convert(T, x)`
|
||||||
|
|
||||||
Wie üblich in Julia, kann man diesen Mechanismus durch [eigene *promotion rules* und `convert(T,x)`-Methoden erweitern.](https://docs.julialang.org/en/v1/manual/conversion-and-promotion/)
|
As usual in Julia, one can extend this mechanism with [custom *promotion rules* and `convert(T,x)` methods.](https://docs.julialang.org/en/v1/manual/conversion-and-promotion/)
|
||||||
|
|
||||||
|
|
||||||
### Die Funktion `promote_type(T1, T2,...)`
|
### The Function `promote_type(T1, T2,...)`
|
||||||
|
|
||||||
Sie ermittelt, zu welchem Typ umgewandelt werden soll. Argumente sind Typen, nicht Werte.
|
It determines to which type conversion should take place. Arguments are types, not values.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show promote_type(Rational{Int64}, ComplexF64, Float32);
|
@show promote_type(Rational{Int64}, ComplexF64, Float32);
|
||||||
@@ -277,10 +276,10 @@ Sie ermittelt, zu welchem Typ umgewandelt werden soll. Argumente sind Typen, nic
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Die Funktion `convert(T,x)`
|
### The Function `convert(T,x)`
|
||||||
|
|
||||||
Die Methoden von
|
The methods of
|
||||||
`convert(T, x)` wandeln `x` in ein Objekt vom Typ `T` um. Dabei sollte eine solche Umwandlung verlustfrei möglich sein.
|
`convert(T, x)` convert `x` into an object of type `T`. Such a conversion should be lossless.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
z = convert(Float64, 3)
|
z = convert(Float64, 3)
|
||||||
@@ -294,7 +293,7 @@ z = convert(Int64, 23.00)
|
|||||||
z = convert(Int64, 2.3)
|
z = convert(Int64, 2.3)
|
||||||
```
|
```
|
||||||
|
|
||||||
Die spezielle Rolle von `convert()` liegt darin, dass es an verschiedenen Stellen _implizit_ und automatisch eingesetzt wird:
|
The special role of `convert()` lies in the fact that it is used *implicitly* and automatically at various points:
|
||||||
|
|
||||||
> [The following language constructs call convert](https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#When-is-convert-called?):
|
> [The following language constructs call convert](https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#When-is-convert-called?):
|
||||||
>
|
>
|
||||||
@@ -304,24 +303,24 @@ Die spezielle Rolle von `convert()` liegt darin, dass es an verschiedenen Stelle
|
|||||||
- Assigning to a variable with a declared type (e.g. local x::T) converts to that type.
|
- Assigning to a variable with a declared type (e.g. local x::T) converts to that type.
|
||||||
- A function with a declared return type converts its return value to that type.
|
- A function with a declared return type converts its return value to that type.
|
||||||
|
|
||||||
-- und natürlich in `promote()`
|
-- and of course in `promote()`
|
||||||
|
|
||||||
Für selbstdefinierte Datentypen kann man convert() um weitere Methoden ergänzen.
|
For self-defined data types, one can extend convert() with further methods.
|
||||||
|
|
||||||
Für Datentypen innerhalb der Number-Hierarchie gibt es wieder eine 'catch-all-Definition'
|
For data types within the Number hierarchy, there is again a 'catch-all definition'
|
||||||
```julia
|
```julia
|
||||||
convert(::Type{T}, x::Number) where {T<:Number} = T(x)
|
convert(::Type{T}, x::Number) where {T<:Number} = T(x)
|
||||||
```
|
```
|
||||||
|
|
||||||
Also: Wenn für einen Typen `T` aus der Hierarchie `T<:Number` ein Konstruktor `T(x)` mit einem numerischen Argument `x` existiert, dann wird dieser Konstruktor `T(x)` automatisch für Konvertierungen benutzt. (Natürlich können auch speziellere Methoden für `convert()` definiert werden, die dann Vorrang haben.)
|
So: If for a type `T` from the hierarchy `T<:Number` there exists a constructor `T(x)` with a numeric argument `x`, then this constructor `T(x)` is automatically used for conversions. (Of course, more specific methods for `convert()` can also be defined, which then have priority.)
|
||||||
|
|
||||||
|
|
||||||
### Weitere Konstruktoren für `PComplex`
|
### Further Constructors for `PComplex`
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
|
|
||||||
## (a) r, ϕ beliebige Reals, z.B. Integers, Rationals
|
## (a) r, ϕ arbitrary reals, e.g. Integers, Rationals
|
||||||
|
|
||||||
PComplex{T}(r::T1, ϕ::T2) where {T<:AbstractFloat, T1<:Real, T2<: Real} =
|
PComplex{T}(r::T1, ϕ::T2) where {T<:AbstractFloat, T1<:Real, T2<: Real} =
|
||||||
PComplex{T}(convert(T, r), convert(T, ϕ))
|
PComplex{T}(convert(T, r), convert(T, ϕ))
|
||||||
@@ -329,8 +328,8 @@ PComplex{T}(r::T1, ϕ::T2) where {T<:AbstractFloat, T1<:Real, T2<: Real} =
|
|||||||
PComplex(r::T1, ϕ::T2) where {T1<:Real, T2<: Real} =
|
PComplex(r::T1, ϕ::T2) where {T1<:Real, T2<: Real} =
|
||||||
PComplex{promote_type(Float64, T1, T2)}(r, ϕ)
|
PComplex{promote_type(Float64, T1, T2)}(r, ϕ)
|
||||||
|
|
||||||
## (b) Zur Umwandlung von Reals: Konstruktor mit
|
## (b) For conversion from reals: constructor with
|
||||||
## nur einem Argument r
|
## only one argument r
|
||||||
|
|
||||||
PComplex{T}(r::S) where {T<:AbstractFloat, S<:Real} =
|
PComplex{T}(r::S) where {T<:AbstractFloat, S<:Real} =
|
||||||
PComplex{T}(convert(T, r), convert(T, 0))
|
PComplex{T}(convert(T, r), convert(T, 0))
|
||||||
@@ -338,7 +337,7 @@ PComplex{T}(r::S) where {T<:AbstractFloat, S<:Real} =
|
|||||||
PComplex(r::S) where {S<:Real} =
|
PComplex(r::S) where {S<:Real} =
|
||||||
PComplex{promote_type(Float64, S)}(r, 0.0)
|
PComplex{promote_type(Float64, S)}(r, 0.0)
|
||||||
|
|
||||||
## (c) Umwandlung Complex -> PComplex
|
## (c) Conversion Complex -> PComplex
|
||||||
|
|
||||||
PComplex{T}(z::Complex{S}) where {T<:AbstractFloat, S<:Real} =
|
PComplex{T}(z::Complex{S}) where {T<:AbstractFloat, S<:Real} =
|
||||||
PComplex{T}(abs(z), angle(z))
|
PComplex{T}(abs(z), angle(z))
|
||||||
@@ -349,8 +348,7 @@ PComplex(z::Complex{S}) where {S<:Real} =
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
A test of the new constructors:
|
||||||
Ein Test der neuen Konstruktoren:
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
|
|
||||||
@@ -359,9 +357,9 @@ Ein Test der neuen Konstruktoren:
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Wir brauchen nun noch *promotion rules*, die festlegen, welcher Typ bei `promote(x::T1, y::T2)` herauskommen soll. Damit wird `promote_type()` intern um die nötigen weiteren Methoden erweitert.
|
We now still need *promotion rules* that determine which type should result from `promote(x::T1, y::T2)`. This internally extends `promote_type()` with the necessary further methods.
|
||||||
|
|
||||||
### *Promotion rules* für `PComplex`
|
### *Promotion rules* for `PComplex`
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -371,15 +369,16 @@ Base.promote_rule(::Type{PComplex{T}}, ::Type{S}) where {T<:AbstractFloat,S<:Rea
|
|||||||
Base.promote_rule(::Type{PComplex{T}}, ::Type{Complex{S}}) where
|
Base.promote_rule(::Type{PComplex{T}}, ::Type{Complex{S}}) where
|
||||||
{T<:AbstractFloat,S<:Real} = PComplex{promote_type(T,S)}
|
{T<:AbstractFloat,S<:Real} = PComplex{promote_type(T,S)}
|
||||||
```
|
```
|
||||||
1. Regel:
|
1. Rule:
|
||||||
: Wenn ein `PComplex{T}` und ein `S<:Real` zusammentreffen, dann sollen beide zu `PComplex{U}` umgewandelt werden, wobei `U` der Typ ist, zu dem `S` und `T` beide umgewandelt (_promoted_) werden können.
|
: If a `PComplex{T}` and an `S<:Real` meet, then both should be converted to `PComplex{U}`, where `U` is the type to which `S` and `T` can both be converted (_promoted_).
|
||||||
|
|
||||||
2. Regel
|
2. Rule
|
||||||
: Wenn ein `PComplex{T}` und ein `Complex{S}` zusammentreffen, dann sollen beide zu `PComplex{U}` umgewandelt werden, wobei `U` der Typ ist, zu dem `S` und `T` beide umgewandelt werden können.
|
: If a `PComplex{T}` and a `Complex{S}` meet, then both should be converted to `PComplex{U}`, where `U` is the type to which `S` and `T` can be converted.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Damit klappt nun die Multiplikation mit beliebigen numerischen Typen.
|
|
||||||
|
Now multiplication with arbitrary numeric types works.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
z3, 3z3
|
z3, 3z3
|
||||||
@@ -391,9 +390,10 @@ z3, 3z3
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
||||||
|
|
||||||
## Zusammenfassung: unser Typ `PComplex`
|
## Summary: our type `PComplex`
|
||||||
|
|
||||||
```julia
|
```julia
|
||||||
struct PComplex{T <: AbstractFloat} <: Number
|
struct PComplex{T <: AbstractFloat} <: Number
|
||||||
@@ -407,7 +407,7 @@ struct PComplex{T <: AbstractFloat} <: Number
|
|||||||
end
|
end
|
||||||
if r==0 ϕ=0 end # normalize r=0 case to phi=0
|
if r==0 ϕ=0 end # normalize r=0 case to phi=0
|
||||||
ϕ = mod(ϕ, 2π) # map phi into interval [0,2pi)
|
ϕ = mod(ϕ, 2π) # map phi into interval [0,2pi)
|
||||||
new(r, ϕ) # new() ist special function,
|
new(r, ϕ) # new() is special function,
|
||||||
end # available only inside inner constructors
|
end # available only inside inner constructors
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -443,7 +443,7 @@ PComplex(z::Complex{S}) where {S<:Real} =
|
|||||||
using Printf
|
using Printf
|
||||||
|
|
||||||
function Base.show(io::IO, z::PComplex)
|
function Base.show(io::IO, z::PComplex)
|
||||||
# wir drucken die Phase in Grad, auf Zehntelgrad gerundet,
|
# we print the phase in degrees, rounded to tenths of a degree,
|
||||||
p = z.ϕ * 180/π
|
p = z.ϕ * 180/π
|
||||||
sp = @sprintf "%.1f" p
|
sp = @sprintf "%.1f" p
|
||||||
print(io, z.r, "⋖", sp, '°')
|
print(io, z.r, "⋖", sp, '°')
|
||||||
@@ -465,7 +465,7 @@ Base.promote_rule(::Type{PComplex{T}}, ::Type{Complex{S}}) where
|
|||||||
|
|
||||||
:::{.content-hidden unless-format="xxx"}
|
:::{.content-hidden unless-format="xxx"}
|
||||||
|
|
||||||
Jetzt geht sowas wie `PComplex(1, 0)` noch nicht. Wir wollen auch andere reelle Typen für `r` und `ϕ` zulassen. Der Einfachheit halber wandeln wir hier alles nach `Float64` um. Analog verfahren wir auch, wenn nur ein reelles oder komplexes Argument verwendet wird.
|
Now something like `PComplex(1, 0)` does not work yet. We also want to allow other real types for `r` and `ϕ`. For simplicity, we convert everything to `Float64` here. We proceed analogously if only one real or complex argument is used.
|
||||||
|
|
||||||
```julia
|
```julia
|
||||||
PComplex(r::Real, ϕ::Real) = PComplex(Float64(r), Float64(ϕ))
|
PComplex(r::Real, ϕ::Real) = PComplex(Float64(r), Float64(ϕ))
|
||||||
|
|||||||
@@ -9,67 +9,67 @@ engine: julia
|
|||||||
using InteractiveUtils
|
using InteractiveUtils
|
||||||
```
|
```
|
||||||
|
|
||||||
# Grundlagen der Syntax
|
# Fundamentals of Syntax
|
||||||
|
|
||||||
## Namen von Variablen, Funktionen, Typen etc.
|
## Names of Variables, Functions, Types, etc.
|
||||||
|
|
||||||
- Namen können Buchstaben, Ziffern, den Unterstrich `_` und das Ausrufezeichen `!` enthalten.
|
- Names may contain letters, digits, underscores `_`, and exclamation marks `!`.
|
||||||
- Das erste Zeichen muss ein Buchstabe oder ein Unterstrich sein.
|
- The first character must be a letter or an underscore.
|
||||||
- Groß- und Kleinbuchstaben werden unterschieden: `Nmax` und `NMAX` sind verschiedene Variablen.
|
- Case is significant: `Nmax` and `NMAX` are different variables.
|
||||||
- Als Zeichensatz wird [Unicode](https://home.unicode.org/) verwendet. Damit stehen über 150 Schriften und zahlreiche Symbole zur Verfügung.
|
- The character set used is [Unicode](https://home.unicode.org/). This provides access to over 150 scripts and numerous symbols.
|
||||||
- Es gibt eine kurze [Liste reservierter Schlüsselwörter](https://docs.julialang.org/en/v1/base/base/#Keywords): `if, then, function, true, false,...`
|
- There is a short [list of reserved keywords](https://docs.julialang.org/en/v1/base/base/#Keywords): `if, then, function, true, false,...`
|
||||||
|
|
||||||
:::{.callout-tip}
|
:::{.callout-tip}
|
||||||
## Beispiel
|
## Example
|
||||||
|
|
||||||
zulässig: `i, x, Ω, x2, DieUnbekannteZahl, neuer_Wert, 🎷, Zähler, лічильник, einself!!!!,...`
|
permissible: `i, x, Ω, x2, DieUnbekannteZahl, neuer_Wert, 🎷, Zähler, лічильник, einself!!!!,...`
|
||||||
|
|
||||||
unzulässig: `Uwe's_Funktion, 3achsen, A#B, $this_is_not_Perl, true,...`
|
impermissible: `Uwe's_Funktion, 3achsen, A#B, $this_is_not_Perl, true,...`
|
||||||
:::
|
:::
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
:::{.callout-note }
|
:::{.callout-note }
|
||||||
## Anmerkung
|
## Note
|
||||||
|
|
||||||
Neben den *reserved keywords* der Kernsprache sind zahlreiche weitere Funktionen und Objekte vordefiniert, wie z.B. die mathematischen Funktionen `sqrt(), log(), sin()`.
|
In addition to the *reserved keywords* of the core language, numerous additional functions and objects are predefined, such as the mathematical functions `sqrt(), log(), sin()`.
|
||||||
Diese Definitionen finden sich in dem Modul `Base`, welches Julia beim Start automatisch lädt.
|
These definitions are found in the module `Base`, which Julia loads automatically at startup.
|
||||||
Namen aus `Base` können umdefiniert werden, solange sie noch nicht verwendet wurden:
|
Names from `Base` can be redefined as long as they have not yet been used:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: true
|
#| error: true
|
||||||
log = 3
|
log = 3
|
||||||
1 + log
|
1 + log
|
||||||
```
|
```
|
||||||
Jetzt ist natürlich der Logarithmus kaputt:
|
Now of course the logarithm is broken:
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: true
|
#| error: true
|
||||||
x = log(10)
|
x = log(10)
|
||||||
```
|
```
|
||||||
(siehe auch <https://stackoverflow.com/questions/65902105/how-to-reset-any-function-in-julia-to-its-original-state>)
|
(see also <https://stackoverflow.com/questions/65902105/how-to-reset-any-function-in-julia-to-its-original-state>)
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Anweisungen
|
## Statements
|
||||||
|
|
||||||
- Im Normalfall enthält eine Zeile eine Anweisung.
|
- In normal circumstances, each line contains one statement.
|
||||||
- Wenn eine Anweisung am Zeilenende als unvollständig erkennbar ist durch
|
- If a statement is recognizable as incomplete at the end of a line through
|
||||||
- offene Klammern
|
- open parentheses
|
||||||
- Operationszeichen,
|
- operators,
|
||||||
|
|
||||||
dann wird die nächste Zeile als Fortsetzung aufgefasst.
|
then the next line is regarded as a continuation.
|
||||||
- Mehrere Anweisungen pro Zeile können durch Semikolon getrennt werden.
|
- Multiple statements per line can be separated by semicolons.
|
||||||
- Im interaktiven Betrieb (REPL oder Notebook) unterdrückt ein Semikolon nach der letzten Anweisung die Ausgabe des Ergebnisses dieser Anweisung.
|
- In interactive mode (REPL or notebook), a semicolon after the last statement suppresses the output of the result of that statement.
|
||||||
|
|
||||||
:::{.callout-tip}
|
:::{.callout-tip}
|
||||||
|
|
||||||
## Beispiel
|
## Example
|
||||||
|
|
||||||
Im interaktiven Betrieb wird der Wert der letzten Anweisung auch ohne explizites `print()` ausgegeben:
|
In interactive mode, the value of the last statement is also displayed without explicit `print()`:
|
||||||
```{julia}
|
```{julia}
|
||||||
println("Hallo 🌍!")
|
println("Hallo 🌍!")
|
||||||
x = sum([i^2 for i=1:10])
|
x = sum([i^2 for i=1:10])
|
||||||
```
|
```
|
||||||
Das Semikolon unterdrückt das:
|
The semicolon suppresses this:
|
||||||
```{julia}
|
```{julia}
|
||||||
println("Hallo 🌍!")
|
println("Hallo 🌍!")
|
||||||
x = sum([i^2 for i=1:10]);
|
x = sum([i^2 for i=1:10]);
|
||||||
@@ -81,14 +81,14 @@ x = sum([i^2 for i=1:10]);
|
|||||||
|
|
||||||
:::{.callout-warning }
|
:::{.callout-warning }
|
||||||
|
|
||||||
Bei mehrzeiligen Anweisungen muss die fortzusetzende Zeile mit einer offenen Operation oder Klammer enden:
|
For multi-line statements, the line to be continued must end with an open operation or parenthesis:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = sin(π/2) +
|
x = sin(π/2) +
|
||||||
3 * cos(0)
|
3 * cos(0)
|
||||||
```
|
```
|
||||||
|
|
||||||
Also geht das Folgende schief, aber leider **ohne eine Fehlermeldung**!
|
Therefore, the following goes wrong, but unfortunately **without an error message**!
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: true
|
#| error: true
|
||||||
#| warning: true
|
#| warning: true
|
||||||
@@ -96,9 +96,9 @@ x = sin(π/2)
|
|||||||
+ 3 * cos(0)
|
+ 3 * cos(0)
|
||||||
println(x)
|
println(x)
|
||||||
```
|
```
|
||||||
Hier wird das `+` in der zweiten Zeile als Präfix-Operator (Vorzeichen) interpretiert. Damit sind 1. und 2. Zeile jeweils für sich vollständige, korrekte Ausdrücke (auch wenn die 2. Zeile natürlich völlig nutzlos ist) und werden auch so abgearbeitet.
|
Here, the `+` in the second line is interpreted as a prefix operator (sign). Thus, lines 1 and 2 are each complete, correct expressions on their own (even though line 2 is of course completely useless) and are processed as such.
|
||||||
|
|
||||||
Moral: Wenn man längere Ausdrücke auf mehrere Zeilen aufteilen will, sollte man immer eine Klammer aufmachen. Dann ist egal, wo der Zeilenumbruch ist:
|
Moral: If you want to split longer expressions across multiple lines, you should always open a parenthesis. Then it doesn't matter where the line break occurs:
|
||||||
```{julia}
|
```{julia}
|
||||||
x = ( sin(π/2)
|
x = ( sin(π/2)
|
||||||
+ 3 * cos(0) )
|
+ 3 * cos(0) )
|
||||||
@@ -107,26 +107,26 @@ println(x)
|
|||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
## Kommentare
|
## Comments
|
||||||
|
|
||||||
Julia kennt 2 Arten von Kommentaren im Programmtext:
|
Julia knows two types of comments in program text:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
# Einzeilige Kommentare beginnen mit einem Doppelkreuz.
|
# Single-line comments begin with a hash symbol.
|
||||||
|
|
||||||
x = 2 # alles vom '#' bis zum Zeilenende ist ein Kommentar und wird ignoriert. x = 3
|
x = 2 # everything from '#' to the end of the line is a comment and is ignored. x = 3
|
||||||
```
|
```
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#=
|
#=
|
||||||
Ein- und mehrzeilige Kommentare können zwischen #= ... =# eingeschlossen werden.
|
Single and multi-line comments can be enclosed between #= ... =#.
|
||||||
Dabei sind verschachtelte Kommentare möglich.
|
Nested comments are possible.
|
||||||
#=
|
#=
|
||||||
d.h., anders als in C/C++/Java endet der Kommentar nicht mit dem ersten
|
i.e., unlike in C/C++/Java, the comment does not end with the first
|
||||||
Kommentar-Endezeichen, sondern die #=...=# - Paare wirken wie Klammern.
|
comment-end character, but the #=...=# pairs act like parentheses.
|
||||||
=#
|
=#
|
||||||
Der automatische 'syntax highlighter' weiss das leider noch nicht, wie die wechselnde
|
The automatic 'syntax highlighter' does not yet know this, as the alternating
|
||||||
Graufärbung dieses Kommentars zeigt.
|
gray shading of this comment shows.
|
||||||
=#
|
=#
|
||||||
|
|
||||||
|
|
||||||
@@ -134,16 +134,16 @@ x #= das ist ein seltener Variablenname! =# = 3
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Datentypen Teil I
|
## Data Types Part I
|
||||||
|
|
||||||
- Julia ist eine [stark typisierte](https://de.wikipedia.org/wiki/Starke_Typisierung) Sprache. Alle Objekte haben einen Typ. Funktionen/Operationen erwarten Argumente mit dem richtigen Typ.
|
- Julia is a [strongly typed](https://de.wikipedia.org/wiki/Starke_Typisierung) language. All objects have a type. Functions/operations expect arguments of the correct type.
|
||||||
- Julia ist eine [dynamisch typisierte](https://de.wikipedia.org/wiki/Dynamische_Typisierung) Sprache. Variablen haben keinen Typ. Sie sind Namen, die durch Zuweisung `x = ...` an Objekte gebunden werden können.
|
- Julia is a [dynamically typed](https://de.wikipedia.org/wiki/Dynamische_Typisierung) language. Variables have no type. They are names that can be bound to objects via assignment `x = ...`.
|
||||||
- Wenn man vom „Typ einer Variablen“ spricht, meint man den Typ des Objektes, das der Variablen gerade zugewiesen ist.
|
- When speaking of the "type of a variable", one means the type of the object currently assigned to the variable.
|
||||||
- Funktionen/Operatoren können verschiedene *methods* für verschiedene Argumenttypen implementieren.
|
- Functions/operators can implement different *methods* for different argument types.
|
||||||
- Abhängig von den konkreten Argumenttypen wird dann bei Verwendung einer Funktion entschieden, welche Methode benutzt wird ([*dynamic dispatch*](https://en.wikipedia.org/wiki/Dynamic_dispatch)).
|
- Depending on the concrete argument types, it is decided at function usage which method is used ([*dynamic dispatch*](https://en.wikipedia.org/wiki/Dynamic_dispatch)).
|
||||||
|
|
||||||
|
|
||||||
Einfache Basistypen sind z.B.:
|
Simple basic types are, for example:
|
||||||
|
|
||||||
```
|
```
|
||||||
Int64, Float64, String, Char, Bool
|
Int64, Float64, String, Char, Bool
|
||||||
@@ -176,41 +176,41 @@ x = 3 > π
|
|||||||
x, typeof(x), sizeof(x)
|
x, typeof(x), sizeof(x)
|
||||||
```
|
```
|
||||||
|
|
||||||
- `sizeof()` liefert die Größe eines Objekts oder Typs in Bytes (1 Byte = 8 Bit)
|
- `sizeof()` returns the size of an object or type in bytes (1 byte = 8 bits)
|
||||||
- 64bit Ganzzahlen und 64bit Gleitkommazahlen entsprechen dem Befehlssatz moderner Prozessoren und sind daher die numerischen Standardtypen.
|
- 64-bit integers and 64-bit floating-point numbers correspond to the instruction set of modern processors and are therefore the standard numeric types.
|
||||||
- Zeichen/*chars* `'A'` und Zeichenketten/*strings* `"A"` der Länge 1 sind verschiedene Objekte.
|
- Characters/*chars* `'A'` and strings/*strings* `"A"` of length 1 are different objects.
|
||||||
|
|
||||||
## Ablaufsteuerung
|
## Control Flow
|
||||||
|
|
||||||
### `if`-Blöcke
|
### `if` Blocks
|
||||||
|
|
||||||
- Ein `if`-Block *kann* **beliebig viele** `elseif`-Zweige und als letztes maximal **einen** `else`-Zweig enthalten.
|
- An `if` block *can* contain **any number** of `elseif` branches and at the end at most **one** `else` branch.
|
||||||
- Der Block hat einen Wert, den Wert der letzten ausgeführten Anweisung.
|
- The block has a value, the value of the last executed statement.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 33
|
x = 33
|
||||||
y = 44
|
y = 44
|
||||||
z = 34
|
z = 34
|
||||||
|
|
||||||
if x < y && z != x # elseif- und else-Blöcke sind optional
|
if x < y && z != x # elseif- and else-branches are optional
|
||||||
println("yes")
|
println("yes")
|
||||||
x += 10
|
x += 10
|
||||||
elseif x < z # beliebig viele elseif-Blöcke
|
elseif x < z # any number of elseif branches
|
||||||
println(" x is smaller than z")
|
println(" x is smaller than z")
|
||||||
elseif x == z+1
|
elseif x == z+1
|
||||||
println(" x is successor of z")
|
println(" x is successor of z")
|
||||||
else # maximal ein else-Block
|
else # at most one else block
|
||||||
println("Alles falsch")
|
println("Alles falsch")
|
||||||
end # Wert des gesamten Blocks ist der Wert der
|
end # value of the entire block is the value of the
|
||||||
# letzten ausgeführten Auswertung
|
# last evaluated statement
|
||||||
```
|
```
|
||||||
|
|
||||||
Kurze Blöcke kann man in eine Zeile schreiben:
|
Short blocks can be written in one line:
|
||||||
```{julia}
|
```{julia}
|
||||||
if x > 10 println("x is larger than 10") end
|
if x > 10 println("x is larger than 10") end
|
||||||
```
|
```
|
||||||
|
|
||||||
Der Wert eines `if`-Blocks kann natürlich zugewiesen werden:
|
The value of an `if` block can of course be assigned:
|
||||||
```{julia}
|
```{julia}
|
||||||
y = 33
|
y = 33
|
||||||
z = if y > 10
|
z = if y > 10
|
||||||
@@ -220,14 +220,14 @@ z = if y > 10
|
|||||||
z
|
z
|
||||||
```
|
```
|
||||||
|
|
||||||
### Auswahloperator (ternary operator) `test ? exp1 : exp2`
|
### Conditional Operator (ternary operator) `test ? exp1 : exp2`
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 20
|
x = 20
|
||||||
y = 15
|
y = 15
|
||||||
z = x < y ? x+1 : y+1
|
z = x < y ? x+1 : y+1
|
||||||
```
|
```
|
||||||
ist äquivalent zu
|
is equivalent to
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
z = if x < y
|
z = if x < y
|
||||||
@@ -237,9 +237,9 @@ z = if x < y
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
## Vergleiche, Tests, Logische Operationen
|
## Comparisons, Tests, Logical Operations
|
||||||
|
|
||||||
### Arithmetische Vergleiche
|
### Arithmetic Comparisons
|
||||||
|
|
||||||
- `==`
|
- `==`
|
||||||
- `!=`, `≠`
|
- `!=`, `≠`
|
||||||
@@ -248,56 +248,56 @@ z = if x < y
|
|||||||
- `<`
|
- `<`
|
||||||
- `<=`, `≤`
|
- `<=`, `≤`
|
||||||
|
|
||||||
Wie üblich, ist der Test auf Gleichheit `==` vom Zuweisungsoperator `=` zu unterscheiden. Vergleichen lässt sich so gut wie alles:
|
As usual, the equality test `==` is to be distinguished from the assignment operator `=`. Almost anything can be compared:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
"Aachen" < "Leipzig", 10 ≤ 10.01, [3,4,5] < [3,6,2]
|
"Aachen" < "Leipzig", 10 ≤ 10.01, [3,4,5] < [3,6,2]
|
||||||
```
|
```
|
||||||
|
|
||||||
Nun ja, fast alles:
|
Well, almost anything:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
3 < "vier"
|
3 < "vier"
|
||||||
```
|
```
|
||||||
|
|
||||||
Die Fehlermeldung zeigt ein paar Grundprinzipien von Julia:
|
The error message shows a few fundamental principles of Julia:
|
||||||
|
|
||||||
- Operatoren sind auch nur Funktionen: `x < y` wird zum Funktionsaufruf `isless(x, y)`.
|
- Operators are also just functions: `x < y` becomes the function call `isless(x, y)`.
|
||||||
- Funktionen (und damit Operatoren) können verschiedene *methods* für verschiedene Argumenttypen implementieren.
|
- Functions (and thus operators) can implement different *methods* for different argument types.
|
||||||
- Abhängig von den konkreten Argumenttypen wird beim Aufruf der Funktion entschieden, welche Methode benutzt wird ([*dynamic dispatch*](https://en.wikipedia.org/wiki/Dynamic_dispatch)).
|
- Depending on the concrete argument types, it is decided at function call which method is used ([*dynamic dispatch*](https://en.wikipedia.org/wiki/Dynamic_dispatch)).
|
||||||
|
|
||||||
Man kann sich alle Methoden zu einer Funktion anzeigen lassen. Das gibt einen Einblick in das komplexe Typssystem von Julia:
|
One can display all methods for a function. This provides insight into Julia's complex type system:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
methods(<)
|
methods(<)
|
||||||
```
|
```
|
||||||
|
|
||||||
Zuletzt noch: Vergleiche können gekettet werden.
|
Finally: comparisons can be chained.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
10 < x ≤ 100 # das ist äquivalent zu
|
10 < x ≤ 100 # this is equivalent to
|
||||||
# 10 < x && x ≤ 100
|
# 10 < x && x ≤ 100
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Tests
|
### Tests
|
||||||
Einge Funktionen vom Typ `f(c::Char) -> Bool`
|
Some functions of type `f(c::Char) -> Bool`
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
isnumeric('a'), isnumeric('7'), isletter('a')
|
isnumeric('a'), isnumeric('7'), isletter('a')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
und vom Typ `f(s1::String, s2::String) -> Bool`
|
and of type `f(s1::String, s2::String) -> Bool`
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
contains("Lampenschirm", "pensch"), startswith("Lampenschirm", "Lamb"), endswith("Lampenschirm", "rm")
|
contains("Lampenschirm", "pensch"), startswith("Lampenschirm", "Lamb"), endswith("Lampenschirm", "rm")
|
||||||
```
|
```
|
||||||
|
|
||||||
- Die Funktion `in(item, collection) -> Bool` testet, ob `item` in `collection` ist.
|
- The function `in(item, collection) -> Bool` tests whether `item` is in `collection`.
|
||||||
- Sie hat auch das Alias ` ∈(item, collection)` und
|
- It also has the alias ` ∈(item, collection)` and
|
||||||
- sowohl `in` als auch `∈` können auch als Infix-Operatoren geschrieben werden.
|
- both `in` and `∈` can also be written as infix operators.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 3
|
x = 3
|
||||||
@@ -307,23 +307,24 @@ x in [1, 2, 3, 4, 5]
|
|||||||
x ∈ [1, 2, 33, 4, 5]
|
x ∈ [1, 2, 33, 4, 5]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Logische Operationen: `&&`, `||`, `!`
|
### Logical Operations: `&&`, `||`, `!`
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
3 < 4 && !(2 > 8) && !contains("aaa", "b")
|
3 < 4 && !(2 > 8) && !contains("aaa", "b")
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Bedingte Auswertung (_short circuit evaluation_)
|
#### Conditional Evaluation (_short circuit evaluation_)
|
||||||
|
|
||||||
- in `a && b` wird `b` nur ausgewertet, wenn `a == true`
|
- in `a && b` `b` is only evaluated if `a == true`
|
||||||
- in `a || b` wird `b` nur ausgewertet, wenn `a == false`
|
- in `a || b` `b` is only evaluated if `a == false`
|
||||||
|
|
||||||
(i) Damit kann `if test statement end` auch als `test && statement` geschrieben werden.
|
(i) Thus, `if test statement end` can also be written as `test && statement`.
|
||||||
|
|
||||||
(ii) Damit kann `if !test statement end` als `test || statement` geschrieben werden.
|
(ii) Thus, `if !test statement end` can be written as `test || statement`.
|
||||||
|
|
||||||
|
As an example^[from the [Julia documentation](https://docs.julialang.org/en/v1/manual/control-flow/#Short-Circuit-Evaluation)] here is an implementation of the factorial function:
|
||||||
|
|
||||||
Als Beispiel^[aus der [Julia-Dokumentation](https://docs.julialang.org/en/v1/manual/control-flow/#Short-Circuit-Evaluation)] hier eine Implementierung der Fakultätsfunktion *(factorial)*:
|
|
||||||
```{julia}
|
```{julia}
|
||||||
function fact(n::Int)
|
function fact(n::Int)
|
||||||
n >= 0 || error("n must be non-negative")
|
n >= 0 || error("n must be non-negative")
|
||||||
@@ -336,23 +337,23 @@ fact(5)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Natürlich kann man alle diese Tests auch Variablen vom Typ `Bool` zuordnen und
|
Of course, all these tests can also be assigned to variables of type `Bool` and
|
||||||
diese Variablen können als Tests in `if`- und `while`-Blöcken verwendet werden:
|
these variables can be used as tests in `if` and `while` blocks:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 3 < 4
|
x = 3 < 4
|
||||||
y = 5 ∈ [1, 2, 5, 7]
|
y = 5 ∈ [1, 2, 5, 7]
|
||||||
z = x && y
|
z = x && y
|
||||||
if z # äquivalent zu: if 3 < 4 && 5 in [1,2,5,7]
|
if z # equivalent to: if 3 < 4 && 5 in [1,2,5,7]
|
||||||
println("Stimmt alles!")
|
println("Stimmt alles!")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
- In Julia müssen alle Tests in einem logischen Ausdruck vom Typ `Bool` sein.
|
- In Julia, all tests in a logical expression must be of type `Bool`.
|
||||||
- Es gibt keine implizite Konvertierung à la *"0 is false and 1 (or anything != 0) is true"*
|
- There is no implicit conversion such as *"0 is false and 1 (or anything != 0) is true"*
|
||||||
- Wenn `x` ein numerischer Typ ist, dann muss daher das C-Idiom `if(x)` als `if x != 0` geschrieben werden.
|
- If `x` is a numeric type, then the C idiom `if(x)` must be written as `if x != 0`.
|
||||||
- Es gibt eine Ausnahme zur Unterstützung der _short circuit evaluation_:
|
- There is an exception to support the _short circuit evaluation_:
|
||||||
- bei den Konstrukten `a && b && c...` bzw `a || b || c...` muss der letzte Teilausdruck nicht vom Typ `Bool` sein, wenn diese Konstrukte nicht als Tests in `if` oder `while` verwendet werden:
|
- in the constructs `a && b && c...` or `a || b || c...` the last subexpression does not need to be of type `Bool` if these constructs are not used as tests in `if` or `while`:
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -365,9 +366,9 @@ z = 3 < 4 && 10 < 50 && sqrt(3^3)
|
|||||||
z, typeof(z)
|
z, typeof(z)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Schleifen *(loops)*
|
## Loops *(loops)*
|
||||||
|
|
||||||
### Die `while` ("solange")-Schleife
|
### The `while` ("while") loop
|
||||||
|
|
||||||
|
|
||||||
Syntax:
|
Syntax:
|
||||||
@@ -376,19 +377,19 @@ while *condition*
|
|||||||
*loop body*
|
*loop body*
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
Eine Reihe von Anweisungen (der Schleifenkörper) wird immer wieder abgearbeitet, solange eine Bedingung erfüllt ist.
|
A series of statements (the loop body) is repeatedly executed as long as a condition is satisfied.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
i = 1 # typischerweise braucht der Test der
|
i = 1 # typically the test of the
|
||||||
# while-Schleife eine Vorbereitung ...
|
# while loop needs preparation ...
|
||||||
while i < 10
|
while i < 10
|
||||||
println(i)
|
println(i)
|
||||||
i += 2 # ... und ein update
|
i += 2 # ... and an update
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Der Körper einer `while`- und `for`-Schleife kann die Anweisungen `break` und `continue` enthalten. `break` stoppt die Schleife, `continue` überspringt den Rest des Schleifenkörpers und beginnt sofort mit dem nächsten Schleifendurchlauf.
|
The body of a `while` and `for` loop can contain the statements `break` and `continue`. `break` stops the loop, `continue` skips the rest of the loop body and immediately starts the next loop iteration.
|
||||||
```{julia}
|
```{julia}
|
||||||
i = 0
|
i = 0
|
||||||
|
|
||||||
@@ -396,20 +397,20 @@ while i<10
|
|||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
if i == 3
|
if i == 3
|
||||||
continue # beginne sofort nächsten Durchlauf,
|
continue # start next iteration immediately,
|
||||||
end # überspringe Rest des Schleifenkörpers
|
end # skip rest of loop body
|
||||||
|
|
||||||
println("i = $i")
|
println("i = $i")
|
||||||
|
|
||||||
if i ≥ 5
|
if i ≥ 5
|
||||||
break # breche Schleife ab
|
break # break loop
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
println("Fertig!")
|
println("Fertig!")
|
||||||
```
|
```
|
||||||
|
|
||||||
Mit `break` kann man auch Endlosschleifen verlassen:
|
With `break` one can also exit infinite loops:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
i = 1
|
i = 1
|
||||||
@@ -421,7 +422,7 @@ while true
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
### `for`-Schleifen
|
### `for` Loops
|
||||||
|
|
||||||
Syntax:
|
Syntax:
|
||||||
|
|
||||||
@@ -431,9 +432,9 @@ for *var* in *iterable container*
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Der Schleifenkörper wird für alle Items aus einem Container durchlaufen.
|
The loop body is executed for all items from a container.
|
||||||
|
|
||||||
Statt `in` kann immer auch $\in$ verwendet werden. Im Kopf einer `for`-Schleife kann auch `=` verwendet werden.
|
Instead of `in`, $\in$ can always be used. In the header of a `for` loop, `=` can also be used.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
for i ∈ ["Mutter", "Vater", "Tochter"]
|
for i ∈ ["Mutter", "Vater", "Tochter"]
|
||||||
@@ -442,8 +443,8 @@ end
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Oft benötigt man einen numerischen Schleifenzähler. Dafür gibt es das *range*-Konstrukt. Die einfachsten Formen sind
|
Often a numerical loop counter is needed. For this purpose, there is the *range* construct. The simplest forms are
|
||||||
`Start:Ende` und `Start:Schrittweite:Ende`.
|
`Start:End` and `Start:Step:End`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
endwert = 5
|
endwert = 5
|
||||||
@@ -469,9 +470,9 @@ for k = 14 : -2.5 : 1 print(" $k") end
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### Geschachtelte Schleifen _(nested loops)_
|
#### Nested Loops _(nested loops)_
|
||||||
|
|
||||||
Ein `break` beendet die innerste Schleife.
|
A `break` ends the innermost loop.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
for i = 1:3
|
for i = 1:3
|
||||||
@@ -484,22 +485,22 @@ for i = 1:3
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Man kann *nested loops* auch in einer `for`-Anweisung zusammenfassen. Dann beendet ein `break` die Gesamtschleife.
|
*Nested loops* can also be combined in a single `for` statement. Then a `break` ends the entire loop.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
for i = 1:3, j=1:3 # im Prinzip dasselbe wie oben, aber:
|
for i = 1:3, j=1:3 # essentially the same as above, but:
|
||||||
println( (i,j) )
|
println( (i,j) )
|
||||||
if j == 2
|
if j == 2
|
||||||
break # break bricht hier die Gesamtschleife ab
|
break # break ends the entire loop here
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
:::{.callout-important .titlenormalxx}
|
:::{.callout-important .titlenormalxx}
|
||||||
## **Wichtig:** Die Semantik ist völlig anders, als bei C-artigen `for`-Schleifen!
|
## **Important:** The semantics are completely different from C-style `for` loops!
|
||||||
|
|
||||||
**Bei jedem Schleifendurchlauf wird die Laufvariable neu mit dem nächsten Element aus dem Container initialisiert.**
|
**In each loop iteration, the loop variable is re-initialized with the next element from the container.**
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -512,11 +513,11 @@ end
|
|||||||
|
|
||||||
-------
|
-------
|
||||||
|
|
||||||
Die C-Semantik von `for(i=1; i<5; i++)` entspricht der `while`-Schleife:
|
The C semantics of `for(i=1; i<5; i++)` corresponds to the `while` loop:
|
||||||
```
|
```
|
||||||
i = 1
|
i = 1
|
||||||
while i<5
|
while i<5
|
||||||
*loop body* # hier kann auch wirksam an i rumgepfuscht werden
|
*loop body* # here one can also mess with i effectively
|
||||||
i += 1
|
i += 1
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
@@ -524,68 +525,68 @@ end
|
|||||||
|
|
||||||
## Unicode
|
## Unicode
|
||||||
|
|
||||||
Julia verwendet Unicode als Zeichensatz. Damit können für Variablen, Funktionen etc auch Bezeichner aus nicht-lateinischen Schriften (zB Kyrillisch, Koreanisch, Sanskrit, Runen,
|
Julia uses Unicode as its character set. This allows identifiers from non-Latin scripts (e.g., Cyrillic, Korean, Sanskrit, runes,
|
||||||
Emoji,...) verwendet werden. Die Frage, wie man solche Zeichen in seinem Editor eingeben kann und ob der verwendete Bildschirm-Font sie darstellen kann, ist nicht Julias Problem.
|
emojis,...) to be used for variables, functions, etc. The question of how one can enter such characters in their editor and whether the used screen font can display them is not Julia's problem.
|
||||||
|
|
||||||
- Einige Unicode-Zeichen, z.B. `≤, ≠, ≥, π, ∈, √`, können anstelle von `<=, !=, >=, pi, in, sqrt` verwendet werden.
|
- Some Unicode characters, e.g., `≤, ≠, ≥, π, ∈, √`, can be used instead of `<=, !=, >=, pi, in, sqrt`.
|
||||||
|
|
||||||
- über 3000 Unicode-Zeichen können in Julia in einer LaTeX-ähnlichen Weise mit der Tab-Vervollständigung eingegeben werden.
|
- Over 3000 Unicode characters can be entered in Julia in a LaTeX-like manner using tab completion.
|
||||||
- `\alpha<TAB>` wird zu `α`,
|
- `\alpha<TAB>` becomes `α`,
|
||||||
- `\euler<TAB>` wird zu `ℯ` (Eulersche Zahl `exp(1)`, [spezielles Schreibschrift-e, `U+0212F`](https://www.htmlsymbol.com/unicode-code/212f.html))
|
- `\euler<TAB>` becomes `ℯ` (Euler's number `exp(1)`, [special script e, `U+0212F`](https://www.htmlsymbol.com/unicode-code/212f.html))
|
||||||
- `\le<TAB>` wird zu `≤`,
|
- `\le<TAB>` becomes `≤`,
|
||||||
- `\in<TAB>` wird zu `∈`,
|
- `\in<TAB>` becomes `∈`,
|
||||||
- `\:rainbow:<TAB>` wird zu `🌈`
|
- `\:rainbow:<TAB>` becomes `🌈`
|
||||||
[Hier geht es zur Liste.](https://docs.julialang.org/en/v1/manual/unicode-input/)
|
[Here is the list.](https://docs.julialang.org/en/v1/manual/unicode-input/)
|
||||||
|
|
||||||
## Eigenheiten und Stolperfallen der Syntax
|
## Idiosyncrasies and Pitfalls of Syntax
|
||||||
|
|
||||||
- Man kann den Multiplikationsoperator `*` nach einer numerischen Konstanten weglassen, wenn eine Variable, Funktion oder öffnende Klammer folgt.
|
- After a numeric constant, the multiplication operator `*` can be omitted when a variable, function, or opening parenthesis follows.
|
||||||
```
|
```
|
||||||
z = 3.4x + 2(x+y) + xy
|
z = 3.4x + 2(x+y) + xy
|
||||||
```
|
```
|
||||||
|
|
||||||
ist daher korrektes Julia. Beachte allerdings, dass der Term `xy` als eine Variable mit dem Namen xy interpretiert wird __und nicht__ als Produkt von x und y!
|
is therefore valid Julia. Note, however, that the term `xy` is interpreted as a single variable named xy __and not__ as the product of x and y!
|
||||||
|
|
||||||
- Diese Regel hat ein paar Tücken:
|
- This rule has a few pitfalls:
|
||||||
|
|
||||||
Das funktioniert wie erwartet:
|
This works as expected:
|
||||||
```{julia}
|
```{julia}
|
||||||
e = 7
|
e = 7
|
||||||
3e
|
3e
|
||||||
```
|
```
|
||||||
|
|
||||||
Hier wird die Eingabe als Gleitkommazahl interpretiert -- und `3E+2` oder `3f+2` (Float32) ebenso.
|
Here, the input is interpreted as a floating-point number -- and `3E+2` or `3f+2` (Float32) as well.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
3e+2
|
3e+2
|
||||||
```
|
```
|
||||||
|
|
||||||
Ein Leerzeichen schafft Eindeutigkeit:
|
A space creates clarity:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
3e + 2
|
3e + 2
|
||||||
```
|
```
|
||||||
|
|
||||||
Das funktioniert:
|
This works:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 4
|
x = 4
|
||||||
3x + 3
|
3x + 3
|
||||||
```
|
```
|
||||||
|
|
||||||
...und das nicht. `0x`, `0o`, `0b` wird als Anfang einer Hexadezimal-, Oktal- bzw. Binärkonstanten interpretiert.
|
...and this does not. `0x`, `0o`, `0b` are interpreted as the beginning of a hexadecimal, octal, or binary constant.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
3y + 0x
|
3y + 0x
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
- Es gibt noch ein paar andere Fälle, bei denen die sehr kulante Syntax zu Überraschungen führt.
|
- There are a few other cases where the very permissive syntax leads to surprises.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
Wichtig = 21
|
Wichtig = 21
|
||||||
Wichtig! = 42 # Bezeichner können auch ein ! enthalten
|
Wichtig! = 42 # identifiers can also contain !
|
||||||
(Wichtig, Wichtig!)
|
(Wichtig, Wichtig!)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -596,28 +597,24 @@ Wichtig!=88
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Julia interpretiert das als Vergleich `Wichtig != 88`.
|
Julia interprets this as the comparison `Wichtig != 88`.
|
||||||
|
|
||||||
Leerzeichen helfen:
|
|
||||||
|
|
||||||
|
Spaces help:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
Wichtig! = 88
|
Wichtig! = 88
|
||||||
Wichtig!
|
Wichtig!
|
||||||
```
|
```
|
||||||
|
|
||||||
- Operatoren der Form `.*`, `.+`,... haben in Julia eine spezielle Bedeutung (*broadcasting*, d.h., vektorisierte Operationen).
|
- Operators of the form `.*`, `.+`,... have a special meaning in Julia (*broadcasting*, i.e., vectorized operations).
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
1.+2.
|
1.+2.
|
||||||
```
|
```
|
||||||
|
|
||||||
Wieder gilt: Leerzeichen schaffen Klarheit!
|
Again, spaces create clarity!
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
1. + 2.
|
1. + 2.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,22 +15,22 @@ Base.active_module() = myactive_module()
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
# Das Typsystem von Julia
|
# The Julia Type System
|
||||||
|
|
||||||
Man kann umfangreiche Programme in Julia schreiben, ohne auch nur eine einzige Typdeklaration verwenden zu müssen. Das ist natürlich Absicht und soll die Arbeit der Anwender vereinfachen.
|
One can write extensive programs in Julia without using a single type declaration. This is, of course, intentional and should simplify the work of users.
|
||||||
|
|
||||||
Wir blicken jetzt trotzdem mal unter die Motorhaube.
|
However, we will now take a look under the hood.
|
||||||
|
|
||||||
## Die Typhierarchie am Beispiel der numerischen Typen
|
## The Type Hierarchy with the Example of Numeric Types
|
||||||
|
|
||||||
Das Typsystem hat die Struktur eines Baums, dessen Wurzel der Typ `Any` ist. Mit den Funktionen `subtypes()` und `supertype()` kann man den Baum erforschen. Sie zeigen alle Kinder bzw. die Mutter eines Knotens an.
|
The type system has the structure of a tree whose root is the type `Any`. The functions `subtypes()` and `supertype()` can be used to explore the tree. They show all children or the parent of a node.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
subtypes(Int64)
|
subtypes(Int64)
|
||||||
```
|
```
|
||||||
Das Ergebnis ist eine leere Liste von Typen. `Int64` ist ein sogenannter **konkreter Typ** und hat keine Untertypen.
|
The result is an empty list of types. `Int64` is a so-called **concrete type** and has no subtypes.
|
||||||
|
|
||||||
Wir klettern jetzt mal die Typhierarchie auf diesem Ast nach oben bis zur Wurzel (Informatiker-Bäume stehen bekanntlich immer auf dem Kopf).
|
Let's now climb the type hierarchy on this branch to the root (in computer science, trees are always standing on their heads).
|
||||||
```{julia}
|
```{julia}
|
||||||
supertype(Int64)
|
supertype(Int64)
|
||||||
```
|
```
|
||||||
@@ -46,72 +46,69 @@ supertype(Real)
|
|||||||
```{julia}
|
```{julia}
|
||||||
supertype(Number)
|
supertype(Number)
|
||||||
```
|
```
|
||||||
Das wäre übrigens auch schneller gegangen: Die Funktion `supertypes()` (mit Plural-s) zeigt alle Vorfahren an.
|
This would have been faster, by the way: The function `supertypes()` (with plural-s) shows all ancestors.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
supertypes(Int64)
|
supertypes(Int64)
|
||||||
```
|
```
|
||||||
|
|
||||||
Nun kann man sich die Knoten angucken:
|
Now one can look at the nodes:
|
||||||
|
|
||||||
{{< embed ../notebooks/nb-types.ipynb#nb3 >}}
|
{{< embed ../notebooks/nb-types.ipynb#nb3 >}}
|
||||||
|
|
||||||
Mit einer kleinen rekursiven Funktion kann man schnell einen ganzen (Unter-)Baum ausdrucken:
|
With a small recursive function, one can quickly print out an entire (sub-)tree:
|
||||||
|
|
||||||
{{< embed ../notebooks/nb-types.ipynb#nb1 >}}
|
{{< embed ../notebooks/nb-types.ipynb#nb1 >}}
|
||||||
|
|
||||||
::::{.content-hidden unless-format="xxx"}
|
::::{.content-hidden unless-format="xxx"}
|
||||||
|
|
||||||
...und natürlich gibt es da auch ein Julia-Paket:
|
...and of course, there is also a Julia package for this:
|
||||||
|
|
||||||
{{< embed ../notebooks/nb-types.ipynb#nb2 >}}
|
{{< embed ../notebooks/nb-types.ipynb#nb2 >}}
|
||||||
|
|
||||||
:::
|
::::
|
||||||
|
|
||||||
|
|
||||||
Hier das Ganze nochmal als Bild (gemacht mit LaTeX/[TikZ](https://tikz.dev/tikz-trees))
|
Here again as an image (made with LaTeX/[TikZ](https://tikz.dev/tikz-trees))
|
||||||
|
|
||||||
::: {.content-visible when-format="html"}
|
::: {.content-visible when-format="html"}
|
||||||
{width=80%}
|
{width=80%}
|
||||||
:::
|
:::
|
||||||
|
|
||||||
::: {.content-visible when-format="pdf"}
|
::: {.content-visible when-format="pdf"}
|
||||||
{width=60%}
|
{width=60%}
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
Natürlich hat Julia nicht nur numerische Typen. Die Anzahl der direkten Abkömmlinge (Kinder) von `Any` ist
|
Of course, Julia has not only numeric types. The number of direct descendants (children) of `Any` is
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
length(subtypes(Any))
|
length(subtypes(Any))
|
||||||
```
|
```
|
||||||
und mit (fast) jedem Paket, das man mit `using ...` lädt, werden es mehr.
|
and with (almost) every package loaded with `using ...`, this increases.
|
||||||
|
|
||||||
|
## Abstract and Concrete Types
|
||||||
|
|
||||||
## Abstrakte und Konkrete Typen
|
- An object always has a **concrete** type.
|
||||||
|
- Concrete types have no more subtypes, they are always the "leaves" of the tree.
|
||||||
- Ein Objekt hat immer einen **konkreten** Typ.
|
- Concrete types specify a concrete data structure.
|
||||||
- Konkrete Typen haben keine Untertypen mehr, sie sind immer „Blätter“ des Baumes.
|
|
||||||
- Konkrete Typen spezifizieren eine konkrete Datenstruktur.
|
|
||||||
|
|
||||||
:::{.xxx}
|
:::{.xxx}
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
- Abstrakte Typen können nicht instanziiert werden, d.h., es gibt keine Objekte mit diesem Typ.
|
- Abstract types cannot be instantiated, i.e., there are no objects of this type.
|
||||||
- Sie definieren eine Menge von konkreten Typen und gemeinsame Methoden für diese Typen.
|
- They define a set of concrete types and common methods for these types.
|
||||||
- Sie können daher in der Definition von Funktionstypen, Argumenttypen, Elementtypen von zusammengesetzten Typen u.ä. verwendet werden.
|
- They can therefore be used in the definition of function types, argument types, element types of composite types, etc.
|
||||||
|
|
||||||
|
|
||||||
|
For **declaring** *and* **testing** the "descent" within the type hierarchy, there is a special operator:
|
||||||
Zum **Deklarieren** *und* **Testen** der "Abstammung" innerhalb der Typhierarchie gibt es einen eigenen Operator:
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
Int64 <: Number
|
Int64 <: Number
|
||||||
```
|
```
|
||||||
|
|
||||||
Zum Testen, ob ein Objekt einen bestimmten Typ (oder einen abstrakten Supertyp davon) hat, dient `isa(object, typ)`. Es wird meist in der Infix-Form verwendet und sollte als Frage `x is a T?` gelesen werden.
|
To test whether an object has a certain type (or an abstract supertype of it), `isa(object, typ)` is used. It is usually used in infix form and should be read as the question `x is a T?`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 17.2
|
x = 17.2
|
||||||
@@ -120,7 +117,7 @@ x = 17.2
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Da abstrakte Typen keine Datenstrukturen definieren, ist ihre Definition recht schlicht. Entweder sie stammen direkt von `Any` ab:
|
Since abstract types do not define data structures, their definition is quite simple. Either they are derived directly from `Any`:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
abstract type MySuperType end
|
abstract type MySuperType end
|
||||||
@@ -128,7 +125,7 @@ abstract type MySuperType end
|
|||||||
supertype(MySuperType)
|
supertype(MySuperType)
|
||||||
```
|
```
|
||||||
|
|
||||||
oder von einem anderen abstrakten Typ:
|
or from another abstract type:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
abstract type MySpecialNumber <: Integer end
|
abstract type MySpecialNumber <: Integer end
|
||||||
@@ -136,24 +133,24 @@ abstract type MySpecialNumber <: Integer end
|
|||||||
supertypes(MySpecialNumber)
|
supertypes(MySpecialNumber)
|
||||||
```
|
```
|
||||||
|
|
||||||
Mit der Definition werden die abstrakten Typen an einer Stelle des Typ-Baums "eingehängt".
|
With the definition, the abstract types are "hung" at a point in the type tree.
|
||||||
|
|
||||||
## Die numerischen Typen `Bool` und `Irrational`
|
## The Numeric Types `Bool` and `Irrational`
|
||||||
|
|
||||||
Da sie im Baum der numerischen Typen zu sehen sind, seien sie kurz erklärt:
|
Since they are seen in the numeric type tree, they should be briefly explained:
|
||||||
|
|
||||||
`Bool` ist numerisch im Sinne von `true=1, false=0`:
|
`Bool` is numeric in the sense of `true=1, false=0`:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
true + true + true, false - true, sqrt(true), true/4
|
true + true + true, false - true, sqrt(true), true/4
|
||||||
```
|
```
|
||||||
|
|
||||||
`Irrational` ist der Typ einiger vordefinierter Konstanten wie `π` und `ℯ`.
|
`Irrational` is the type of some predefined constants such as `π` and `ℯ`.
|
||||||
Laut [Dokumentation](https://docs.julialang.org/en/v1/base/numbers/#Base.AbstractIrrational) ist `Irrational` ein *"Number type representing an exact irrational value, which is automatically rounded to the correct precision in arithmetic operations with other numeric quantities".*
|
According to the [documentation](https://docs.julialang.org/en/v1/base/numbers/#Base.AbstractIrrational), `Irrational` is a *"Number type representing an exact irrational value, which is automatically rounded to the correct precision in arithmetic operations with other numeric quantities".*
|
||||||
|
|
||||||
## Union-Typen
|
## Union Types
|
||||||
|
|
||||||
Falls die Baum-Hierarchie nicht ausreicht, kann man auch abstrakte Typen als Vereinigung beliebiger (abstrakter und konkreter) Typen definieren.
|
If the tree hierarchy is not sufficient, one can also define abstract types as a union of arbitrary (abstract and concrete) types.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
IntOrString = Union{Int64,String}
|
IntOrString = Union{Int64,String}
|
||||||
@@ -161,17 +158,17 @@ IntOrString = Union{Int64,String}
|
|||||||
|
|
||||||
:::{.callout-note .titlenormal}
|
:::{.callout-note .titlenormal}
|
||||||
|
|
||||||
## Beispiel
|
## Example
|
||||||
Das Kommando `methods(<)` zeigt, dass unter den über 70 Methoden, die für den Vergleichsoperator definiert sind, einige auch *union types* verwenden, z.B. ist
|
The command `methods(<)` shows that among the over 70 methods defined for the comparison operator, some also use *union types*, e.g., there is
|
||||||
```julia
|
```julia
|
||||||
<(x::Union{Float16, Float32, Float64}, y::BigFloat)
|
<(x::Union{Float16, Float32, Float64}, y::BigFloat)
|
||||||
```
|
```
|
||||||
eine Methode für den Vergleich einer Maschinenzahl fester Länge mit einer Maschinenzahl beliebiger Länge.
|
a method for comparing a machine number of fixed length with a machine number of arbitrary length.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Zusammengesetzte (_composite_) Typen: `struct`
|
## Composite (_composite_) Types: `struct`
|
||||||
|
|
||||||
Eine `struct` ist eine Zusammenstellung von mehreren benannten Feldern und definiert einen konkreten Typ.
|
A `struct` is a collection of several named fields and defines a concrete type.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
abstract type Point end
|
abstract type Point end
|
||||||
@@ -188,7 +185,7 @@ mutable struct Point3D <: Point
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Wie wir schon bei Ausdrücken der Form `x = Int8(33)` gesehen haben, kann man Typnamen direkt als Konstruktoren einsetzen:
|
As we have already seen with expressions of the form `x = Int8(33)`, type names can be used directly as constructors:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
p1 = Point2D(1.4, 3.5)
|
p1 = Point2D(1.4, 3.5)
|
||||||
@@ -200,20 +197,20 @@ p1 isa Point3D, p1 isa Point2D, p1 isa Point
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Die Felder einer `struct` können über ihren Namen mit dem `.`-Operator adressiert werden.
|
The fields of a `struct` can be addressed by their name with the `.` operator.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
p1.y
|
p1.y
|
||||||
```
|
```
|
||||||
|
|
||||||
Da wir unsere `struct` als `mutable` deklariert haben, können wir das Objekt `p1` modifizieren, indem wir den Feldern neue Werte zuweisen.
|
Since we declared our `struct` as `mutable`, we can modify the object `p1` by assigning new values to the fields.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
p1.x = 3333.4
|
p1.x = 3333.4
|
||||||
p1
|
p1
|
||||||
```
|
```
|
||||||
|
|
||||||
Informationen über den Aufbau eines Typs oder eines Objekts von diesem Typ liefert `dump()`.
|
Information about the structure of a type or an object of that type is provided by `dump()`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
dump(Point3D)
|
dump(Point3D)
|
||||||
@@ -224,28 +221,28 @@ dump(Point3D)
|
|||||||
dump(p1)
|
dump(p1)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Funktionen und *Multiple dispatch*
|
## Functions and *Multiple Dispatch*
|
||||||
|
|
||||||
:::{.callout-note .titlenormal}
|
:::{.callout-note .titlenormal}
|
||||||
|
|
||||||
## Objekte, Funktionen, Methoden
|
## Objects, Functions, Methods
|
||||||
|
|
||||||
In klassischen objektorientierten Sprachen wie C++/Java haben Objekte üblicherweise mit ihnen assoziierte Funktionen, die Methoden des Objekts.
|
In classical object-oriented languages like C++/Java, objects usually have functions associated with them, which are the methods of the object.
|
||||||
|
|
||||||
In Julia gehören Methoden zu einer Funktion und nicht zu einem Objekt.
|
In Julia, methods belong to a function and not to an object.
|
||||||
(Eine Ausnahme sind die Konstruktoren, also Funktionen, die genauso heißen wie ein Typ und ein Objekt dieses Typs erzeugen.)
|
(An exception is the constructors, i.e., functions that have the same name as a type and create an object of that type.)
|
||||||
|
|
||||||
Sobald man einen neuen Typ definiert hat, kann man sowohl neue als auch bestehende Funktionen um neue Methoden für diesen Typ ergänzen.
|
Once one has defined a new type, one can add new or existing functions around new methods for this type.
|
||||||
|
|
||||||
- Eine Funktion kann mehrfach für verschiedene Argumentlisten (Typ und Anzahl) definiert werden.
|
- A function can be defined multiple times for different argument lists (type and number).
|
||||||
- Die Funktion hat dann mehrere Methoden.
|
- The function then has multiple methods.
|
||||||
- Beim Aufruf wird an Hand der konkreten Argumente entschieden, welche Methode genutzt wird *(multiple dispatch)*.
|
- When calling, it is decided based on the concrete arguments which method is used *(multiple dispatch)*.
|
||||||
- Es ist typisch für Julia, dass für Standardfunktionen viele Methoden definiert sind. Diese können problemlos um weitere Methoden für eigene Typen erweitert werden.
|
- It is typical for Julia that for standard functions, many methods are defined. These can be easily extended by further methods for own types.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
Den Abstand zwischen zwei Punkten implementieren wir als Funktion mit zwei Methoden:
|
We implement the distance between two points as a function with two methods:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
function distance(p1::Point2D, p2::Point2D)
|
function distance(p1::Point2D, p2::Point2D)
|
||||||
@@ -256,35 +253,34 @@ function distance(p1::Point3D, p2::Point3D)
|
|||||||
sqrt((p1.x-p2.x)^2 + (p1.y-p2.y)^2 + (p1.z-p2.z)^2)
|
sqrt((p1.x-p2.x)^2 + (p1.y-p2.y)^2 + (p1.z-p2.z)^2)
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
distance(p1, Point2D(2200, -300))
|
distance(p1, Point2D(2200, -300))
|
||||||
```
|
```
|
||||||
|
|
||||||
Wie schon erwähnt, zeigt `methods()` die Methodentabelle einer Funktion an:
|
As mentioned earlier, `methods()` shows the method table of a function:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
methods(distance)
|
methods(distance)
|
||||||
```
|
```
|
||||||
|
|
||||||
Das Macro `@which`, angewendet auf einen vollen Funktionsaufruf mmit konkreter Argumentliste, zeigt an, welche Methode zu diesen konkreten Argumenten ausgewählt wird:
|
The macro `@which`, applied to a full function call with concrete argument list, shows which method is selected for these concrete arguments:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@which sqrt(3.3)
|
@which sqrt(3.3)
|
||||||
```
|
```
|
||||||
```{julia}
|
```{julia}
|
||||||
z = "Hallo" * '!'
|
z = "Hello" * '!'
|
||||||
println(z)
|
println(z)
|
||||||
|
|
||||||
@which "Hallo" * '!'
|
@which "Hello" * '!'
|
||||||
```
|
```
|
||||||
|
|
||||||
Methoden können auch abstrakte Typen als Argument haben:
|
Methods can also have abstract types as arguments:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
"""
|
"""
|
||||||
Berechnet den Winkel ϕ (in Grad) der Polarkoordinaten (2D) bzw.
|
Calculates the angle ϕ (in degrees) of the polar coordinates (2D) or
|
||||||
Kugelkoordinaten (3D) eines Punktes
|
spherical coordinates (3D) of a point
|
||||||
"""
|
"""
|
||||||
function phi_winkel(p::Point)
|
function phi_winkel(p::Point)
|
||||||
atand(p.y, p.x)
|
atand(p.y, p.x)
|
||||||
@@ -294,8 +290,8 @@ phi_winkel(p1)
|
|||||||
```
|
```
|
||||||
|
|
||||||
:::{.callout-tip collapse="true"}
|
:::{.callout-tip collapse="true"}
|
||||||
Ein in *triple quotes* eingeschlossene Text unmittelbat vor der Funktionsdefinition
|
A text enclosed in *triple quotes* immediately before the function definition
|
||||||
wird automatisch in die Hilfe-Datenbank von Julia integriert:
|
is automatically integrated into Julia's help database:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
?phi_winkel
|
?phi_winkel
|
||||||
@@ -304,8 +300,8 @@ wird automatisch in die Hilfe-Datenbank von Julia integriert:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Beim *multiple dispatch* wird die Methode angewendet, die unter allen passenden die spezifischste ist. Hier eine Funktion mit mehreren Methoden
|
With *multiple dispatch*, the method is applied that is the most specific among all matching ones. Here is a function with several methods
|
||||||
(alle bis auf die letzte in der kurzen [*assignment form*](https://docs.julialang.org/en/v1/manual/functions/#man-functions) geschrieben):
|
(all but the last in the short [*assignment form*](https://docs.julialang.org/en/v1/manual/functions/#man-functions) written):
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
f(x::String, y::Number) = "Args: String + Zahl"
|
f(x::String, y::Number) = "Args: String + Zahl"
|
||||||
@@ -318,35 +314,35 @@ function f(x::Number, y::Number, z::String)
|
|||||||
return "Arg: 2 x Zahl + String"
|
return "Arg: 2 x Zahl + String"
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
Hier passen die ersten beiden Methoden. Gewählt wird die zweite, da sie spezifischer ist, `Int64 <: Number`.
|
Here, the first two methods match. The second is chosen since it is more specific, `Int64 <: Number`.
|
||||||
```{julia}
|
```{julia}
|
||||||
f("Hallo", 42)
|
f("Hello", 42)
|
||||||
```
|
```
|
||||||
Es kann sein, dass diese Vorschrift zu keinem eindeutigen Ergebnis führt, wenn man seine Methoden schlecht gewählt hat.
|
It may happen that this rule does not lead to a unique result if one chooses one's methods badly.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
f(42, 42)
|
f(42, 42)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Parametrisierte numerische Typen: `Rational` und `Complex`
|
## Parametric Numeric Types: `Rational` and `Complex`
|
||||||
|
|
||||||
|
|
||||||
- Für rationale Zahlen (Brüche) verwendet Julia `//` als Infix-Konstruktor:
|
- For rational numbers (fractions), Julia uses `//` as an infix constructor:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show Rational(23, 17) 4//16 + 1//3;
|
@show Rational(23, 17) 4//16 + 1//3;
|
||||||
```
|
```
|
||||||
|
|
||||||
- Die imaginäre Einheit $\sqrt{-1}$ heißt `im`
|
- The imaginary unit $\sqrt{-1}$ is called `im`
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show Complex(0.4) 23 + 0.5im/(1-2im);
|
@show Complex(0.4) 23 + 0.5im/(1-2im);
|
||||||
```
|
```
|
||||||
|
|
||||||
`Rational` und `Complex` bestehen, ähnlich wie unser `Point2D`, aus 2 Feldern: Zähler und Nenner bzw. Real- und Imaginärteil.
|
`Rational` and `Complex` consist, similar to our `Point2D`, of 2 fields: numerator and denominator or real and imaginary part.
|
||||||
|
|
||||||
Der Typ dieser Felder ist allerdings nicht vollständig festgelegt. `Rational` und `Complex` sind _parametrisierte_ Typen.
|
However, the type of these fields is not completely fixed. `Rational` and `Complex` are _parametric_ types.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 2//7
|
x = 2//7
|
||||||
@@ -367,14 +363,14 @@ y = 1.0 + 2.0im
|
|||||||
typeof(y)
|
typeof(y)
|
||||||
```
|
```
|
||||||
|
|
||||||
Die konkreten Typen `Rational{Int64}`, `Rational{BigInt}`,..., `Complex{Int64}`, `Complex{Float64}}`, ... sind Subtypen von `Rational` bzw. `Complex`.
|
The concrete types `Rational{Int64}`, `Rational{BigInt}`,..., `Complex{Int64}`, `Complex{Float64}}`, ... are subtypes of `Rational` resp. `Complex`.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
Rational{BigInt} <: Rational
|
Rational{BigInt} <: Rational
|
||||||
```
|
```
|
||||||
|
|
||||||
Die Definitionen [sehen etwa so aus](https://github.com/JuliaLang/julia/blob/master/base/rational.jl#L6-L15):
|
The definitions [look roughly like this](https://github.com/JuliaLang/julia/blob/master/base/rational.jl#L6-L15):
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
struct MyComplex{T<:Real} <: Number
|
struct MyComplex{T<:Real} <: Number
|
||||||
@@ -388,19 +384,19 @@ struct MyRational{T<:Integer} <: Real
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Die erste Definition besagt:
|
The first definition says:
|
||||||
|
|
||||||
- `MyComplex` hat zwei Felder `re` und `im`, beide vom gleichen Typ `T`.
|
- `MyComplex` has two fields `re` and `im`, both of the same type `T`.
|
||||||
- Dieser Typ `T` muss ein Untertyp von `Real` sein.
|
- This type `T` must be a subtype of `Real`.
|
||||||
- `MyComplex` und alle seine Varianten wie `MyComplex{Float64}` sind Untertypen von `Number`.
|
- `MyComplex` and all its variants like `MyComplex{Float64}` are subtypes of `Number`.
|
||||||
|
|
||||||
und die zweite besagt analog:
|
and the second says analogously:
|
||||||
|
|
||||||
- `MyRational` hat zwei Felder `num` und `den`, beide vom gleichen Typ `T`.
|
- `MyRational` has two fields `num` and `den`, both of the same type `T`.
|
||||||
- Dieser Typ `T` muss ein Untertyp von `Integer` sein.
|
- This type `T` must be a subtype of `Integer`.
|
||||||
- `MyRational` und seine Varianten sind Untertypen von `Real`.
|
- `MyRational` and its variants are subtypes of `Real`.
|
||||||
|
|
||||||
Nun ist ℚ$\subset$ ℝ, oder auf julianisch `Rational <: Real`. Also können die Komponenten einer komplexen Zahl auch rational sein:
|
Now ℚ$\subset$ ℝ, or in Julia notation `Rational <: Real`. Thus, the components of a complex number can also be rational:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
z = 3//4 + 5im
|
z = 3//4 + 5im
|
||||||
@@ -409,23 +405,24 @@ dump(z)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Diese Strukturen sind ohne das `mutable`-Attribut definiert, also *immutable*:
|
|
||||||
|
These structures are defined without the `mutable` attribute, therefore *immutable*:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x = 2.2 + 3.3im
|
x = 2.2 + 3.3im
|
||||||
println("Der Realteil ist: $(x.re)")
|
println("The real part is: $(x.re)")
|
||||||
|
|
||||||
x.re = 4.4
|
x.re = 4.4
|
||||||
```
|
```
|
||||||
Das ist so üblich. Wir betrachten das Objekt `9` vom Typ `Int64` ja auch als unveränderlich.
|
This is common. We also consider the object `9` of type `Int64` as immutable.
|
||||||
Das Folgende geht natürlich trotzdem:
|
The following, of course, still works:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x += 2.2
|
x += 2.2
|
||||||
```
|
```
|
||||||
Hier wird ein neues Objekt vom Typ `Complex{Float64}` erzeugt und `x` zur Referenz auf dieses neue Objekt gemacht.
|
Here, a new object of type `Complex{Float64}` is created and `x` is made a reference to this new object.
|
||||||
|
|
||||||
Die Möglichkeiten des Typsystems verleiten leicht zum Spielen. Hier definieren wir eine `struct`, die wahlweise eine Maschinenzahl oder ein Paar von Ganzzahlen enthalten kann:
|
The possibilities of the type system easily invite to play. Here we define a `struct` that can contain either a machine number or a pair of integers:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
struct MyParms{T <: Union{Float64, Tuple{Int64, Int64}}}
|
struct MyParms{T <: Union{Float64, Tuple{Int64, Int64}}}
|
||||||
@@ -441,13 +438,13 @@ p2 = MyParms( (2, 4) )
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Typen als Objekte
|
## Types as Objects
|
||||||
|
|
||||||
(1) Typen sind ebenfalls Objekte. Sie sind Objekte einer der drei "Meta-Typen"
|
(1) Types are also objects. They are objects of one of the three "meta-types"
|
||||||
|
|
||||||
- `Union` (Union-Typen)
|
- `Union` (union types)
|
||||||
- `UnionAll` (parametrisierte Typen)
|
- `UnionAll` (parametric types)
|
||||||
- `DataType` (alle konkreten und sonstige abstrakte Typen)
|
- `DataType` (all concrete and other abstract types)
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@show 23779 isa Int64 Int64 isa DataType;
|
@show 23779 isa Int64 Int64 isa DataType;
|
||||||
@@ -463,7 +460,7 @@ p2 = MyParms( (2, 4) )
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Diese 3 konkreten "Meta-Typen" sind übrigens Subtypen des abstrakten "Meta-Typen" `Type`.
|
These 3 concrete "meta-types" are, by the way, subtypes of the abstract "meta-type" `Type`.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
subtypes(Type)
|
subtypes(Type)
|
||||||
@@ -471,7 +468,7 @@ subtypes(Type)
|
|||||||
|
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
(2) Damit können Typen auch einfach Variablen zugewiesen werden:
|
(2) Thus, types can also be easily assigned to variables:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
x3 = Float64
|
x3 = Float64
|
||||||
@@ -480,15 +477,15 @@ x3 = Float64
|
|||||||
|
|
||||||
:::{.callout-note collapse="true"}
|
:::{.callout-note collapse="true"}
|
||||||
|
|
||||||
Dies zeigt auch, dass die [Style-Vorgaben in Julia](https://docs.julialang.org/en/v1/manual/style-guide/#Use-naming-conventions-consistent-with-Julia-base/) wie „Typen und Typvariablen starten mit Großbuchstaben, sonstige Variablen und Funktionen werden klein geschrieben.“ nur Konventionen sind und von der Sprache nicht erzwungen werden.
|
This also shows that the [style guidelines in Julia](https://docs.julialang.org/en/v1/manual/style-guide/#Use-naming-conventions-consistent-with-Julia-base/) such as "Types and type variables start with uppercase letters, other variables and functions are written in lowercase." are only conventions and are not enforced by the language.
|
||||||
|
|
||||||
Man sollte sie trotzdem einhalten, um den Code lesbar zu halten.
|
One should still follow them to keep the code readable.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
Wenn man solche Zuweisungen mit `const` für dauerhaft erklärt, entsteht ein
|
If such assignments are declared permanent with `const`, a
|
||||||
*type alias*.
|
*type alias* is created.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -500,7 +497,7 @@ typeof(z)
|
|||||||
|
|
||||||
--------
|
--------
|
||||||
|
|
||||||
(3) Typen können Argumente von Funktionen sein.
|
(3) Types can be arguments of functions.
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
@@ -516,74 +513,76 @@ z = myf(43, UInt16, Real)
|
|||||||
@show z typeof(z);
|
@show z typeof(z);
|
||||||
```
|
```
|
||||||
|
|
||||||
Wenn man diese Funktion mit Typsignaturen definieren möchte, kann man natürlich
|
If one wants to define this function with type signatures, of course one can write
|
||||||
```julia
|
```julia
|
||||||
function myf(x, S::Type, T::Type) ... end
|
function myf(x, S::Type, T::Type) ... end
|
||||||
```
|
```
|
||||||
schreiben. Üblicher ist hier die (dazu äquivalente) spezielle Syntax
|
However, the (equivalent) special syntax
|
||||||
```julia
|
```julia
|
||||||
function myf(x, ::Type{S}, ::Type{T}) where {S,T} ... end
|
function myf(x, ::Type{S}, ::Type{T}) where {S,T} ... end
|
||||||
```
|
```
|
||||||
bei der man in der `where`-Klausel auch noch Einschränkungen an die zulässigen Werte der Typvariablen `S` und `T` stellen kann.
|
is more common here, where one can also impose restrictions on the permissible values of the type variables `S` and `T` in the `where` clause.
|
||||||
|
|
||||||
Wie definiere ich eine spezielle Methode von `myf`, die nur aufgerufen werden soll, wenn `S` und `T` gleich `Int64` sind? Das ist folgendermaßen möglich:
|
How do I define a special method of `myf` that should only be called when `S` and `T` are equal to `Int64`? This is possible as follows:
|
||||||
|
|
||||||
```julia
|
```julia
|
||||||
function myf(x, ::Type{Int64}, ::Type{Int64}) ... end
|
function myf(x, ::Type{Int64}, ::Type{Int64}) ... end
|
||||||
```
|
```
|
||||||
`Type{Int64}` wirkt wie ein "Meta-Typ", dessen einzige Instanz der Typ `Int64` ist.
|
`Type{Int64}` acts like a "meta-type", whose only instance is the type `Int64`.
|
||||||
|
|
||||||
|
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
(4) Es gibt zahlreiche Operationen mit Typen als Argumenten. Wir haben schon `<:(T1, T2)`, `supertype(T)`, `supertypes(T)`, `subtypes(T)` gesehen. Erwähnt seien noch `typejoin(T1,T2)` (nächster gemeinsamer Vorfahre im Typbaum) und Tests wie `isconcretetype(T)`, `isabstracttype(T)`, `isstructtype(T)`.
|
(4) There are numerous operations with types as arguments. We have already seen `<:(T1, T2)`, `supertype(T)`, `supertypes(T)`, `subtypes(T)`. Mentioned should be still `typejoin(T1,T2)` (next common ancestor in the type tree) and tests like `isconcretetype(T)`, `isabstracttype(T)`, `isstructtype(T)`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Invarianz parametrisierter Typen {#sec-invariance}
|
## Invariance of Parametric Types {#sec-invariance}
|
||||||
|
|
||||||
Kann man in parametrisierten Typen auch nicht-konkrete Typen einsetzen? Gibt es `Complex{AbstractFloat}` oder `Complex{Union{Float32, Int16}}`?
|
Can non-concrete types also be substituted into parametric types? Are there `Complex{AbstractFloat}` or `Complex{Union{Float32, Int16}}`?
|
||||||
|
|
||||||
Ja, die gibt es; und es sind konkrete Typen, man kann also Objekte von diesem Typ erzeugen.
|
Yes, they exist; and they are concrete types, one can therefore create objects of this type.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
z5 = Complex{Integer}(2, 0x33)
|
z5 = Complex{Integer}(2, 0x33)
|
||||||
dump(z5)
|
dump(z5)
|
||||||
```
|
```
|
||||||
Das ist eine heterogene Struktur. Jede Komponente hat einen individuellen Typ `T`, für den `T<:Integer` gilt.
|
This is a heterogeneous structure. Each component has an individual type `T`, for which `T<:Integer` holds.
|
||||||
|
|
||||||
Nun gilt zwar
|
Now it holds that
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
Int64 <: Integer
|
Int64 <: Integer
|
||||||
```
|
```
|
||||||
aber es gilt nicht, dass
|
but it does not hold that
|
||||||
```{julia}
|
```{julia}
|
||||||
Complex{Int64} <: Complex{Integer}
|
Complex{Int64} <: Complex{Integer}
|
||||||
```
|
```
|
||||||
|
|
||||||
Diese Typen sind beide konkret. Damit können sie in der Typhierarchie von Julia nicht in einer Sub/Supertype-Relation zueinander stehen. Julias parametrisierte Typen sind [in der Sprache der theoretischen Informatik](https://de.wikipedia.org/wiki/Kovarianz_und_Kontravarianz) **invariant**.
|
These types are both concrete. Therefore, they cannot stand in a sub/supertype relation to each other in Julia's type hierarchy. Julia's parametric types are [in the language of theoretical computer science](https://en.wikipedia.org/wiki/Covariance_and_contravariance) **invariant**.
|
||||||
(Wenn aus `S<:T` folgen würde, dass auch `ParamType{S} <: ParamType{T}` gilt, würde man von **Kovarianz** sprechen.)
|
(If from `S<:T` it would follow that also `ParamType{S} <: ParamType{T}`, one would speak of **covariance**.)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Generische Funktionen
|
|
||||||
|
|
||||||
Der übliche (und in vielen Fällen empfohlene!) Programmierstil in Julia ist das Schreiben generischer Funktionen:
|
## Generic Functions
|
||||||
|
|
||||||
|
The usual (and in many cases recommended!) programming style in Julia is writing generic functions:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
function fsinnfrei1(x, y)
|
function fsinnfrei1(x, y)
|
||||||
return x * x * y
|
return x * x * y
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
Diese Funktion funktioniert sofort mit allen Typen, für die die verwendeten Operationen definiert sind.
|
This function works immediately with all types for which the used operations are defined.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
fsinnfrei1( Complex(2,3), 10), fsinnfrei1("Hallo", '!')
|
fsinnfrei1( Complex(2,3), 10), fsinnfrei1("Hello", '!')
|
||||||
```
|
```
|
||||||
|
|
||||||
Man kann natürlich Typ-Annotationen benutzen, um die Verwendbarkeit einzuschränken oder um unterschiedliche Methoden für unterschiedliche Typen zu implementieren:
|
|
||||||
|
One can of course use type annotations to restrict usability or to implement different methods for different types:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
function fsinnfrei2(x::Number, y::AbstractFloat)
|
function fsinnfrei2(x::Number, y::AbstractFloat)
|
||||||
@@ -600,15 +599,15 @@ end
|
|||||||
|
|
||||||
:::{.callout-important}
|
:::{.callout-important}
|
||||||
|
|
||||||
**Explizite Typannotationen sind fast immer irrelevent für die Geschwindigkeit des Codes!**
|
**Explicit type annotations are almost always irrelevant for the speed of the code!**
|
||||||
|
|
||||||
Dies ist einer der wichtigsten *selling points* von Julia.
|
This is one of the most important *selling points* of Julia.
|
||||||
|
|
||||||
Sobald eine Funktion zum ersten Mal mit bestimmten Typen aufgerufen wird, wird eine auf diese Argumenttypen spezialisierte Form der Funktion generiert und compiliert. Damit sind generische Funktionen in der Regel genauso schnell, wie die spezialisierten Funktionen, die man in anderen Sprachen schreibt.
|
Once a function is called for the first time with certain types, a specialized form of the function is generated and compiled for these argument types. Thus, generic functions are usually just as fast as the specialized functions one writes in other languages.
|
||||||
|
|
||||||
Generische Funktionen erlauben die Zusammenarbeit unterschiedlichster Pakete und eine hohe Abstraktion.
|
Generic functions enable the cooperation of the most diverse packages and a high level of abstraction.
|
||||||
|
|
||||||
Ein einfaches Beispiel: Das Paket `Measurements.jl` definiert einen neuen Datentyp `Measurement`, einen Wert mit Fehler, und die Arithmetik dieses Typs. Damit funktionieren generische Funktionen automatisch:
|
A simple example: The `Measurements.jl` package defines a new data type `Measurement`, a value with error, and the arithmetic of this type. Thus, generic functions work automatically:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| echo: false
|
#| echo: false
|
||||||
@@ -652,18 +651,18 @@ fsinnfrei1(x, y)
|
|||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Typ-Parameter in Funktionsdefinitionen: die `where`-Klausel
|
## Type Parameters in Function Definitions: the `where` Clause
|
||||||
|
|
||||||
Wir wollen eine Funktion schreiben, die für **alle komplexen Integer** (und nur diese) funktioniert, z.B. eine [in ℤ[i] mögliche Primfaktorzerlegung](https://de.wikipedia.org/wiki/Gau%C3%9Fsche_Zahl). Die Definition
|
We want to write a function that works for **all complex integers** (and only these), e.g., a [possible prime factorization in ℤ[i](https://en.wikipedia.org/wiki/Gaussian_integer). The definition
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| eval: false
|
#| eval: false
|
||||||
function isprime(x::Complex{Integer}) ... end
|
function isprime(x::Complex{Integer}) ... end
|
||||||
```
|
```
|
||||||
|
|
||||||
liefert nun nicht das Gewünschte, wie wir in @sec-invariance gesehen haben. Die Funktion würde für ein Argument vom Typ `Complex{Int64}` nicht funktionieren, da letzteres kein Subtyp von `Complex{Integer}` ist.
|
does not give the desired result, as we saw in @sec-invariance. The function would not work for an argument of type `Complex{Int64}`, since the latter is not a subtype of `Complex{Integer}`.
|
||||||
|
|
||||||
Wir müssen eine Typ-Variable einführen. Dazu dient die `where`-Klausel.
|
We must introduce a type variable. The `where` clause serves this purpose.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| eval: false
|
#| eval: false
|
||||||
@@ -672,11 +671,11 @@ function isprime(x::Complex{T}) where {T<:Integer}
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Das ist zu lesen als:
|
This is to be read as:
|
||||||
|
|
||||||
> „Das Argument x soll von einem der Typen `Complex{T}` sein, wobei die Typvariable `T` irgendein Untertyp von `Integer` sein kann.“
|
> "The argument x should be one of the types `Complex{T}`, where the type variable `T` can be any subtype of `Integer`."
|
||||||
|
|
||||||
Noch ein Beispiel:
|
Another example:
|
||||||
```{julia}
|
```{julia}
|
||||||
#| eval: false
|
#| eval: false
|
||||||
function kgV(x::Complex{T}, y::Complex{S}) where {T<:Integer, S<:Integer}
|
function kgV(x::Complex{T}, y::Complex{S}) where {T<:Integer, S<:Integer}
|
||||||
@@ -684,10 +683,11 @@ function kgV(x::Complex{T}, y::Complex{S}) where {T<:Integer, S<:Integer}
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
> Die Argumente x und y können verschiedene Typen haben und beide müssen Subtypen von `Integer` sein.
|
> The arguments x and y can have different types and both must be subtypes of `Integer`.
|
||||||
|
|
||||||
|
|
||||||
Wenn es nur eine `where`-Klausel wie im vorletzten Beispiel gibt, kann man die geschweiften Klammern weglassen und
|
If there is only one `where` clause as in the last example, one can omit the curly braces and
|
||||||
|
write
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| eval: false
|
#| eval: false
|
||||||
@@ -695,7 +695,7 @@ function isprime(x::Complex{T}) where T<:Integer
|
|||||||
...
|
...
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
schreiben. Das lässt sich noch weiter kürzen zu
|
This can still be shortened to
|
||||||
```{julia}
|
```{julia}
|
||||||
#| eval: false
|
#| eval: false
|
||||||
function isprime(x::Complex{<:Integer})
|
function isprime(x::Complex{<:Integer})
|
||||||
@@ -703,7 +703,7 @@ function isprime(x::Complex{<:Integer})
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Diese verschiedenen Varianten können verwirrend sein, aber das ist nur Syntax.
|
These different variants can be confusing, but it is only syntax.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
C1 = Complex{T} where {T<:Integer}
|
C1 = Complex{T} where {T<:Integer}
|
||||||
@@ -713,24 +713,24 @@ C3 = Complex{<:Integer}
|
|||||||
C1 == C2 == C3
|
C1 == C2 == C3
|
||||||
```
|
```
|
||||||
|
|
||||||
Kurze Syntax für einfache Fälle, ausführliche Syntax für komplexe Varianten.
|
Short syntax for simple cases, extended syntax for complex variants.
|
||||||
|
|
||||||
Als letztes sein bemerkt, dass `where T` die Kurzform von `where T<:Any` ist, also eine völlig unbeschränkte Typvariable einführt. Damit ist sowas möglich:
|
Last, it should be noted that `where T` is the short form of `where T<:Any`, which introduces a completely unrestricted type variable. Thus, something like this is possible:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
function fgl(x::T, y::T) where T
|
function fgl(x::T, y::T) where T
|
||||||
println("Glückwunsch! x und y sind vom gleichen Typ!")
|
println("Congratulations! x and y are of the same type!")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
Diese Methode erfordert, dass die Argumente genau den gleichen, aber ansonsten beliebigen Typ haben.
|
This method requires that the arguments are exactly the same type, but otherwise arbitrary.
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
fgl(33, 44)
|
fgl(33, 44)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
fgl(33, 44.0)
|
fgl(33, 44.0)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
83
index.qmd
83
index.qmd
@@ -1,12 +1,13 @@
|
|||||||
---
|
---
|
||||||
engine: julia
|
engine: julia
|
||||||
---
|
---
|
||||||
# Was ist Julia? {.unnumbered}
|
|
||||||
|
# What is Julia? {.unnumbered}
|
||||||
|
|
||||||
|
|
||||||
Julia ist eine noch recht junge für *scientific computing* konzipierte moderne Programmiersprache.
|
Julia is a relatively young, modern programming language designed for *scientific computing*.
|
||||||
|
|
||||||
Ein kleines Codebeispiel:
|
A small code example:
|
||||||
|
|
||||||
```{julia}
|
```{julia}
|
||||||
#| error: false
|
#| error: false
|
||||||
@@ -33,25 +34,24 @@ end
|
|||||||
f
|
f
|
||||||
```
|
```
|
||||||
|
|
||||||
## Geschichte {.unnumbered}
|
## History {.unnumbered}
|
||||||
|
|
||||||
- 2009 Beginn der Entwicklung am *Computer Science and Artificial
|
- 2009 Start of development at the *Computer Science and Artificial
|
||||||
Intelligence Laboratory* des MIT
|
Intelligence Laboratory* of MIT
|
||||||
- 2012 erste Release v0.1
|
- 2012 first release v0.1
|
||||||
- 2018 Version v1.0
|
- 2018 Version v1.0
|
||||||
- aktuell: v1.11.4 vom 10. März 2025
|
- current: v1.11.4 from March 10, 2025
|
||||||
|
|
||||||
Zum ersten Release 2012 haben die Schöpfer von Julia ihre Ziele und Motivation in dem Blogbeitrag [Why we created Julia](https://julialang.org/blog/2012/02/why-we-created-julia/)
|
For the first release in 2012, the creators of Julia summarized their goals and motivation in a blog post [Why we created Julia](https://julialang.org/blog/2012/02/why-we-created-julia) interestingly.
|
||||||
interessant zusammengefasst.
|
|
||||||
|
|
||||||
Für ein Bild von *Stefan Karpinski, Viral Shah, Jeff
|
For a picture of *Stefan Karpinski, Viral Shah, Jeff
|
||||||
Bezanson* und *Alan Edelman* bitte hier klicken: <https://news.mit.edu/2018/julia-language-co-creators-win-james-wilkinson-prize-numerical-software-1226>.
|
Bezanson*, and *Alan Edelman*, please click here: <https://news.mit.edu/2018/julia-language-co-creators-win-james-wilkinson-prize-numerical-software-1226>.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
:::{.content-hidden unless-format="xxx"}
|
:::{.content-hidden unless-format="xxx"}
|
||||||
|
|
||||||
Kurzfassung:
|
Short summary:
|
||||||
|
|
||||||
> We want a language that is
|
> We want a language that is
|
||||||
>
|
>
|
||||||
@@ -67,22 +67,22 @@ Bezanson* und *Alan Edelman* bitte hier klicken: <https://news.mit.edu/2018/juli
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Formale Syntax
|
Formal syntax
|
||||||
:
|
:
|
||||||
- Algorithmisches Denken
|
- Algorithmic thinking
|
||||||
- Gefühl für die Effizienz und Komplezität von Algorithmen
|
- Intuition for the efficiency and complexity of algorithms
|
||||||
- Besonderheiten der Computerarithmetik, insbes. Gleitkommazahlen
|
- Special features of computer arithmetic, particularly floating-point numbers
|
||||||
- „Ökosystem“ der Sprache:
|
- The "ecosystem" of the language
|
||||||
- die Kunst des Debugging.
|
- The art of debugging.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
## Warum Julia? {.unnumbered}
|
## Why Julia? {.unnumbered}
|
||||||
|
|
||||||
:::{.callout-tip .titlenormal icon=false}
|
:::{.callout-tip .titlenormal icon=false}
|
||||||
|
|
||||||
## aus [The fast track to Julia](https://cheatsheet.juliadocs.org/)
|
## from [The fast track to Julia](https://cheatsheet.juliadocs.org/)
|
||||||
|
|
||||||
"Julia is an open-source, multi-platform, high-level, high-performance programming language for technical computing.
|
"Julia is an open-source, multi-platform, high-level, high-performance programming language for technical computing.
|
||||||
|
|
||||||
@@ -96,39 +96,38 @@ Julia has a built-in package manager."
|
|||||||
|
|
||||||
|
|
||||||
*open source*
|
*open source*
|
||||||
: - offene Entwicklung auf [GitHub](https://github.com/JuliaLang/julia)
|
: - open development on [GitHub](https://github.com/JuliaLang/julia)
|
||||||
- Implementierungen für alle gängigen Betriebssysteme
|
- implementations for all common operating systems
|
||||||
|
|
||||||
*high-performance programming language for technical computing*
|
*high-performance programming language for technical computing*
|
||||||
: - viele Funktionen für *scientific computing* eingebaut,
|
: - many functions for *scientific computing* built-in,
|
||||||
- (bewusste) Ähnlichkeit zu Python, R und Matlab,
|
- (intentional) similarity to Python, R and Matlab,
|
||||||
- komplexe Berechnungen in wenigen Zeilen
|
- complex calculations in a few lines
|
||||||
- einfaches Interface zu anderen Sprachen wie C oder Python
|
- simple interface to other languages like C or Python
|
||||||
|
|
||||||
*a JIT compiler*
|
*a JIT compiler*
|
||||||
: - interaktives Arbeiten möglich: `read-eval-print loop (REPL)` mit
|
: - interactive work possible: `read-eval-print loop (REPL)` with
|
||||||
- just-in-time (JIT) Compilation
|
- just-in-time (JIT) compilation
|
||||||
- dadurch Laufzeiten vergleichbar mit statischen Sprachen wie C/C++, Fortran oder Rust
|
- thereby runtimes comparable to static languages like C/C++, Fortran or Rust
|
||||||
|
|
||||||
*a built-in package manager*
|
*a built-in package manager*
|
||||||
: - riesiges *ecosystem* an einfach installierbaren Paketen, z.B.
|
: - huge *ecosystem* of easily installable packages, e.g.
|
||||||
- [Mathematische Optimierung](https://jump.dev/)
|
- [Mathematical Optimization](https://jump.dev/)
|
||||||
- [Machine Learning](https://fluxml.ai/)
|
- [Machine Learning](https://fluxml.ai/)
|
||||||
- [Data Visualization](https://docs.makie.org/stable/)
|
- [Data Visualization](https://docs.makie.org/stable/)
|
||||||
- [Differentialgleichungen](https://docs.sciml.ai/DiffEqDocs/stable/)
|
- [Differential Equations](https://docs.sciml.ai/DiffEqDocs/stable/)
|
||||||
- [Mathematische Modellierung](https://sciml.ai/)
|
- [Mathematical Modeling](https://sciml.ai/)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Eine kleine Auswahl an Online-Material zu Julia {.unnumbered}
|
## A Small Selection of Online Materials on Julia {.unnumbered}
|
||||||
|
|
||||||
- [Dokumentation](https://docs.julialang.org/en/v1/) - die offizielle Dokumentation
|
- [Documentation](https://docs.julialang.org/en/v1/) - the official documentation
|
||||||
- [Cheat Sheet](https://cheatsheet.juliadocs.org/) - "a quick & dirty overview"
|
- [Cheat Sheet](https://cheatsheet.juliadocs.org/) - "a quick & dirty overview"
|
||||||
- [Introducing Julia](https://en.wikibooks.org/wiki/Introducing_Julia)-- ein WikiBook
|
- [Introducing Julia](https://en.wikibooks.org/wiki/Introducing_Julia)-- a WikiBook
|
||||||
- [The Julia Express](http://bogumilkaminski.pl/files/julia_express.pdf) - Kurzfassung, Julia auf 16 Seiten
|
- [The Julia Express](http://bogumilkaminski.pl/files/julia_express.pdf) - short version, Julia in 16 pages
|
||||||
- [Think Julia](https://benlauwens.github.io/ThinkJulia.jl/latest/book.html) - Einführung in die Programmierung mit Julia als Sprache
|
- [Think Julia](https://benlauwens.github.io/ThinkJulia.jl/latest/book.html) - introduction to programming with Julia as a language
|
||||||
- Das [Julia Forum](https://discourse.julialang.org/)
|
- The [Julia Forum](https://discourse.julialang.org/)
|
||||||
- Was fürs Auge: [Beispiele zum Julia-Grafikpaket `Makie`](https://beautiful.makie.org/)
|
- For the eyes: [Examples for the Julia graphics package `Makie`](https://beautiful.makie.org/)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user