Compare commits
2 Commits
english
...
origquarto
| Author | SHA1 | Date | |
|---|---|---|---|
| b4ee0760e3 | |||
| 9b4e271fdf |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -31,4 +31,3 @@ xelatex.py
|
||||
/.luarc.json
|
||||
nb/*.qmd
|
||||
nb/*.ipynb
|
||||
.cache/
|
||||
|
||||
216
AGENTS.md
216
AGENTS.md
@@ -1,216 +0,0 @@
|
||||
# AGENTS.md - Guidelines for Agentic Coding in JuliaKurs23
|
||||
|
||||
This is a **Quarto-based Julia programming course book** in English. The book teaches scientific computing with Julia using interactive Jupyter notebooks rendered with Quarto.
|
||||
|
||||
**Translation Note:** The book was originally written in German and has been translated to professional, concise English suitable for mathematicians. All code, LaTeX equations, and formatting have been preserved during translation. Only text descriptions and code comments were translated to English.
|
||||
|
||||
## Project Overview
|
||||
|
||||
- **Type**: Educational book website/PDF generated from Quarto (.qmd) files
|
||||
- **Language**: English (all content)
|
||||
- **Build System**: Quarto with Julia Jupyter kernel
|
||||
- **Julia Version**: 1.10
|
||||
- **Output**: HTML website and PDF
|
||||
- **License**: CC BY-NC-SA 4.0
|
||||
|
||||
---
|
||||
|
||||
## Build Commands
|
||||
|
||||
### Build the Book
|
||||
|
||||
```bash
|
||||
# Build HTML website
|
||||
quarto render
|
||||
|
||||
# Build only HTML
|
||||
quarto render --to julia-color-html
|
||||
|
||||
# Build only PDF
|
||||
quarto render --to julia-color-pdf
|
||||
|
||||
# Preview locally
|
||||
quarto preview
|
||||
```
|
||||
|
||||
### Development Commands
|
||||
|
||||
```bash
|
||||
# Render a specific chapter
|
||||
quarto render chapters/first_contact.qmd
|
||||
|
||||
# Build with specific output directory
|
||||
quarto render --output-dir _book
|
||||
|
||||
# Run in daemon mode (faster rebuilds)
|
||||
quarto render --execute-daemon 3600
|
||||
```
|
||||
|
||||
### Deployment
|
||||
|
||||
```bash
|
||||
# Deploy to web server (rsync _book/)
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
### Testing Individual Code Blocks
|
||||
|
||||
Quarto executes Julia code in Jupyter notebooks. To test individual code blocks:
|
||||
|
||||
1. Open the `.qmd` file in VS Code with Julia extension
|
||||
2. Use Julia REPL to execute code blocks interactively
|
||||
3. Or use IJulia/Jupyter to run specific cells
|
||||
|
||||
```julia
|
||||
# In Julia REPL, test code from a cell:
|
||||
include("path/to/notebook.jl")
|
||||
```
|
||||
|
||||
### Julia Package Management
|
||||
|
||||
```bash
|
||||
# Install dependencies (from Project.toml)
|
||||
julia -e 'using Pkg; Pkg.instantiate()'
|
||||
|
||||
# Add a new package
|
||||
julia -e 'using Pkg; Pkg.add("PackageName")'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
### General Structure (.qmd files)
|
||||
|
||||
- All `.qmd` files start with YAML front matter specifying `engine: julia`
|
||||
- Code blocks use triple backticks with `julia` language identifier
|
||||
- Use Quarto cell options in comments like `#| option: value`
|
||||
- Common options: `eval:`, `echo:`, `output:`, `error:`, `hide_line:`
|
||||
|
||||
Example:
|
||||
```markdown
|
||||
---
|
||||
engine: julia
|
||||
---
|
||||
|
||||
```{julia}
|
||||
#| eval: true
|
||||
#| echo: true
|
||||
#| output: true
|
||||
using Statistics
|
||||
mean([1, 2, 3])
|
||||
```
|
||||
```
|
||||
|
||||
### Julia Code Conventions
|
||||
|
||||
#### Imports
|
||||
|
||||
```julia
|
||||
# Prefer using for packages with many exports
|
||||
using Statistics, LinearAlgebra, Plots
|
||||
|
||||
# Use import when you need specific exports or module name
|
||||
import Base: convert, show
|
||||
```
|
||||
|
||||
#### Naming Conventions
|
||||
|
||||
- **Variables/functions**: lowercase with underscores (`my_variable`, `calculate_mean`)
|
||||
- **Types**: CamelCase (`MyType`, `AbstractMatrix`)
|
||||
- **Constants**: ALL_UPPERCASE (`MAX_ITER`, `PI`)
|
||||
- **Modules**: PascalCase (`Statistics`, `LinearAlgebra`)
|
||||
|
||||
#### Formatting
|
||||
|
||||
- Use 4 spaces for indentation (Julia default)
|
||||
- Limit lines to ~92 characters when practical
|
||||
- Use spaces around operators: `a + b`, not `a+b`
|
||||
- No spaces before commas: `f(a, b)`, not `f(a , b)`
|
||||
|
||||
#### Types
|
||||
|
||||
- Use explicit types when needed for performance or clarity
|
||||
- Parameterize types when useful: `Vector{Float64}`, `Dict{Symbol, Int}`
|
||||
- Prefer concrete types for fields in structs
|
||||
|
||||
#### Error Handling
|
||||
|
||||
```julia
|
||||
# Use try-catch for expected errors
|
||||
try
|
||||
parse(Int, user_input)
|
||||
catch e
|
||||
println("Invalid input: $e")
|
||||
end
|
||||
|
||||
# Use assertions for internal checks
|
||||
@assert x >= 0 "x must be non-negative"
|
||||
```
|
||||
|
||||
### Quarto-Specific Guidelines
|
||||
|
||||
#### Cell Options
|
||||
|
||||
Use these in code block comments:
|
||||
- `#| eval: true/false` - whether to execute
|
||||
- `#| echo: true/false` - show source code
|
||||
- `#| output: true/false` - show output
|
||||
- `#| error: true/false` - show errors
|
||||
- `#| hide_line: true` - hide this line from output
|
||||
- `#| fig-cap: "Caption"` - figure caption
|
||||
|
||||
#### Embedding Notebooks
|
||||
|
||||
```markdown
|
||||
{{< embed notebooks/nb-types.ipynb#nb1 >}}
|
||||
```
|
||||
|
||||
#### Conditional Content
|
||||
|
||||
```markdown
|
||||
::: {.content-visible when-format="html"}
|
||||
... HTML only content
|
||||
:::
|
||||
|
||||
::: {.content-visible when-format="pdf"}
|
||||
... PDF only content
|
||||
:::
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File Organization
|
||||
|
||||
```
|
||||
/
|
||||
├── _quarto.yml # Quarto configuration
|
||||
├── Project.toml # Julia dependencies
|
||||
├── index.qmd # Book index
|
||||
├── chapters/ # Chapter .qmd files
|
||||
├── notebooks/ # Jupyter notebooks (.ipynb)
|
||||
├── css/ # Custom styles
|
||||
├── images/ # Images and logos
|
||||
├── fonts/ # Custom fonts
|
||||
└── _book/ # Built output (generated)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## VS Code Settings
|
||||
|
||||
The project uses VS Code with:
|
||||
- Julia environment: `/home/hellmund/Julia/23`
|
||||
- LTEx for spell checking (disabled for code blocks)
|
||||
- Auto-exclude: `.ipynb`, `.md`, `.quarto_ipynb` files
|
||||
|
||||
---
|
||||
|
||||
## Important Notes
|
||||
|
||||
1. **All content is in English** - Comments, documentation, variable names in examples should be English (professional, concise, suitable for mathematicians)
|
||||
2. **Code comments were translated** - German text and code comments were translated to English; all Julia code, LaTeX equations, and Quarto formatting were preserved
|
||||
3. **Code execution is cached** - Use `#| eval: true` to execute cells
|
||||
4. **ansi color codes** - The `julia-color` extension handles ANSI escape sequences in output
|
||||
5. **Freeze mode** - Set to `auto` in _quarto.yml; use `freeze: false` to re-run all code
|
||||
6. **Keep intermediate files** - `keep-ipynb`, `keep-tex`, `keep-md` are all true
|
||||
2339
Manifest.toml
2339
Manifest.toml
File diff suppressed because it is too large
Load Diff
16
Notes.txt
16
Notes.txt
@@ -1,16 +0,0 @@
|
||||
|
||||
|
||||
SoSe25:
|
||||
|
||||
14_Plot.html: die beiden Zeilen mit require.js, define jquery entfernen
|
||||
für Plots/plotlyjs
|
||||
|
||||
|
||||
Book25: Versuch ohne quarto-patch:
|
||||
LaTeX: ansi in stdout not supported, Julia errors werden total
|
||||
zerschossen
|
||||
mit stdout-cell-support koennte ein eigener laufilter gehen, wenn der
|
||||
vor dem quarto-latex-filter gerufen wird
|
||||
|
||||
|
||||
|
||||
23
Project.toml
23
Project.toml
@@ -1,23 +0,0 @@
|
||||
[deps]
|
||||
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
|
||||
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
||||
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
|
||||
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
|
||||
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
|
||||
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
|
||||
HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
|
||||
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
|
||||
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
|
||||
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
||||
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
|
||||
Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7"
|
||||
PlotThemes = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
|
||||
PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a"
|
||||
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
||||
Primes = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae"
|
||||
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
|
||||
RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b"
|
||||
StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"
|
||||
TreeView = "39424ebd-4cf3-5550-a685-96706a953f40"
|
||||
@@ -1,16 +1,12 @@
|
||||
title: Julia-color
|
||||
author: Meik Hellmund
|
||||
version: 1.0.0
|
||||
quarto-required: ">=99.9.0"
|
||||
quarto-required: ">=1.6.0"
|
||||
contributes:
|
||||
formats:
|
||||
common:
|
||||
filters:
|
||||
- "ansi2htmltex.lua"
|
||||
html:
|
||||
monofont: "JuliaMono"
|
||||
css:
|
||||
- "resources/css/ansicolor.css"
|
||||
- "resources/css/juliamono.css"
|
||||
pdf:
|
||||
include-in-header:
|
||||
|
||||
@@ -16,29 +16,28 @@
|
||||
\DeclareRobustCommand{\lseries}{\fontseries{l}\selectfont}
|
||||
\DeclareTextFontCommand{\textlight}{\lseries}
|
||||
|
||||
|
||||
\DefineVerbatimEnvironment{OutputCell}{Verbatim}%
|
||||
{xleftmargin=1.5em}
|
||||
\DefineVerbatimEnvironment{AnsiOutputCell}{Verbatim}%
|
||||
{commandchars=\\\{\}, xleftmargin=1.5em}
|
||||
\DefineVerbatimEnvironment{StderrOutputCell}{Verbatim}%
|
||||
{commandchars=\\\{\}, xleftmargin=1.5em,frame=single,rulecolor=\color{red}}
|
||||
|
||||
\definecolor{ansi-black}{HTML}{3E424D}
|
||||
\definecolor{ansi-black-intense}{HTML}{282C36}
|
||||
\definecolor{ansi-red}{HTML}{E75C58}
|
||||
\definecolor{ansi-red-intense}{HTML}{B22B31}
|
||||
\definecolor{ansi-green}{HTML}{00A250}
|
||||
\definecolor{ansi-green-intense}{HTML}{007427}
|
||||
\definecolor{ansi-yellow}{HTML}{DDB62B}
|
||||
\definecolor{ansi-yellow-intense}{HTML}{B27D12}
|
||||
\definecolor{ansi-blue}{HTML}{208FFB}
|
||||
\definecolor{ansi-blue-intense}{HTML}{0065CA}
|
||||
\definecolor{ansi-magenta}{HTML}{D160C4}
|
||||
\definecolor{ansi-magenta-intense}{HTML}{A03196}
|
||||
\definecolor{ansi-cyan}{HTML}{60C6C8}
|
||||
\definecolor{ansi-cyan-intense}{HTML}{258F8F}
|
||||
\definecolor{ansi-white}{HTML}{C5C1B4}
|
||||
\definecolor{ansi-white-intense}{HTML}{A1A6B2}
|
||||
\definecolor{ansi-default-inverse-fg}{HTML}{FFFFFF}
|
||||
\definecolor{ansi-default-inverse-bg}{HTML}{000000}
|
||||
%\DefineVerbatimEnvironment{OutputCell}{Verbatim}%
|
||||
% {xleftmargin=1.5em}
|
||||
%\DefineVerbatimEnvironment{AnsiOutputCell}{Verbatim}%
|
||||
% {commandchars=\\\{\}, xleftmargin=1.5em}
|
||||
%\DefineVerbatimEnvironment{StderrOutputCell}{Verbatim}%
|
||||
% {commandchars=\\\{\}, xleftmargin=1.5em,frame=single,rulecolor=\color{red}}
|
||||
%
|
||||
%\definecolor{ansi-black}{HTML}{3E424D}
|
||||
%\definecolor{ansi-black-intense}{HTML}{282C36}
|
||||
%\definecolor{ansi-red}{HTML}{E75C58}
|
||||
%\definecolor{ansi-red-intense}{HTML}{B22B31}
|
||||
%\definecolor{ansi-green}{HTML}{00A250}
|
||||
%\definecolor{ansi-green-intense}{HTML}{007427}
|
||||
%\definecolor{ansi-yellow}{HTML}{DDB62B}
|
||||
%\definecolor{ansi-yellow-intense}{HTML}{B27D12}
|
||||
%\definecolor{ansi-blue}{HTML}{208FFB}
|
||||
%\definecolor{ansi-blue-intense}{HTML}{0065CA}
|
||||
%\definecolor{ansi-magenta}{HTML}{D160C4}
|
||||
%\definecolor{ansi-magenta-intense}{HTML}{A03196}
|
||||
%\definecolor{ansi-cyan}{HTML}{60C6C8}
|
||||
%\definecolor{ansi-cyan-intense}{HTML}{258F8F}
|
||||
%\definecolor{ansi-white}{HTML}{C5C1B4}
|
||||
%\definecolor{ansi-white-intense}{HTML}{A1A6B2}
|
||||
%\definecolor{ansi-default-inverse-fg}{HTML}{FFFFFF}
|
||||
%\definecolor{ansi-default-inverse-bg}{HTML}{000000}
|
||||
|
||||
42
_quarto.yml
42
_quarto.yml
@@ -40,22 +40,22 @@ book:
|
||||
|
||||
chapters:
|
||||
- index.qmd
|
||||
- chapters/entwicklungsumgebungen.qmd
|
||||
- chapters/first_contact.qmd
|
||||
- chapters/Erste_Bsp.qmd
|
||||
- chapters/syntax.qmd
|
||||
- chapters/5_TricksHelp.qmd
|
||||
#- chapters/entwicklungsumgebungen.qmd
|
||||
#- chapters/first_contact.qmd
|
||||
#- chapters/Erste_Bsp.qmd
|
||||
#- chapters/syntax.qmd
|
||||
#- chapters/5_TricksHelp.qmd
|
||||
- chapters/numerictypes.qmd
|
||||
- chapters/Pi2.qmd
|
||||
- chapters/types.qmd
|
||||
- chapters/pcomplex.qmd
|
||||
- chapters/9_functs.qmd
|
||||
- chapters/6_ArraysEtcP1.qmd
|
||||
- chapters/7_ArraysP2.qmd
|
||||
- chapters/11_LinAlg.qmd
|
||||
- chapters/10_Strings.qmd
|
||||
- chapters/13_IO.qmd
|
||||
- chapters/14_Plot.qmd
|
||||
#- chapters/Pi2.qmd
|
||||
#- chapters/types.qmd
|
||||
#- chapters/pcomplex.qmd
|
||||
#- chapters/9_functs.qmd
|
||||
#- chapters/6_ArraysEtcP1.qmd
|
||||
#- chapters/7_ArraysP2.qmd
|
||||
#- chapters/11_LinAlg.qmd
|
||||
#- chapters/10_Strings.qmd
|
||||
#- chapters/13_IO.qmd
|
||||
#- chapters/14_Plot.qmd
|
||||
# - chapters/makie.qmd
|
||||
|
||||
|
||||
@@ -66,7 +66,8 @@ format:
|
||||
dark: [superhero, css/dark.scss]
|
||||
css:
|
||||
- css/styles.css
|
||||
- css/roboto-condensed.css
|
||||
- css/roboto-condensed.css
|
||||
|
||||
highlight-style: github # arrow ?????
|
||||
mainfont: "Roboto Condensed" # Ubuntu # "Atkinson Hyperlegible" # Verdana #Quicksand
|
||||
toc: true # change for Vorlesung
|
||||
@@ -104,7 +105,10 @@ format:
|
||||
code-overflow: wrap
|
||||
include-in-header:
|
||||
- file: macros.tex
|
||||
|
||||
|
||||
typst:
|
||||
toc: true
|
||||
|
||||
latex-auto-install: false
|
||||
|
||||
execute:
|
||||
@@ -116,13 +120,13 @@ execute:
|
||||
eval: true
|
||||
freeze: auto
|
||||
daemon: 3600
|
||||
preserve-ansi: true
|
||||
#preserve-ansi: true
|
||||
|
||||
keep-ipynb: true
|
||||
keep-tex: true
|
||||
keep-md: true
|
||||
|
||||
jupyter: julia-1.10
|
||||
#jupyter: julia-1.10
|
||||
|
||||
filters:
|
||||
- code-visibility
|
||||
|
||||
@@ -11,97 +11,96 @@ import QuartoNotebookWorker
|
||||
Base.stdout = QuartoNotebookWorker.with_context(stdout)
|
||||
```
|
||||
|
||||
# Characters, Strings, and Unicode
|
||||
# Zeichen, Strings und Unicode
|
||||
|
||||
## Character Encodings (Early History)
|
||||
## Zeichencodierungen (Frühgeschichte)
|
||||
|
||||
There were - depending on manufacturer, country, programming language, operating system, etc. - a large variety of encodings.
|
||||
Es gab - abhängig von Hersteller, Land, Programmiersprache, Betriebsssystem,... - eine große Vielzahl von Codierungen.
|
||||
|
||||
Still relevant today:
|
||||
Bis heute relevant sind:
|
||||
|
||||
|
||||
### ASCII
|
||||
The _American Standard Code for Information Interchange_ was published as a standard in the USA in 1963.
|
||||
Der _American Standard Code for Information Interchange_ wurde 1963 in den USA als Standard veröffentlicht.
|
||||
|
||||
- It defines $2^7=128$ characters, namely:
|
||||
- 33 control characters, such as `newline`, `escape`, `end of transmission/file`, `delete`
|
||||
- 95 graphically printable characters:
|
||||
- 52 Latin letters `a-z, A-Z`
|
||||
- 10 digits `0-9`
|
||||
- 7 punctuation marks `.,:;?!"`
|
||||
- 1 space ` `
|
||||
- 6 parentheses `[{()}]`
|
||||
- 7 mathematical operations `+-*/<>=`
|
||||
- 12 special characters ``` #$%&'\^_|~`@ ```
|
||||
- Er definiert $2^7=128$ Zeichen, und zwar:
|
||||
- 33 Steuerzeichen, wie `newline`, `escape`, `end of transmission/file`, `delete`
|
||||
- 95 graphisch darstellbare Zeichen:
|
||||
- 52 lateinische Buchstaben `a-z, A-Z`
|
||||
- 10 Ziffern `0-9`
|
||||
- 7 Satzzeichen `.,:;?!"`
|
||||
- 1 Leerzeichen ` `
|
||||
- 6 Klammern `[{()}]`
|
||||
- 7 mathematische Operationen `+-*/<>=`
|
||||
- 12 Sonderzeichen ``` #$%&'\^_|~`@ ```
|
||||
|
||||
- ASCII is still the "lowest common denominator" in the encoding chaos.
|
||||
- The first 128 Unicode characters are identical to ASCII.
|
||||
- ASCII ist heute noch der "kleinste gemeinsame Nenner" im Codierungs-Chaos.
|
||||
- Die ersten 128 Unicode-Zeichen sind identisch mit ASCII.
|
||||
|
||||
### ISO 8859 Character Sets
|
||||
### ISO 8859-Zeichensätze
|
||||
|
||||
- ASCII uses only 7 bits.
|
||||
- In a byte, one can fit another 128 characters by setting the 8th bit.
|
||||
- In 1987/88, various 1-byte encodings were standardized in ISO 8859, all ASCII-compatible, including:
|
||||
- ASCII nutzt nur 7 Bits.
|
||||
- In einem Byte kann man durch Setzen des 8. Bits weitere 128 Zeichen unterbringen.
|
||||
- 1987/88 wurden im ISO 8859-Standard verschiedene 1-Byte-Codierungen festgelegt, die alle ASCII-kompatibel sind, darunter:
|
||||
|
||||
:::{.narrow}
|
||||
|Encoding | Region | Languages|
|
||||
|Codierung | Region | Sprachen|
|
||||
|:-----------|:----------|:-------|
|
||||
|ISO 8859-1 (Latin-1) | Western Europe | German, French,..., Icelandic
|
||||
|ISO 8859-2 (Latin-2) | Eastern Europe | Slavic languages with Latin script
|
||||
|ISO 8859-3 (Latin-3) | Southern Europe | Turkish, Maltese,...
|
||||
|ISO 8859-4 (Latin-4) | Northern Europe | Estonian, Latvian, Lithuanian, Greenlandic, Sami
|
||||
|ISO 8859-5 (Latin/Cyrillic) | Eastern Europe | Slavic languages with Cyrillic script
|
||||
|ISO 8859-1 (Latin-1) | Westeuropa | Deutsch, Französisch,...,Isländisch
|
||||
|ISO 8859-2 (Latin-2) | Osteuropa | slawische Sprachen mit lateinischer Schrift
|
||||
|ISO 8859-3 (Latin-3) | Südeuropa | Türkisch, Maltesisch,...
|
||||
|ISO 8859-4 (Latin-4) | Nordeuropa | Estnisch, Lettisch, Litauisch, Grönländisch, Sami
|
||||
|ISO 8859-5 (Latin/Cyrillic) | Osteuropa | slawische Sprachen mit kyrillischer Schrift
|
||||
|ISO 8859-6 (Latin/Arabic) | |
|
||||
|ISO 8859-7 (Latin/Greek) | |
|
||||
|...| |
|
||||
|ISO 8859-15 (Latin-9)| | 1999: Revision of Latin-1: now including Euro sign
|
||||
|ISO 8859-15 (Latin-9)| | 1999: Revision von Latin-1: jetzt u.a. mit Euro-Zeichen
|
||||
|
||||
:::
|
||||
|
||||
|
||||
## Unicode
|
||||
|
||||
The goal of the Unicode Consortium is a uniform encoding for all scripts of the world.
|
||||
Das Ziel des Unicode-Consortiums ist eine einheitliche Codierung für alle Schriften der Welt.
|
||||
|
||||
- Unicode version 1 was published in 1991
|
||||
- Unicode version 15.1 was published in 2023 with 149,813 characters, including:
|
||||
- 161 scripts
|
||||
- mathematical and technical symbols
|
||||
- Emojis and other symbols, control and formatting characters
|
||||
- Over 90,000 characters are assigned to the CJK scripts (Chinese/Japanese/Korean)
|
||||
- Unicode Version 1 erschien 1991
|
||||
- Unicode Version 15.1 erschien 2023 mit 149 813 Zeichen, darunter:
|
||||
- 161 Schriften
|
||||
- mathematische und technische Symbole
|
||||
- Emojis und andere Symbole, Steuer- und Formatierungszeichen
|
||||
- davon entfallen über 90 000 Zeichen auf die CJK-Schriften (Chinesisch/Japanisch/Koreanisch)
|
||||
|
||||
|
||||
### Technische Details
|
||||
|
||||
- Jedem Zeichen wird ein `codepoint` zugeordnet. Das ist einfach eine fortlaufende Nummer.
|
||||
- Diese Nummer wird hexadezimal notiert
|
||||
- entweder 4-stellig als `U+XXXX` (0-te Ebene)
|
||||
- oder 6-stellig als `U+XXXXXX` (weitere Ebenen)
|
||||
- Jede Ebene geht von `U+XY0000` bis `U+XYFFFF`, kann also $2^{16}=65\;534$ Zeichen enthalten.
|
||||
- Vorgesehen sind bisher 17 Ebenen `XY=00` bis `XY=10`, also der Wertebereich von `U+0000` bis `U+10FFFF`.
|
||||
- Damit sind maximal 21 Bits pro Zeichen nötig.
|
||||
- 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.
|
||||
- Bisher wurden nur Codepoints aus den Ebenen
|
||||
- Ebene 0 = BMP _Basic Multilingual Plane_ `U+0000 - U+FFFF`,
|
||||
- Ebene 1 = SMP _Supplementary Multilingual Plane_ `U+010000 - U+01FFFF`,
|
||||
- Ebene 2 = SIP _Supplementary Ideographic Plane_ `U+020000 - U+02FFFF`,
|
||||
- Ebene 3 = TIP _Tertiary Ideographic Plane_ `U+030000 - U+03FFFF` und
|
||||
- Ebene 14 = SSP _Supplementary Special-purpose Plane_ `U+0E0000 - U+0EFFFF`
|
||||
vergeben.
|
||||
- `U+0000` bis `U+007F` ist identisch mit ASCII
|
||||
- `U+0000` bis `U+00FF` ist identisch mit ISO 8859-1 (Latin-1)
|
||||
|
||||
### Technical Details
|
||||
### Eigenschaften von Unicode-Zeichen
|
||||
|
||||
- Each character is assigned a `codepoint`. This is simply a sequential number.
|
||||
- This number is written hexadecimally
|
||||
- either 4-digit as `U+XXXX` (0th plane)
|
||||
- or 6-digit as `U+XXXXXX` (further planes)
|
||||
- Each plane ranges from `U+XY0000` to `U+XYFFFF`, thus can contain $2^{16}=65\;534$ characters.
|
||||
- 17 planes `XY=00` to `XY=10` are provided so far, thus the value range from `U+0000` to `U+10FFFF`.
|
||||
- Thus, a maximum of 21 bits per character are needed.
|
||||
- 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.
|
||||
- So far, codepoints from the planes have been assigned only from
|
||||
- Plane 0 = BMP _Basic Multilingual Plane_ `U+0000 - U+FFFF`,
|
||||
- Plane 1 = SMP _Supplementary Multilingual Plane_ `U+010000 - U+01FFFF`,
|
||||
- Plane 2 = SIP _Supplementary Ideographic Plane_ `U+020000 - U+02FFFF`,
|
||||
- Plane 3 = TIP _Tertiary Ideographic Plane_ `U+030000 - U+03FFFF` and
|
||||
- Plane 14 = SSP _Supplementary Special-purpose Plane_ `U+0E0000 - U+0EFFFF`
|
||||
have been assigned.
|
||||
- `U+0000` to `U+007F` is identical to ASCII
|
||||
- `U+0000` to `U+00FF` is identical to ISO 8859-1 (Latin-1)
|
||||
Im Standard wird jedes Zeichen beschrieben duch
|
||||
|
||||
### Properties of Unicode Characters
|
||||
- seinen Codepoint (Nummer)
|
||||
- einen Namen (welcher nur aus ASCII-Großbuchstaben, Ziffern und Minuszeichen besteht) und
|
||||
- verschiedene Attributen wie
|
||||
- Laufrichtung der Schrift
|
||||
- Kategorie: Großbuchstabe, Kleinbuchstabe, modifizierender Buchstabe, Ziffer, Satzzeichen, Symbol, Seperator,....
|
||||
|
||||
In the standard, each character is described by
|
||||
|
||||
- its codepoint (number)
|
||||
- a name (which consists only of ASCII uppercase letters, digits, and hyphens) and
|
||||
- various attributes such as
|
||||
- script direction
|
||||
- category: uppercase letter, lowercase letter, modifier letter, digit, punctuation, symbol, separator,....
|
||||
|
||||
In the Unicode standard, this looks like this (simplified, only codepoint and name):
|
||||
Im Unicode-Standard sieht das dann so aus (zur Vereinfachung nur Codepoint und Name):
|
||||
```
|
||||
...
|
||||
U+0041 LATIN CAPITAL LETTER A
|
||||
@@ -119,29 +118,29 @@ U+21B4 RIGHTWARDS ARROW WITH CORNER DOWNWARDS
|
||||
...
|
||||
```
|
||||
|
||||
What does 'RIGHTWARDS ARROW WITH CORNER DOWNWARDS' look like?
|
||||
Wie sieht 'RIGHTWARDS ARROW WITH CORNER DOWNWARDS' aus?
|
||||
|
||||
Julia uses `\U...` for input of Unicode codepoints.
|
||||
Julia verwendet `\U...` zur Eingabe von Unicode Codepoints.
|
||||
|
||||
```{julia}
|
||||
'\U21b4'
|
||||
```
|
||||
|
||||
|
||||
### A Selection of Scripts
|
||||
### Eine Auswahl an Schriften
|
||||
|
||||
::: {.content-visible when-format="html"}
|
||||
|
||||
:::{.callout-note}
|
||||
If individual characters or scripts are not displayable in your browser, you must install appropriate
|
||||
fonts on your computer.
|
||||
Falls im Folgenden einzelne Zeichen oder Schriften in Ihrem Browser nicht darstellbar sind, müssen Sie geeignete
|
||||
Fonts auf Ihrem Rechner installieren.
|
||||
|
||||
Alternatively, you can use the PDF version of this page. There, all fonts are embedded.
|
||||
Alternativ können Sie die PDF-Version dieser Seite verwenden. Dort sind alle Fonts eingebunden.
|
||||
:::
|
||||
|
||||
:::
|
||||
|
||||
A small helper function:
|
||||
Eine kleine Hilfsfunktion:
|
||||
```{julia}
|
||||
function printuc(c, n)
|
||||
for i in 0:n-1
|
||||
@@ -150,15 +149,14 @@ function printuc(c, n)
|
||||
end
|
||||
```
|
||||
|
||||
__Cyrillic__
|
||||
__Kyrillisch__
|
||||
|
||||
|
||||
```{julia}
|
||||
printuc('\U0400', 100)
|
||||
```
|
||||
|
||||
__Tamil__
|
||||
|
||||
__Tamilisch__
|
||||
|
||||
:::{.cellmerge}
|
||||
```{julia}
|
||||
@@ -179,21 +177,21 @@ printuc('\U0be7',20)
|
||||
|
||||
:::
|
||||
|
||||
__Chess__
|
||||
__Schach__
|
||||
|
||||
|
||||
```{julia}
|
||||
printuc('\U2654', 12)
|
||||
```
|
||||
|
||||
__Mathematical Operators__
|
||||
__Mathematische Operatoren__
|
||||
|
||||
|
||||
```{julia}
|
||||
printuc('\U2200', 255)
|
||||
```
|
||||
|
||||
__Runes__
|
||||
__Runen__
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -202,11 +200,12 @@ printuc('\U16a0', 40)
|
||||
|
||||
:::{.cellmerge}
|
||||
|
||||
__Phaistos Disc__
|
||||
__Scheibe (Diskus) von Phaistos__
|
||||
|
||||
- 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}
|
||||
@@ -227,54 +226,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_ define how a sequence of codepoints is represented as a sequence of bytes.
|
||||
_Unicode transformation formats_ legen fest, wie eine Folge von Codepoints als eine Folge von Bytes dargestellt wird.
|
||||
|
||||
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?
|
||||
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?
|
||||
|
||||
- __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.
|
||||
- In __UTF-16__, a codepoint is represented either with 2 bytes or with 4 bytes.
|
||||
- In __UTF-8__, a codepoint is represented with 1, 2, 3, or 4 bytes.
|
||||
- __UTF-8__ is the format with the highest prevalence. Julia also uses it.
|
||||
- __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.
|
||||
- Bei __UTF-16__ wird ein Codepoint entweder mit 2 Bytes oder mit 4 Bytes dargestellt.
|
||||
- Bei __UTF-8__ wird ein Codepoint mit 1,2,3 oder 4 Bytes dargestellt.
|
||||
- __UTF-8__ ist das Format mit der höchsten Verbreitung. Es wird auch von Julia verwendet.
|
||||
|
||||
|
||||
### UTF-8
|
||||
|
||||
- For each codepoint, 1, 2, 3, or 4 full bytes are used.
|
||||
- Für jeden Codepoint werden 1, 2, 3 oder 4 volle Bytes verwendet.
|
||||
|
||||
- With variable-length encoding, one must be able to recognize which byte sequences belong together:
|
||||
- A byte of the form 0xxxxxxx represents an ASCII codepoint of length 1.
|
||||
- A byte of the form 110xxxxx starts a 2-byte code.
|
||||
- A byte of the form 1110xxxx starts a 3-byte code.
|
||||
- A byte of the form 11110xxx starts a 4-byte code.
|
||||
- All further bytes of a 2-, 3-, or 4-byte code have the form 10xxxxxx.
|
||||
- Bei einer Codierung mit variabler Länge muss man erkennen können, welche Bytefolgen zusammengehören:
|
||||
- Ein Byte der Form 0xxxxxxx steht für einen ASCII-Codepoint der Länge 1.
|
||||
- Ein Byte der Form 110xxxxx startet einen 2-Byte-Code.
|
||||
- Ein Byte der Form 1110xxxx startet einen 3-Byte-Code.
|
||||
- Ein Byte der Form 11110xxx startet einen 4-Byte-Code.
|
||||
- Alle weiteren Bytes eines 2-,3- oder 4-Byte-Codes haben die Form 10xxxxxx.
|
||||
|
||||
- Thus, the space available for the codepoint (number of x):
|
||||
- One-byte code: 7 bits
|
||||
- Two-byte code: 5 + 6 = 11 bits
|
||||
- Three-byte code: 4 + 6 + 6 = 16 bits
|
||||
- Four-byte code: 3 + 6 + 6 + 6 = 21 bits
|
||||
- Damit ist der Platz, der für den Codepoint zur Verfügung steht (Anzahl der x):
|
||||
- Ein-Byte-Code: 7 Bits
|
||||
- Zwei-Byte-Code: 5 + 6 = 11 Bits
|
||||
- Drei-Byte-Code: 4 + 6 + 6 = 16 Bits
|
||||
- Vier-Byte-Code: 3 + 6 + 6 + 6 = 21 Bits
|
||||
|
||||
- Thus, every ASCII text is automatically also a correctly encoded UTF-8 text.
|
||||
- Damit ist jeder ASCII-Text automatisch auch ein korrekt codierter UTF-8-Text.
|
||||
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
|
||||
## Zeichen und Zeichenketten in Julia
|
||||
|
||||
### Zeichen: `Char`
|
||||
|
||||
Der Datentyp `Char` kodiert ein einzelnes Unicode-Zeichen.
|
||||
|
||||
- Julia verwendet dafür einfache Anführungszeichen: `'a'`.
|
||||
- Ein `Char` belegt 4 Bytes Speicher und
|
||||
- repräsentiert einen Unicode-Codepoint.
|
||||
- `Char`s können von/zu `UInt`s umgewandelt werden und
|
||||
- der Integer-Wert ist gleich dem Unicode-codepoint.
|
||||
|
||||
|
||||
## Characters and Character Strings in Julia
|
||||
|
||||
### Characters: `Char`
|
||||
|
||||
The `Char` type encodes a single Unicode character.
|
||||
|
||||
- Julia uses single quotes for this: `'a'`.
|
||||
- A `Char` occupies 4 bytes of memory and
|
||||
- represents a Unicode codepoint.
|
||||
- `Char`s can be converted to/from `UInt`s and
|
||||
- the integer value is equal to the Unicode codepoint.
|
||||
|
||||
|
||||
`Char`s can be converted to/from `UInt`s.
|
||||
`Char`s können von/zu `UInt`s umgewandelt werden.
|
||||
|
||||
```{julia}
|
||||
UInt('a')
|
||||
@@ -285,10 +284,10 @@ UInt('a')
|
||||
b = Char(0x2656)
|
||||
```
|
||||
|
||||
### Character Strings: `String`
|
||||
### Zeichenketten: `String`
|
||||
|
||||
- For strings, Julia uses double quotes: `"a"`.
|
||||
- They are UTF-8 encoded, i.e., one character can be between 1 and 4 bytes long.
|
||||
- Für Strings verwendet Julia doppelte Anführungszeichen: `"a"`.
|
||||
- Sie sind UTF-8-codiert, d.h., ein Zeichen kann zwischen 1 und 4 Bytes lang sein.
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -298,21 +297,21 @@ b = Char(0x2656)
|
||||
|
||||
|
||||
|
||||
__For a non-ASCII string, the number of bytes and the number of characters differ:__
|
||||
__Bei einem Nicht-ASCII-String unterscheiden sich Anzahl der Bytes und Anzahl der Zeichen:__
|
||||
|
||||
|
||||
```{julia}
|
||||
asciistr = "Hello World!"
|
||||
@show length(asciistr) ncodeunits(asciistr);
|
||||
```
|
||||
(The space, of course, also counts.)
|
||||
(Das Leerzeichen zählt natürlich auch.)
|
||||
|
||||
```{julia}
|
||||
str = "😄 Hellö 🎶"
|
||||
@show length(str) ncodeunits(str);
|
||||
```
|
||||
|
||||
__Iterating over a string iterates over the characters:__
|
||||
__Iteration über einen String iteriert über die Zeichen:__
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -321,76 +320,76 @@ for i in str
|
||||
end
|
||||
```
|
||||
|
||||
### Concatenation of Strings
|
||||
### Verkettung von Strings
|
||||
|
||||
"Strings with concatenation form a non-commutative monoid."
|
||||
"Strings mit Verkettung bilden ein nichtkommutatives Monoid."
|
||||
|
||||
Therefore, Julia writes concatenation multiplicatively.
|
||||
Deshalb wird in Julia die Verkettung multiplikativ geschrieben.
|
||||
```{julia}
|
||||
str * asciistr * str
|
||||
```
|
||||
|
||||
Powers with natural exponents are thus also defined.
|
||||
Damit sind auch Potenzen mit natürlichem Exponenten definiert.
|
||||
|
||||
```{julia}
|
||||
str^3, str^0
|
||||
```
|
||||
|
||||
### String Interpolation
|
||||
### Stringinterpolation
|
||||
|
||||
The dollar sign has a special function in strings, which we have often used in
|
||||
`print()` statements. One can interpolate a variable or expression with it:
|
||||
Das Dollarzeichen hat in Strings eine Sonderfunktion, die wir schon oft in
|
||||
`print()`-Anweisungen genutzt haben. MAn kann damit eine Variable oder einen Ausdruck interpolieren:
|
||||
|
||||
|
||||
```{julia}
|
||||
a = 33.4
|
||||
b = "x"
|
||||
|
||||
s = "The result for $b is equal to $a and the doubled square root of it is $(2sqrt(a))\n"
|
||||
s = "Das Ergebnis für $b ist gleich $a und die verdoppelte Wurzel daraus ist $(2sqrt(a))\n"
|
||||
```
|
||||
|
||||
### Backslash Escape Sequences
|
||||
### Backslash escape sequences
|
||||
|
||||
The _backslash_ `\` also has a special function in string constants.
|
||||
Julia uses the backslash codings known from C and other languages for special characters and for dollar signs and backslashes themselves:
|
||||
Der _backslash_ `\` hat in Stringkonstanten ebenfalls eine Sonderfunktion.
|
||||
Julia benutzt die von C und anderen Sprachen bekannten _backslash_-Codierungen für Sonderzeichen und für Dollarzeichen und Backslash selbst:
|
||||
|
||||
|
||||
```{julia}
|
||||
s = "This is how one gets \'quotes\" and a \$ sign and a\nline break and a \\ etc... "
|
||||
s = "So bekommt man \'Anführungszeichen\" und ein \$-Zeichen und einen\nZeilenumbruch und ein \\ usw... "
|
||||
print(s)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Triple Quotes
|
||||
### Triple-Quotes
|
||||
|
||||
Strings can also be delimited with triple quotes.
|
||||
In this form, line breaks and quotes are preserved:
|
||||
Man kann Strings auch mit Triple-Quotes begrenzen.
|
||||
In dieser Form bleiben Zeilenumbrüche und Anführungszeichen erhalten:
|
||||
|
||||
|
||||
```{julia}
|
||||
s = """
|
||||
This should
|
||||
be a "longer"
|
||||
'text'.
|
||||
Das soll
|
||||
ein "längerer"
|
||||
'Text' sein.
|
||||
"""
|
||||
|
||||
print(s)
|
||||
```
|
||||
|
||||
### Raw Strings
|
||||
### Raw strings
|
||||
|
||||
In a `raw string`, all backslash codings except `\"` are disabled:
|
||||
In einem `raw string` sind alle backslash-Codierungen außer `\"` abgeschaltet:
|
||||
|
||||
|
||||
```{julia}
|
||||
s = raw"A $ and a \ and two \\ and a 'bla'..."
|
||||
s = raw"Ein $ und ein \ und zwei \\ und ein 'bla'..."
|
||||
print(s)
|
||||
```
|
||||
|
||||
## Further Functions for Characters and Strings (Selection)
|
||||
## Weitere Funktionen für Zeichen und Strings (Auswahl)
|
||||
|
||||
### Tests for Characters
|
||||
### Tests für Zeichen
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -398,9 +397,9 @@ print(s)
|
||||
@show isnumeric('½') iscntrl('\n') ispunct(';');
|
||||
```
|
||||
|
||||
### Application to Strings
|
||||
### Anwendung auf Strings
|
||||
|
||||
These tests can e.g. be used with `all()`, `any()`, or `count()` on strings:
|
||||
Diese Tests lassen sich z.B. mit `all()`, `any()` oder `count()` auf Strings anwenden:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -409,7 +408,7 @@ all(ispunct, ";.:")
|
||||
|
||||
|
||||
```{julia}
|
||||
any(isdigit, "It is 3 o'clock! 🕒" )
|
||||
any(isdigit, "Es ist 3 Uhr! 🕒" )
|
||||
```
|
||||
|
||||
|
||||
@@ -417,7 +416,7 @@ any(isdigit, "It is 3 o'clock! 🕒" )
|
||||
count(islowercase, "Hello, du!!")
|
||||
```
|
||||
|
||||
### Other String Functions
|
||||
### Weitere String-Funktionen
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -439,50 +438,50 @@ count(islowercase, "Hello, du!!")
|
||||
|
||||
|
||||
```{julia}
|
||||
split("π is irrational.")
|
||||
split("π ist irrational.")
|
||||
```
|
||||
|
||||
|
||||
```{julia}
|
||||
replace("π is irrational.", "is" => "is allegedly")
|
||||
replace("π ist irrational.", "ist" => "ist angeblich")
|
||||
```
|
||||
|
||||
## Indexing of Strings
|
||||
## Indizierung von Strings
|
||||
|
||||
Strings are immutable but indexable. There are a few special features here.
|
||||
Strings sind nicht mutierbar aber indizierbar. Dabei gibt es ein paar Besonderheiten.
|
||||
|
||||
- The index numbers the bytes of the string.
|
||||
- For a non-ASCII string, not all indices are valid, because
|
||||
- a valid index always addresses a Unicode character.
|
||||
- Der Index nummeriert die Bytes des Strings.
|
||||
- Bei einem nicht-ASCII-String sind nicht alle Indizes gültig, denn
|
||||
- ein gültiger Index adressiert immer ein Unicode-Zeichen.
|
||||
|
||||
Our example string:
|
||||
Unser Beispielstring:
|
||||
```{julia}
|
||||
str
|
||||
```
|
||||
|
||||
The first character
|
||||
Das erste Zeichen
|
||||
```{julia}
|
||||
str[1]
|
||||
```
|
||||
|
||||
This character is 4 bytes long in UTF-8 encoding. Thus, 2, 3, and 4 are invalid indices.
|
||||
Dieses Zeichen ist in UTF8-Kodierung 4 Bytes lang. Damit sind 2,3 und 4 ungültige Indizes.
|
||||
```{julia}
|
||||
str[2]
|
||||
```
|
||||
|
||||
Only the 5th byte is a new character:
|
||||
Erst das 5. Byte ist ein neues Zeichen:
|
||||
|
||||
```{julia}
|
||||
str[5]
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
```{julia}
|
||||
str[1:7]
|
||||
```
|
||||
|
||||
The function `eachindex()` returns an iterator over the valid indices:
|
||||
Die Funktion `eachindex()` liefert einen Iterator über die gültigen Indizes:
|
||||
|
||||
```{julia}
|
||||
for i in eachindex(str)
|
||||
@@ -491,24 +490,24 @@ for i in eachindex(str)
|
||||
end
|
||||
```
|
||||
|
||||
As usual, `collect()` makes an iterator into a vector.
|
||||
Wie üblich macht collect() aus einem Iterator einen Vektor.
|
||||
|
||||
```{julia}
|
||||
collect(eachindex(str))
|
||||
```
|
||||
|
||||
The function `nextind()` returns the next valid index.
|
||||
Die Funktion `nextind()` liefert den nächsten gültigen Index.
|
||||
```{julia}
|
||||
@show nextind(str, 1) nextind(str, 2);
|
||||
```
|
||||
|
||||
Why does Julia use a byte index instead of a character index? The main reason is the efficiency of indexing.
|
||||
Warum verwendet Julia einen Byte-Index und keinen Zeichenindex? Der Hauptgrund dürfte die Effizienz der Indizierung sein.
|
||||
|
||||
- In a long string, e.g., a book text, the position `s[123455]` can be found quickly with a byte index.
|
||||
- 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.
|
||||
- In einem langen String, z.B. einem Buchtext, ist die Stelle `s[123455]` mit einem Byte-Index schnell zu finden.
|
||||
- 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.
|
||||
|
||||
|
||||
Some functions return indices or ranges as results. They always return valid indices:
|
||||
Einige Funktionen liefern Indizes oder Ranges als Resultat. Sie liefern immer gültige Indizes:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -530,8 +529,9 @@ str2 = "αβγδϵ"^3
|
||||
n = findfirst('γ', str2)
|
||||
```
|
||||
|
||||
So one can continue searching from the next valid index after `n=5`:
|
||||
So kann man ab dem nächsten nach `n=5` gültigen Index weitersuchen:
|
||||
|
||||
```{julia}
|
||||
findnext('γ', str2, nextind(str2, n))
|
||||
```
|
||||
|
||||
|
||||
@@ -9,15 +9,15 @@ engine: julia
|
||||
using InteractiveUtils
|
||||
```
|
||||
|
||||
# Linear Algebra in Julia
|
||||
# Lineare Algebra in Julia
|
||||
|
||||
```{julia}
|
||||
using LinearAlgebra
|
||||
```
|
||||
|
||||
The `LinearAlgebra` package provides among other things:
|
||||
Das `LinearAlgebra`-Paket liefert unter anderem:
|
||||
|
||||
- additional subtypes of `AbstractMatrix`: usable like other matrices, e.g.,
|
||||
- zusätzliche Subtypen von `AbstractMatrix`: genauso verwendbar, wie andere Matrizen, z.B.
|
||||
|
||||
- `Tridiagonal`
|
||||
- `SymTridiagonal`
|
||||
@@ -25,26 +25,26 @@ The `LinearAlgebra` package provides among other things:
|
||||
- `UpperTriangular`
|
||||
|
||||
|
||||
- additional/extended functions: `norm`, `opnorm`, `cond`, `inv`, `det`, `exp`, `tr`, `dot`, `cross`, ...
|
||||
- zusätzliche/erweiterte Funktionen: `norm`, `opnorm`, `cond`, `inv`, `det`, `exp`, `tr`, `dot`, `cross`, ...
|
||||
|
||||
- a universal solver for systems of linear equations: `\`
|
||||
- `x = A \ b` solves $A \mathbf{x}=\mathbf{b}$ by appropriate matrix factorization and forward/backward substitution
|
||||
- einen universellen Solver für lineare Gleichungssysteme: `\`
|
||||
- `x = A \ b` löst $A \mathbf{x}=\mathbf{b}$ durch geeignete Matrixfaktorisierung und Vorwärts/Rückwärtssubstition
|
||||
|
||||
- [Matrix factorizations](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#man-linalg-factorizations)
|
||||
- [Matrixfaktorisierungen](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#man-linalg-factorizations)
|
||||
- `LU`
|
||||
- `QR`
|
||||
- `Cholesky`
|
||||
- `SVD`
|
||||
- ...
|
||||
|
||||
- Computation of eigenvalues/eigenvectors
|
||||
- Berechnung von Eigenwerte/-vektoren
|
||||
|
||||
- `eigen`, `eigvals`, `eigvecs`
|
||||
|
||||
|
||||
- Access to BLAS/LAPACK functions
|
||||
- Zugriff auf BLAS/LAPACK-Funktionen
|
||||
|
||||
## Matrix Types
|
||||
## Matrixtypen
|
||||
|
||||
|
||||
|
||||
@@ -57,31 +57,31 @@ A = SymTridiagonal(fill(1.0, 4), fill(-0.3, 3))
|
||||
B = UpperTriangular(A)
|
||||
```
|
||||
|
||||
These types are stored space-efficiently. The usual arithmetic operations are implemented:
|
||||
Diese Typen werden platzsparend gespeichert. Die üblichen Rechenoperationen sind implementiert:
|
||||
|
||||
```{julia}
|
||||
A + B
|
||||
```
|
||||
|
||||
Read-only index access is possible,
|
||||
Lesende Indexzugriffe sind möglich,
|
||||
```{julia}
|
||||
A[1,4]
|
||||
```
|
||||
|
||||
write operations not necessarily:
|
||||
schreibende nicht unbedingt:
|
||||
```{julia}
|
||||
#| error: true
|
||||
A[1,3] = 17
|
||||
```
|
||||
|
||||
Conversion to a 'normal' matrix is possible, for example, with `collect()`:
|
||||
Die Umwandlung in eine 'normale' Matrix ist z.B. mit `collect()` möglich:
|
||||
```{julia}
|
||||
A2 = collect(A)
|
||||
```
|
||||
|
||||
### The Identity Matrix `I`
|
||||
### Die Einheitsmatrix `I`
|
||||
|
||||
`I` denotes an identity matrix (square, diagonal elements = 1, all others = 0) of the respective required size
|
||||
`I` bezeichnet eine Einheitsmatrix (quadratisch, Diagonalelemente = 1, alle anderen = 0) in der jeweils erforderlichen Größe
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -89,39 +89,39 @@ A + 4I
|
||||
```
|
||||
|
||||
|
||||
## Norms
|
||||
## Normen
|
||||
|
||||
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:
|
||||
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:
|
||||
$$
|
||||
d(x,y) := ||x-y||
|
||||
$$
|
||||
|
||||
### $p$-Norms
|
||||
### $p$-Normen
|
||||
|
||||
A simple class of norms in $ℝ^n$ are the $p$-norms
|
||||
Eine einfache Klasse von Normen im $ℝ^n$ sind die $p$-Normen
|
||||
$$
|
||||
||\mathbf{x}||_p = \left(\sum |x_i|^p\right)^\frac{1}{p},
|
||||
$$
|
||||
which generalize the Euclidean norm $p=2$.
|
||||
die die die euklidische Norm $p=2$ verallgemeinern.
|
||||
|
||||
|
||||
:::{.callout-note}
|
||||
|
||||
## The Max-Norm $p=\infty$
|
||||
## Die Max-Norm $p=\infty$
|
||||
|
||||
Let $x_{\text{max}}$ be the _largest in absolute value_ component of $\mathbf{x}\in ℝ^n$. Then always
|
||||
Sei $x_{\text{max}}$ die _betragsmäßig_ größte Komponente von $\mathbf{x}\in ℝ^n$. Dann gilt stets
|
||||
$$ |x_{\text{max}}| \le ||\mathbf{x}||_p \le n^\frac{1}{p} |x_{\text{max}}|
|
||||
$$
|
||||
(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}}$.)
|
||||
(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.)
|
||||
|
||||
Thus follows
|
||||
Damit folgt
|
||||
$$
|
||||
\lim_{p \rightarrow \infty} ||\mathbf{x}||_p = |x_{\text{max}}| =: ||\mathbf{x}||_\infty.
|
||||
$$
|
||||
:::
|
||||
|
||||
|
||||
In Julia, the `LinearAlgebra` package defines a function `norm(v, p)`.
|
||||
In Julia definiert das `LinearAlgebra`-Paket eine Funktion `norm(v, p)`.
|
||||
|
||||
```{julia}
|
||||
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);
|
||||
```
|
||||
|
||||
- If the 2nd argument `p` is missing, `p=2` is set.
|
||||
- The 2nd argument can also be `Inf` (i.e., $+\infty$).
|
||||
- The 1st argument can be any container full of numbers. The sum $\sum |x_i|^p$ extends over *all* elements of the container.
|
||||
- Thus, for a matrix `norm(A)` is equal to the _Frobenius norm_ of the matrix `A`.
|
||||
- Wenn das 2. Argument `p` fehlt, wird `p=2` gesetzt.
|
||||
- Das 2. Argument kann auch `Inf` (also $+\infty$) sein.
|
||||
- Das 1. Argument kann ein beliebiger Container voller Zahlen sein. Die Summe $\sum |x_i|^p$ erstreckt sich über *alle* Elemente des Containers.
|
||||
- Damit ist für eine Matrix `norm(A)` gleich der _Frobenius-Norm_ der Matrix `A`.
|
||||
|
||||
```{julia}
|
||||
A = [1 2 3
|
||||
@@ -144,12 +144,12 @@ norm(A) # Frobenius norm
|
||||
|
||||
|
||||
|
||||
Since norms are homogeneous under multiplication with scalars,
|
||||
$||\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 visible by clicking).
|
||||
Da Normen homogen unter Multiplikation mit Skalaren sind,
|
||||
$||\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
|
||||
(Code durch anklicken sichtbar).
|
||||
```{julia}
|
||||
#| code-fold: true
|
||||
#| fig-cap: "Unit balls in $ℝ^2$ for different $p$-norms: $p$=0.8; 1; 1.5; 2; 3.001 and 1000"
|
||||
#| fig-cap: "Einheitskugeln im $ℝ^2$ für verschiedene $p$-Normen: $p$=0.8; 1; 1.5; 2; 3.001 und 1000"
|
||||
using Plots
|
||||
|
||||
colors=[:purple, :green, :red, :blue,:aqua, :black]
|
||||
@@ -163,35 +163,35 @@ for p ∈ (0.8, 1, 1.5, 2, 3.001, 1000)
|
||||
end
|
||||
fig1
|
||||
```
|
||||
As one can see, $p\ge 1$ must hold so that the unit ball is convex and $||.||_p$ is a norm.
|
||||
Wie man sieht, muß $p\ge 1$ sein, damit die Einheitskugel konvex und $||.||_p$ eine Norm ist.
|
||||
|
||||
However, the Julia function `norm(v, p)` returns a result for arbitrary parameters `p`.
|
||||
Die Julia-Funktion `norm(v, p)` liefert allerdings für beliebige Parameter `p` ein Ergebnis.
|
||||
|
||||
|
||||
### Induced Norms (Operator Norms)
|
||||
### Induzierte Normen (Operatornormen)
|
||||
|
||||
Matrices $A$ represent linear mappings $\mathbf{v}\mapsto A\mathbf{v}$. The matrix norm induced by a vector norm answers the question:
|
||||
Matrizen $A$ repräsentieren lineare Abbildungen $\mathbf{v}\mapsto A\mathbf{v}$. Die von einer Vektornorm Induzierte Matrixnorm beantwortet die Frage:
|
||||
|
||||
> _"By what factor can a vector be maximally stretched by the transformation $A$?"_
|
||||
> _„Um welchen Faktor kann ein Vektor durch die Transformation $A$ maximal gestreckt werden?“_
|
||||
|
||||
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$.
|
||||
Auf Grund der Homogenität der Norm unter Multiplikation mit Skalaren reicht es aus, das Bild der Einheitskugel unter der Transformation $A$ zu betrachten.
|
||||
|
||||
::: {.callout-tip}
|
||||
## Definition
|
||||
Let $V$ be a vector space with dimension $0<n<\infty$ and
|
||||
$A$ an $n\times n$-matrix. Then
|
||||
Sei $V$ ein Vektorraum mit einer Dimension $0<n<\infty$ und
|
||||
$A$ eine $n\times n$-Matrix. Dann ist
|
||||
$$
|
||||
||A||_p = \max_{||\mathbf{v}||_p=1} ||A\mathbf{v}||_p
|
||||
$$
|
||||
:::
|
||||
|
||||
Induced norms can only be calculated with difficulty for general $p$. Exceptions are the cases
|
||||
Induzierte Normen lassen sich für allgemeines $p$ nur schwer berechnen. Ausnahmen sind die Fälle
|
||||
|
||||
- $p=1$: column sum norm
|
||||
- $p=2$: spectral norm and
|
||||
- $p=\infty$: row sum norm
|
||||
- $p=1$: Spaltensummennorm
|
||||
- $p=2$: Spektralnorm und
|
||||
- $p=\infty$: Zeilensummennorm
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
```{julia}
|
||||
A = [ 0 1
|
||||
@@ -200,7 +200,7 @@ A = [ 0 1
|
||||
@show opnorm(A, 1) opnorm(A, Inf) opnorm(A, 2) opnorm(A);
|
||||
```
|
||||
|
||||
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):
|
||||
Das folgende Bild zeigt die Wirkung von $A$ auf Einheitsvektoren. Vektoren gleicher Farbe werden aufeinander abgebildet. (Code durch anklicken sichtbar):
|
||||
|
||||
```{julia}
|
||||
#| error: false
|
||||
@@ -214,12 +214,12 @@ CairoMakie.activate!(type = "svg")
|
||||
|
||||
```{julia}
|
||||
#| code-fold: true
|
||||
#| fig-cap: "Image of the unit ball under $v \\mapsto Av$ with $||A||\\approx 2.088$"
|
||||
#| fig-cap: "Bild der Einheitskugel unter $v \\mapsto Av$ mit $||A||\\approx 2.088$"
|
||||
|
||||
using CairoMakie
|
||||
|
||||
# Makie bug https://github.com/MakieOrg/Makie.jl/issues/3255
|
||||
# Workaround https://github.com/MakieOrg/Makie.jl/issues/2607#issuecomment-1385816645
|
||||
# Würgaround https://github.com/MakieOrg/Makie.jl/issues/2607#issuecomment-1385816645
|
||||
tri = BezierPath([
|
||||
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
|
||||
```
|
||||
|
||||
### Condition Number
|
||||
### Konditionszahl
|
||||
|
||||
For p = 1, p = 2 (default) or p = Inf, `cond(A,p)` returns the condition number in the $p$-norm
|
||||
Für p = 1, p = 2 (default) oder p = Inf liefert `cond(A,p)` die Konditionszahl in der $p$-Norm
|
||||
$$
|
||||
\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);
|
||||
```
|
||||
|
||||
## Matrix Factorizations
|
||||
## Matrixfaktorisierungen
|
||||
|
||||
Basic tasks of numerical linear algebra:
|
||||
Basisaufgaben der numerischen linearen Algebra:
|
||||
|
||||
- Solve a system of linear equations $A\mathbf{x} = \mathbf{b}$.
|
||||
- If no solution exists, find the best approximation, i.e., the vector $\mathbf{x}$ that minimizes $||A\mathbf{x} - \mathbf{b}||$.
|
||||
- Find eigenvalues and eigenvectors $A\mathbf{x} = \lambda \mathbf{x}$ of $A$.
|
||||
- Löse ein lineares Gleichungssystem $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.
|
||||
- Finde Eigenwerte und Eigenvektoren $A\mathbf{x} = \lambda \mathbf{x}$ von $A$.
|
||||
|
||||
These tasks can be solved using matrix factorizations. Some fundamental matrix factorizations:
|
||||
Diese Aufgaben sind mit Matrixfaktorisierungen lösbar. Einige grundlegende Matrixfaktorisierungen:
|
||||
|
||||
- **LU decomposition** $A=L\cdot U$
|
||||
- factorizes a matrix as a product of a _lower_ and an _upper_ triangular matrix
|
||||
- in German also called LR decomposition (but the Julia function is called `lu()`)
|
||||
- always works (possibly after row exchanges - pivoting)
|
||||
- **Cholesky decomposition** $A=L\cdot L^*$
|
||||
- the upper triangular matrix is the conjugate of the lower,
|
||||
- half the effort compared to LU
|
||||
- only works if $A$ is Hermitian and positive definite
|
||||
- **QR decomposition** $A=Q\cdot R$
|
||||
- decomposes $A$ as a product of an orthogonal (or unitary in the complex case) matrix and an upper triangular matrix
|
||||
- $Q$ is length-preserving (rotations and/or reflections); the scalings are described by $R$
|
||||
- always works
|
||||
- **LU-Zerlegung** $A=L\cdot U$
|
||||
- faktorisiert eine Matrix als Produkt einer _lower_ und einer _upper_ Dreiecksmatrix
|
||||
- im Deutschen auch LR-Zerlegung (aber die Julia-Funktion heisst `lu()`)
|
||||
- geht (eventuell nach Zeilenvertauschung - Pivoting) immer
|
||||
- **Cholesky-Zerlegung** $A=L\cdot L^*$
|
||||
- die obere Dreiecksmatrix ist die konjugierte der unteren,
|
||||
- halber Aufwand im Vergleich zu LU
|
||||
- geht nur, wenn $A$ hermitesch und positiv definit ist
|
||||
- **QR-Zerlegung** $A=Q\cdot R$
|
||||
- zerlegt $A$ als Produkt einer orthogonalen (bzw. unitären im komplexen Fall) Matrix und einer oberen Dreiecksmatrix
|
||||
- $Q$ ist längenerhaltend (Drehungen und/oder Spiegelungen); die Stauchungen/Streckungen werden durch $R$ beschrieben
|
||||
- geht immer
|
||||
- **SVD** _(Singular value decomposition)_: $A = U\cdot D \cdot V^*$
|
||||
- $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$.
|
||||
- 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$.
|
||||
- $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$.
|
||||
- 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$.
|
||||
|
||||
|
||||
### LU Factorization
|
||||
### LU-Faktorisierung
|
||||
|
||||
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.
|
||||
An example:
|
||||
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.
|
||||
Ein Beispiel:
|
||||
$$
|
||||
A=\left[
|
||||
\begin{array}{ccc}
|
||||
@@ -303,10 +303,10 @@ A=\left[
|
||||
-2 & 1 & 5
|
||||
\end{array}\right]
|
||||
~ \begin{array}{c}
|
||||
~\\
|
||||
Z_2 \mapsto Z_2 \mathbin{\color{red}-}\textcolor{red}{3} Z_1\\
|
||||
Z_3 \mapsto Z_3 + \textcolor{red}{2} Z_1
|
||||
\end{array} \quad \Longrightarrow\
|
||||
~\\
|
||||
Z_2 \mapsto Z_2 \mathbin{\color{red}-}\textcolor{red}{3} Z_1\\
|
||||
Z_3 \mapsto Z_3 + \textcolor{red}{2} Z_1
|
||||
\end{array} \quad \Longrightarrow\
|
||||
\left[
|
||||
\begin{array}{ccc}
|
||||
1 &2 &2 \\
|
||||
@@ -314,10 +314,10 @@ A=\left[
|
||||
& 5 & 9
|
||||
\end{array}\right]
|
||||
~ \begin{array}{c}
|
||||
~\\
|
||||
~\\
|
||||
Z_3 \mapsto Z_3 + \textcolor{red}{\frac{1}{2}} Z_2
|
||||
\end{array} \quad \Longrightarrow\
|
||||
~\\
|
||||
~\\
|
||||
Z_3 \mapsto Z_3 + \textcolor{red}{\frac{1}{2}} Z_2
|
||||
\end{array} \quad \Longrightarrow\
|
||||
\left[
|
||||
\begin{array}{ccc}
|
||||
1 &2 &2 \\
|
||||
@@ -342,11 +342,11 @@ A = \left[
|
||||
$$
|
||||
|
||||
|
||||
- Often in practice: $A\mathbf{x}=\mathbf{b}$ must be solved for one $A$ and many right-hand sides $\mathbf{b}$.
|
||||
- The factorization, whose effort grows cubically $\sim n^3$ with the matrix size $n$, only needs to be done once.
|
||||
- The subsequent effort of forward/backward substitution for each $\mathbf{b}$ is only quadratically $\sim n^2$.
|
||||
- Häufig in der Praxis: $A\mathbf{x}=\mathbf{b}$ muss für ein $A$ und viele rechte Seiten $\mathbf{b}$ gelöst werden.
|
||||
- Die Faktorisierung, deren Aufwand kubisch $\sim n^3$ mit der Matrixgröße $n$ wächst, muss nur einmal gemacht werden.
|
||||
- Der anschliessende Aufwand der Vorwärts/Rückwärtssubstition für jedes $\mathbf{b}$ ist nur noch quadratisch $\sim n^2$.
|
||||
|
||||
The `LinearAlgebra` package of Julia contains the function `lu(A, options)` for calculating an LU decomposition:
|
||||
Das `LinearAlgebra`-Paket von Julia enthält zur Berechnung einer LU-Zerlegung die Funktion `lu(A, options)`:
|
||||
```{julia}
|
||||
A = [ 1 2 2
|
||||
3 -4 4
|
||||
@@ -361,7 +361,7 @@ display(U)
|
||||
|
||||
#### Pivoting
|
||||
|
||||
Let's look at one step of Gaussian elimination:
|
||||
Sehen wir uns einen Schritt der Gauß-Elimination an:
|
||||
$$
|
||||
\left[
|
||||
\begin{array}{cccccc}
|
||||
@@ -375,34 +375,37 @@ $$
|
||||
\end{array}
|
||||
\right]
|
||||
$$
|
||||
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.
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
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}}|
|
||||
$$
|
||||
|
||||
#### LU in Julia
|
||||
|
||||
- The factorizations in Julia return a special object that contains the matrix factors and additional information.
|
||||
- The Julia function `lu(A)` performs an LU factorization with pivoting.
|
||||
- Die Faktorisierungen in Julia geben ein spezielles Objekt zurück, das die Matrixfaktoren und weitere
|
||||
Informationen enthält.
|
||||
- Die Julia-Funktion `lu(A)` führt eine LU-Faktorisierung mit Pivoting durch.
|
||||
|
||||
|
||||
```{julia}
|
||||
F = lu(A)
|
||||
typeof(F)
|
||||
```
|
||||
Elements of the object:
|
||||
Elemente des Objekts:
|
||||
```{julia}
|
||||
@show F.L F.U F.p;
|
||||
```
|
||||
One can also use an appropriate tuple on the left side:
|
||||
Man kann auch gleich auf der linken Seite ein entsprechendes Tupel verwenden:
|
||||
```{julia}
|
||||
L, U, p = lu(A);
|
||||
p
|
||||
```
|
||||
|
||||
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,:]`:
|
||||
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:
|
||||
```{julia}
|
||||
display(A)
|
||||
display(A[p,:])
|
||||
@@ -410,28 +413,28 @@ display(L*U)
|
||||
```
|
||||
|
||||
|
||||
Forward/backward substitution with an `LU`-object is performed by the `\` operator:
|
||||
Die Vorwärts/Rückwärtssubstition mit einem `LU`- erledigt der Operator `\`:
|
||||
```{julia}
|
||||
b = [1, 2, 3]
|
||||
x = F \ b
|
||||
```
|
||||
Verification:
|
||||
Probe:
|
||||
```{julia}
|
||||
A * x - b
|
||||
```
|
||||
|
||||
In Julia, the `\` operator hides a quite universal "matrix solver", and it can also be applied directly:
|
||||
In Julia verbirgt sich hinter dem `\`-Operator ein ziemlich universeller "matrix solver" und man kann ihn auch direkt anwenden:
|
||||
```{julia}
|
||||
A \ b
|
||||
```
|
||||
An appropriate factorization is performed implicitly, but its result is not saved.
|
||||
Dabei wird implizit eine geeignete Faktorisierung durchgeführt, deren Ergebnis allerdings nicht abgespeichert.
|
||||
|
||||
|
||||
### QR Decomposition
|
||||
### QR-Zerlegung
|
||||
|
||||
|
||||
The function `qr()` returns a special QR object that contains the components $Q$ and $R$. The orthogonal (or unitary) matrix $Q$ is
|
||||
[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.
|
||||
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
|
||||
[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.
|
||||
```{julia}
|
||||
F = qr(A)
|
||||
@show typeof(F) typeof(F.Q)
|
||||
@@ -439,11 +442,11 @@ display(collect(F.Q))
|
||||
display(F.R)
|
||||
```
|
||||
|
||||
### Appropriate Factorization
|
||||
### Passende Faktorisierung
|
||||
|
||||
|
||||
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.
|
||||
If solutions for several right-hand sides $\mathbf{b_1}, \mathbf{b_2},...$ are needed, the factorization should only be performed once:
|
||||
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.
|
||||
Wenn man Lösungen zu mehreren rechten Seiten $\mathbf{b_1}, \mathbf{b_2},...$ benötigt, sollte man die Faktorisierung nur einmal durchführen:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -459,3 +462,4 @@ Af \ [1, 2, 3]
|
||||
```{julia}
|
||||
Af \ [5, 7, 9]
|
||||
```
|
||||
|
||||
|
||||
@@ -2,23 +2,7 @@
|
||||
engine: julia
|
||||
---
|
||||
|
||||
```{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
|
||||
# Ein- und Ausgabe
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -38,50 +22,51 @@ Base.active_module() = myactive_module()
|
||||
```
|
||||
|
||||
|
||||
## Console
|
||||
## Konsole
|
||||
|
||||
The operating system normally provides 3 channels (_streams_) for a program:
|
||||
Das Betriebssystem stellt für ein Programm üblicherweise 3 Kanäle _(streams)_ zur Verfügung:
|
||||
|
||||
- Standard input channel `stdin`
|
||||
- Standard output channel `stdout` and
|
||||
- Standard error output channel `stderr`.
|
||||
- Standardeingabekanal `stdin`
|
||||
- Standardausgabekanal `stdout` und
|
||||
- Standardfehlerausgabekanal `stderr`.
|
||||
|
||||
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`.
|
||||
Wenn das Programm in einem Terminal (oder Konsole bzw. Shell) gestartet wird, kann das Programm über `stdin` die Tastatureingaben
|
||||
einlesen und Ausgaben über `stdout` sowie `stdout` erscheinen im Terminal.
|
||||
|
||||
|
||||
- Writing to `stdout`: `print()`,`println()`,`printstyled()`
|
||||
- Writing to `stderr`: `print(strerr,...)`, `println(stderr,...)`, `printstyled(stderr,...)`
|
||||
- Reading from `stdin`: `readline()`
|
||||
- Schreiben nach `stdout`: `print()`,`println()`,`printstyled()`
|
||||
- Schreiben nach `stderr`: `print(strerr,...)`, `println(stderr,...)`, `printstyled(stderr,...)`
|
||||
- Lesen von `stdin`: `readline()`
|
||||
|
||||
|
||||
### Input
|
||||
### Eingaben
|
||||
|
||||
The language _Python_ provides a function `input()`:
|
||||
Die Sprache _Python_ stellt eine Funktion `input()` zur Verfügung:
|
||||
```{.python}
|
||||
ans = input("Please enter a positive number!")
|
||||
ans = input("Bitte eine positive Zahl eingeben!")
|
||||
```
|
||||
The function prints the prompt, waits for input, and returns the
|
||||
input as a `string`.
|
||||
Die Funktion gibt den Prompt aus, wartet auf eine Eingabe und liefert die
|
||||
Eingabe als `string` zurück.
|
||||
|
||||
|
||||
In Julia, you can implement this function as follows:
|
||||
In Julia kann man diese Funktion so implementieren:
|
||||
|
||||
```{julia}
|
||||
function input(prompt = "Input:")
|
||||
function input(prompt = "Eingabe:")
|
||||
println(prompt)
|
||||
flush(stdout)
|
||||
return chomp(readline())
|
||||
end
|
||||
```
|
||||
|
||||
**Comments**
|
||||
**Anmerkungen**
|
||||
|
||||
- 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()` returns a string ending with a newline `\n`. The function `chomp()` removes a possible line break from the end of a string.
|
||||
- Schreibanweisungen werden von modernen Betriebssystemen gebuffert. Mit `flush(stdout)` wird die Leerung des Buffers und sofortige Schreiboperation erzwungen.
|
||||
- `readline()` liefert einen String zurück, der mit einer Newline `\n` endet. Die Funktion `chomp()` entfernt einen eventuellen Zeilenumbruch vom Ende eines Strings.
|
||||
|
||||
```{julia}
|
||||
#| eval: false
|
||||
a = input("Please enter 2 numbers!")
|
||||
a = input("Bitte 2 Zahlen eingeben!")
|
||||
```
|
||||
```{julia}
|
||||
#| echo: false
|
||||
@@ -89,33 +74,32 @@ a = "34 56"
|
||||
```
|
||||
|
||||
|
||||
### Processing the Input
|
||||
### Verarbeitung der Eingabe
|
||||
|
||||
> `split(str)` splits a string into "words" and returns an _(array of strings)_:
|
||||
> `split(str)` zerlegt einen String in "Wörter" und liefert einen _(array of strings)_:
|
||||
|
||||
```{julia}
|
||||
av = split(a)
|
||||
```
|
||||
|
||||
|
||||
> `parse(T, str)` tries to convert `str` to type `T`:
|
||||
> `parse(T, str)` versucht, `str` in den Typ `T` umzuwandeln:
|
||||
|
||||
|
||||
```{julia}
|
||||
v = parse.(Int, av)
|
||||
```
|
||||
|
||||
`parse()` generates an error if the string cannot be parsed as a value of type `T`. You can catch the error with
|
||||
`try/catch` or use the function `tryparse(T, str)`, which returns `nothing` in such a case - on which you can then
|
||||
e.g. test with `isnothing()`.
|
||||
`parse()` erzeugt einen Fehler, wenn der String sich nicht als Wertangabe von Typ `T` parsen lässt. Man kann den Fehler mit
|
||||
`try/catch` abfangen oder die Funktion `tryparse(T, str)` verwenden, die in so einem Fall `nothing` zurückgibt - worauf man dann
|
||||
z.B. mit `isnothing()` testen kann.
|
||||
|
||||
|
||||
|
||||
### Einzelne Tastenanschläge einlesen
|
||||
|
||||
### Reading Individual Keystrokes
|
||||
|
||||
- `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:
|
||||
- `readline()` u.ä. warten auf den Abschluss der Eingabe durch Drücken der `Enter`-Taste.
|
||||
- Techniken zum Einlesen einzelner _keystrokes_ findet man hier:
|
||||
|
||||
- [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)
|
||||
@@ -123,30 +107,30 @@ e.g. test with `isnothing()`.
|
||||
|
||||
|
||||
|
||||
## Formatted Output with the `Printf` Macro
|
||||
## Formatierte Ausgabe mit dem `Printf`-Makro
|
||||
|
||||
Often you want to output numbers or strings with a strict format specification - total length, decimal places, right/left-aligned, etc.
|
||||
Oft möchte man Zahlen oder Strings mit einer strikten Formatvorgabe - Gesamtlänge, Nachkommastellen, rechts/linksbündig usw - ausgeben.
|
||||
|
||||
To this end, the `Printf` package defines the macros `@sprintf` and `@printf`, which work very similarly to the corresponding C functions.
|
||||
Dazu definiert das Paket `Printf` die Makros `@sprintf` und `@printf`, welche sehr ähnlich wie die gleichnamigen C-Funktionen arbeiten.
|
||||
|
||||
```{julia}
|
||||
using Printf
|
||||
|
||||
x = 123.7876355638734
|
||||
|
||||
@printf("Output right-aligned with max. 10 character width and 3 decimal places: x= %10.3f", x)
|
||||
@printf("Ausgabe rechtsbündig mit max. 10 Zeichen Platz und 3 Nachkommastellen: x= %10.3f", x)
|
||||
```
|
||||
|
||||
|
||||
The first argument is a string containing placeholders (here: `%10.3`) for variables to be output; followed by these variables as further arguments.
|
||||
Das erste Argument ist ein String, der Platzhalter (hier: `%10.3`) für auszugebende Variablen enthält; gefolgt von diesen Variablen als weitere Argumente.
|
||||
|
||||
Placeholders have the form
|
||||
Platzhalter haben die Form
|
||||
```
|
||||
%[flags][width][.precision]type
|
||||
```
|
||||
where the entries in square brackets are all optional.
|
||||
wobei die Angaben in eckigen Klammern alle optional sind.
|
||||
|
||||
**Type specifications in placeholders**
|
||||
**Typangaben im Platzhalter**
|
||||
|
||||
| | |
|
||||
|:--|:------------|
|
||||
@@ -165,9 +149,9 @@ where the entries in square brackets are all optional.
|
||||
|
||||
| | |
|
||||
|:----|:-----|
|
||||
|Plus sign| right-aligned (default)|
|
||||
|Minus sign| left-aligned|
|
||||
|Zero| with leading zeros|
|
||||
|Pluszeichen| rechtsbündig (Standard)|
|
||||
|Minuszeichen| linksbündig|
|
||||
|Null| mit führenden Nullen|
|
||||
|
||||
: {.striped .hover}
|
||||
|
||||
@@ -175,37 +159,37 @@ where the entries in square brackets are all optional.
|
||||
**Width**
|
||||
|
||||
```
|
||||
Number of minimum characters used (more will be taken if necessary)
|
||||
Anzahl der minimal verwendeten Zeichen (wenn nötig, werden auch mehr genommen)
|
||||
```
|
||||
|
||||
|
||||
### Examples:
|
||||
### Beispiele:
|
||||
|
||||
|
||||
```{julia}
|
||||
using Printf # Don't forget to load the package!
|
||||
using Printf # Paket laden nicht vergessen!
|
||||
```
|
||||
|
||||
|
||||
```{julia}
|
||||
@printf("|%s|", "Hello") # string with placeholder for string
|
||||
@printf("|%s|", "Hallo") # string mit Platzhalter für String
|
||||
```
|
||||
The vertical bars are not part of the placeholder. They are intended to indicate the boundaries of the output field.
|
||||
Die senkrechten Striche sind nicht Teil des Platzhalters. Sie sollen die Begrenzung des Ausgabefeldes anzeigen.
|
||||
|
||||
|
||||
```{julia}
|
||||
@printf("|%10s|", "Hello") # Minimum length, right-aligned
|
||||
@printf("|%10s|", "Hallo") # Minimallänge, rechtsbündig
|
||||
```
|
||||
|
||||
|
||||
```{julia}
|
||||
@printf("|%-10s|", "Hello") # left-aligned
|
||||
@printf("|%-10s|", "Hallo") # linksbündig
|
||||
```
|
||||
|
||||
|
||||
```{julia}
|
||||
@printf("|%3s|", "Hello") # Length specification can be exceeded
|
||||
# Better a 'badly formatted' table than incorrect values!
|
||||
@printf("|%3s|", "Hallo") # Längenangabe kann überschritten werden
|
||||
# besser eine 'kaputt formatierte' Tabelle als falsche Werte!
|
||||
```
|
||||
|
||||
|
||||
@@ -214,36 +198,37 @@ j = 123
|
||||
k = 90019001
|
||||
l = 3342678
|
||||
|
||||
@printf("j= %012i, k= %-12i, l = %12i", j, k, l) # 0-flag for leading zeros
|
||||
@printf("j= %012i, k= %-12i, l = %12i", j, k, l) # 0-Flag für führende Nullen
|
||||
```
|
||||
|
||||
`@printf` and `@sprintf` can be called like functions or as macros:
|
||||
`@printf` und `@sprintf` können wie alle Makros wie Funktionen aufgerufen werden:
|
||||
|
||||
|
||||
```{julia}
|
||||
@printf("%i %i", 22, j)
|
||||
```
|
||||
|
||||
-- or as macros, i.e., without function parentheses and without comma:
|
||||
-- oder wie Makros, also ohne Funktionsklammern und ohne Komma:
|
||||
|
||||
|
||||
```{julia}
|
||||
@printf "%i %i" 22 j
|
||||
```
|
||||
|
||||
`@printf` can take a stream as its first argument.
|
||||
`@printf` kann als erstes Argument noch einen Stream übergeben bekommen.
|
||||
|
||||
Otherwise, the argument list consists of
|
||||
Ansonsten besteht die Argumentliste aus
|
||||
|
||||
- format string with placeholders
|
||||
- variables in the order of the placeholders, matching in number and type to the placeholders
|
||||
- Formatstring mit Platzhaltern
|
||||
- Variablen in der Reihenfolge der Platzhalter, in Anzahl und Typ zu den Platzhaltern passend
|
||||
|
||||
|
||||
```{julia}
|
||||
@printf(stderr, "First result: %i %s\nSecond result %i",
|
||||
j, "(estimated)" ,k)
|
||||
@printf(stderr, "Erstes Resultat: %i %s\nZweites Resultat %i",
|
||||
j, "(geschätzt)" ,k)
|
||||
```
|
||||
|
||||
The macro `@sprintf` does not print anything but returns the filled formatted string:
|
||||
Das Makro `@sprintf` druckt nichts, sondern liefert den ausgefüllten formatierten String zurück:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -255,52 +240,52 @@ str = @sprintf("x = %10.6f", π );
|
||||
str
|
||||
```
|
||||
|
||||
### Formatting Floating Point Numbers:
|
||||
### Formatierung der Gleitkommazahlen:
|
||||
|
||||
Meaning of the _precision_ value:
|
||||
Bedeutung des _Precision_-Wertes:
|
||||
|
||||
- `%f` and `%e` format: maximum number of decimal places
|
||||
- `%g` format: maximum number of digits output (integer + decimal places)
|
||||
- `%f` und `%e`-Format: maximale Anzahl der Nachkommastellen
|
||||
- `%g`-Format: maximale Anzahl von ausgegebenen Ziffern (Vor- + Nachkommastellen)
|
||||
|
||||
|
||||
```{julia}
|
||||
x = 123456.7890123456
|
||||
|
||||
@printf("%20.4f %20.4e", x, x) # 4 decimal places
|
||||
@printf("%20.4f %20.4e", x, x) # 4 Nachkommastellen
|
||||
```
|
||||
|
||||
|
||||
```{julia}
|
||||
@printf("%20.7f %20.7e", x, x) # 7 decimal places
|
||||
@printf("%20.7f %20.7e", x, x) # 7 Nachkommastellen
|
||||
```
|
||||
|
||||
|
||||
```{julia}
|
||||
@printf("%20.7g %20.4g", x, x) # total 7 and 4 digits respectively
|
||||
@printf("%20.7g %20.4g", x, x) # insgesamt 7 bzw. 4 Stellen
|
||||
```
|
||||
|
||||
## File Operations
|
||||
## Dateioperationen
|
||||
|
||||
Files are
|
||||
Dateien werden
|
||||
|
||||
- opened $\Longrightarrow$ a new _stream_-object is created (in addition to `stdin, stdout, stderr`)
|
||||
- then this _stream_ can be read from and written to
|
||||
- closed $\Longrightarrow$ _stream_-object is detached from file
|
||||
|
||||
```{.julia}
|
||||
stream = open(path, mode)
|
||||
```
|
||||
|
||||
- path: filename/path
|
||||
- mode:
|
||||
- geöffnet $\Longrightarrow$ dabei ensteht ein neues _stream_-Objekt (zusätzlich zu `stdin, stdout, stderr`)
|
||||
- dann kann dieser _stream_ gelesen und geschrieben werden
|
||||
- geschlossen $\Longrightarrow$ _stream_-Objekt wird von Datei getrennt
|
||||
|
||||
```{.julia}
|
||||
stream = open(path, mode)
|
||||
```
|
||||
|
||||
- path: Dateiname/pfad
|
||||
- mode:
|
||||
|
||||
```
|
||||
"r" read, opens at file beginning
|
||||
"w" write, opens at file beginning (file is created or overwritten)
|
||||
"a" append, opens to continue writing at file end
|
||||
```
|
||||
```
|
||||
"r" read, öffnet am Dateianfang
|
||||
"w" write, öffnet am Dateianfang (Datei wird neu angelegt oder überschrieben)
|
||||
"a" append, öffnet zum Weiterschreiben am Dateiende
|
||||
```
|
||||
|
||||
Let's write a file:
|
||||
Schreiben wir mal eine Datei:
|
||||
|
||||
```{julia}
|
||||
file = open("datei.txt", "w")
|
||||
@@ -313,7 +298,7 @@ file = open("datei.txt", "w")
|
||||
|
||||
|
||||
```{julia}
|
||||
println(file, " second line")
|
||||
println(file, " zweite Zeile")
|
||||
```
|
||||
|
||||
|
||||
@@ -321,58 +306,59 @@ println(file, " second line")
|
||||
close(file)
|
||||
```
|
||||
|
||||
Let's look at the file:
|
||||
Schauen wir uns die Datei an:
|
||||
|
||||
```{julia}
|
||||
;cat datei.txt
|
||||
```
|
||||
|
||||
...and now we open it again for reading:
|
||||
...und jetzt öffnen wir sie wieder zum Einlesen:
|
||||
|
||||
```{julia}
|
||||
stream = open("datei.txt", "r")
|
||||
```
|
||||
|
||||
`readlines(stream)` returns all lines of a text file as a vector of strings.
|
||||
`readlines(stream)` liefert alle Zeilen einer Textdatei als Vector von Strings.
|
||||
|
||||
`eachline(stream)` returns an iterator over the lines of the file.
|
||||
`eachline(stream)` liefert einen Iterator über die Zeilen der Datei.
|
||||
|
||||
|
||||
```{julia}
|
||||
n = 0
|
||||
for line in eachline(stream) # Read line by line
|
||||
for line in eachline(stream) # Lese zeilenweise
|
||||
n += 1
|
||||
println(n, line) # Print with line number
|
||||
println(n, line) # Drucke mit Zeilennummer
|
||||
end
|
||||
close(stream)
|
||||
```
|
||||
|
||||
## Packages for File Formats
|
||||
## Pakete für Dateiformate
|
||||
|
||||
For input and output in various file formats, there are Julia packages, e.g.,
|
||||
Für die Ein- und Ausgabe in den verschiedensten Dateiformaten existieren Julia-Pakete, z.B.
|
||||
|
||||
- [PrettyTables.jl](https://ronisbr.github.io/PrettyTables.jl/stable/) Output of formatted tables
|
||||
- [DelimitedFiles.jl](https://docs.julialang.org/en/v1/stdlib/DelimitedFiles/) Input and output of matrices, etc.
|
||||
- [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/) Input and output of Excel files
|
||||
- [PrettyTables.jl](https://ronisbr.github.io/PrettyTables.jl/stable/) Ausgabe von formatierten Tabellen
|
||||
- [DelimitedFiles.jl](https://docs.julialang.org/en/v1/stdlib/DelimitedFiles/) Ein- und Ausgabe von Matrizen u.ä.
|
||||
- [CSV.jl](https://csv.juliadata.org/stable/) Ein- und Ausgabe von Dateien mit "comma-separated values" u.ä.
|
||||
- [XLSX.jl](https://felipenoris.github.io/XLSX.jl/stable/tutorial/) Ein- und Ausgabe von Excel-Dateien
|
||||
|
||||
and many more...
|
||||
und viele andere mehr...
|
||||
|
||||
### DelimitedFiles.jl
|
||||
|
||||
This package enables convenient saving/reading of matrices. It provides the functions `writedlm()` and `readdlm()`.
|
||||
Dieses Paket ermöglicht das bequeme Abspeichern/Einlesen von Matrizen. Dazu stellt es die Funktionen `writedlm()` und `readdlm()` zur
|
||||
Verfügung.
|
||||
|
||||
```{julia}
|
||||
using DelimitedFiles
|
||||
```
|
||||
|
||||
|
||||
We generate a 200×3 matrix of random numbers
|
||||
Wir erzeugen eine 200×3-Matrix von Zufallszahlen
|
||||
```{julia}
|
||||
A = rand(200,3)
|
||||
```
|
||||
|
||||
and save it
|
||||
und speichern diese
|
||||
```{julia}
|
||||
f = open("data2.txt", "w")
|
||||
writedlm(f, A)
|
||||
@@ -380,23 +366,23 @@ close(f)
|
||||
```
|
||||
|
||||
|
||||
The written file starts like this:
|
||||
Die geschriebene Datei fängt so an:
|
||||
|
||||
```{julia}
|
||||
;head data2.txt
|
||||
```
|
||||
|
||||
|
||||
Reading it back is even simpler:
|
||||
Das Wiedereinlesen ist noch einfacher:
|
||||
```{julia}
|
||||
B = readdlm("data2.txt")
|
||||
```
|
||||
|
||||
|
||||
One more point: In Julia, the `do` notation is often used for file handling, see @sec-do.
|
||||
This uses the fact that `open()` also has methods where the 1st argument is a `function(iostream)`.
|
||||
This function is then applied to the _stream_ and the stream is automatically closed at the end. The `do` notation allows you to
|
||||
define this function anonymously after the `do`:
|
||||
Noch ein Punkt: Beim Umgang mit Dateien wird in Julia oft die `do`-Notation verwendet, s. @sec-do.
|
||||
Dazu nutzt man, dass `open()` auch Methoden hat, bei denen das 1. Argument eine `function(iostream)` ist.
|
||||
Diese wird dann auf den _stream_ angewendet und dieser abschliessend automatisch geschlossen. Die `do`-Notation erlaubt es,
|
||||
diese Funktion anonym nach dem `do` zu definieren:
|
||||
|
||||
```{julia}
|
||||
open("data2.txt", "w") do io
|
||||
@@ -404,16 +390,18 @@ open("data2.txt", "w") do io
|
||||
end
|
||||
```
|
||||
|
||||
### CSV and DataFrames
|
||||
### CSV und 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}
|
||||
using CSV, DataFrames, Downloads
|
||||
# Weather data from Westerland, see https://dev.meteostat.net/bulk/hourly.html
|
||||
# Wetterdaten von Westerland, s. https://dev.meteostat.net/bulk/hourly.html
|
||||
|
||||
url = "https://bulk.meteostat.net/v2/hourly/10018.csv.gz"
|
||||
http_response = Downloads.download(url)
|
||||
@@ -421,26 +409,25 @@ file = CSV.File(http_response, header=false);
|
||||
```
|
||||
|
||||
|
||||
The data looks like this:
|
||||
Die Daten sehen so aus:
|
||||
|
||||
|
||||
```{julia}
|
||||
# https://dev.meteostat.net/bulk/hourly.html#endpoints
|
||||
#
|
||||
# Column 1 Date
|
||||
# 2 Time (hour)
|
||||
# 3 Temperature
|
||||
# 5 Humidity
|
||||
# 6 Precipitation
|
||||
# 8 Wind direction
|
||||
# 9 Wind speed
|
||||
# Spalte 1 Datum
|
||||
# 2 Uhrzeit (Stunde)
|
||||
# 3 Temp
|
||||
# 5 Luftfeuchtigkeit
|
||||
# 6 Niederschlag
|
||||
# 8 Windrichtung
|
||||
# 9 Windstärke
|
||||
|
||||
df = DataFrame(file)
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
```{julia}
|
||||
#| error: false
|
||||
#| echo: false
|
||||
@@ -451,19 +438,18 @@ describe(df)
|
||||
|
||||
|
||||
|
||||
|
||||
For convenient plotting and handling of date and time formats in the weather table,
|
||||
we load two helper packages:
|
||||
Zum bequemen Plotten und zum Umgang mit den Datums- und Zeitformaten in der Wettertabelle
|
||||
laden wir noch 2 Helferlein:
|
||||
|
||||
```{julia}
|
||||
using StatsPlots, Dates
|
||||
```
|
||||
|
||||
|
||||
We create a new column that combines date (from column 1) and time (from column 2):
|
||||
Wir erzeugen eine neue Spalte, die Datum (aus Spalte 1) und Uhrzeit (aus Spalte 2) kombiniert:
|
||||
|
||||
```{julia}
|
||||
# new column combining col. 1 and 2 (date & time)
|
||||
# neue Spalte mit Sp.1 und 2 (date & time) kombiniert
|
||||
|
||||
df[!, :datetime] = DateTime.(df.Column1) .+ Hour.(df.Column2);
|
||||
```
|
||||
@@ -480,12 +466,14 @@ df[!, :datetime] = DateTime.(df.Column1) .+ Hour.(df.Column2);
|
||||
@df df plot(:datetime, :Column3)
|
||||
```
|
||||
|
||||
And now to the plot:
|
||||
Und nun zum Plot:
|
||||
|
||||
```{julia}
|
||||
@df df plot(:datetime, [:Column9, :Column6, :Column3],
|
||||
xlims = (DateTime(2023,9,1), DateTime(2024,5,30)),
|
||||
layout=(3,1), title=["Wind" "Rain" "Temp"],
|
||||
layout=(3,1), title=["Wind" "Regen" "Temp"],
|
||||
legend=:none, size=(800,800))
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,41 +10,41 @@ using InteractiveUtils
|
||||
```
|
||||
|
||||
|
||||
# Plots and Data Visualization in Julia: _Plots.jl_
|
||||
# Plots und Datenvisualisierung in Julia: _Plots.jl_
|
||||
|
||||
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/). Before presenting these in more detail, some other packages are listed.
|
||||
Es gibt zahlreiche Grafikpakete für Julia. Zwei oft genutzte sind [Makie.jl](https://docs.makie.org/stable/) und
|
||||
[Plots.jl](https://docs.juliaplots.org/latest/). Bevor wir diese genauer vorstellen, seien noch einige andere Pakete aufgelistet.
|
||||
|
||||
## Brief Overview: Some Graphics Packages
|
||||
## Kurze Übersicht: einige Grafikpakete
|
||||
|
||||
| Package/Documentation | Tutorial | Examples | Remarks |
|
||||
| Paket/Doku | Tutorial | Beispiele | Bemerkungen |
|
||||
|:----|:--|:--|:--------|
|
||||
|[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 (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 to the [Plotly](https://plotly.com/graphing-libraries/) JavaScript graphics library |
|
||||
| [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/) | | [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 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/)| 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/)| *Animated* vector graphics
|
||||
|[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) |
|
||||
| [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 |
|
||||
|[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 |
|
||||
| [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/)" |
|
||||
| [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/) |
|
||||
|[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/)|
|
||||
| [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 |
|
||||
| [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
|
||||
| [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 to Matplotlib (Python), 1:1 transfer of the Python API, therefore see [Matplotlib documentation](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 zu Matplotlib (Python), 1:1-Übertragung der Python-API, deswegen s. [Matplotlib-Dokumentation](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 to Matplotlib (Python), 1:1 transfer of the Python API, therefore see [Matplotlib documentation](https://matplotlib.org/stable/) |
|
||||
| [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/) |
|
||||
-->
|
||||
|
||||
## Plots.jl
|
||||
|
||||
### Simple Plots
|
||||
### Einfache Plots
|
||||
|
||||
The `plot()` function expects, in the simplest case:
|
||||
Die `plot()`-Funktion erwartet im einfachsten Fall:
|
||||
|
||||
- as the first argument a vector of $x$-values of length $n$ and
|
||||
- as the second argument a vector of the same length with the corresponding $y$-values.
|
||||
- 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:
|
||||
- als erstes Argument einen Vektor von $x$-Werten der Länge $n$ und
|
||||
- als zweites Argument einen gleichlangen Vektor mit den dazugehörigen $y$-Werten.
|
||||
- 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:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -57,16 +57,16 @@ cx = @. cos(2x^(1/2))
|
||||
plot(x, [sx cx])
|
||||
```
|
||||
|
||||
- The functions of the _Plots.jl_ package such as `plot(), scatter(), contour(), heatmap(), histogram(), bar(),...` etc. all start a new plot.
|
||||
- The versions `plot!(), scatter!(), contour!(), heatmap!(), histogram!(), bar!(),...` extend an existing plot:
|
||||
- Die Funktionen des _Plots.jl_-Paketes wie `plot(), scatter(), contour(), heatmap(), histogram(), bar(),...` usw. starten alle einen neuen Plot.
|
||||
- Die Versionen `plot!(), scatter!(), contour!(), heatmap!(), histogram!(), bar!(),...` erweitern einen existierenden Plot:
|
||||
|
||||
```{julia}
|
||||
plot(x, sx) # plot only sin(x)
|
||||
plot!(x, cx) # add second graph
|
||||
plot!(x, sqrt.(x)) # add a third one
|
||||
plot!(x, sqrt.(x)) # add a thirth one
|
||||
```
|
||||
|
||||
Plots are objects that can be assigned. Then they can be used later, copied, and in particular extended with the `!` functions:
|
||||
Plots sind Objekte, die zugewiesen werden können. Dann kann man sie später weiterverwenden, kopieren und insbesondere mit den `!`-Funktionen erweitern:
|
||||
|
||||
```{julia}
|
||||
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
|
||||
```
|
||||
|
||||
The copied version `plot1a` has not been modified by the `scatter!` statement and can be used independently:
|
||||
Die kopierte Version `plot1a` ist durch die `scatter!`-Anweisung nicht modifiziert worden und kann unabhängig weiterverwendet werden:
|
||||
|
||||
```{julia}
|
||||
plot!(plot1a, x, 2 .* sx)
|
||||
@@ -82,7 +82,7 @@ plot!(plot1a, x, 2 .* sx)
|
||||
|
||||
|
||||
|
||||
Plot objects can be saved as graphics files (PDF, SVG, PNG,...):
|
||||
Plot-Objekte kann man als Grafikdateien (PDF, SVG, PNG,...) abspeichern:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -94,13 +94,13 @@ savefig(plot1, "plot.png")
|
||||
;ls -l plot.png
|
||||
```
|
||||
|
||||
Plot objects can also be inserted as subplots into other plots, see section @sec-subplot.
|
||||
Plot-Objekte können auch als Teilplot in andere Plots eingefügt werden, siehe Abschnitt @sec-subplot.
|
||||
|
||||
|
||||
|
||||
### Function Plots
|
||||
### Funktionsplots
|
||||
|
||||
`plot()` can also be passed a function and a vector of $x$-values:
|
||||
Man kann `plot()` auch eine Funktion und einen Vektor mit $x$-Werten übergeben:
|
||||
|
||||
```{julia}
|
||||
# https://mzrg.com/math/graphs.shtml
|
||||
@@ -109,9 +109,9 @@ f(x) = abs(sin(x^x)/2^((x^x-π/2)/π))
|
||||
|
||||
plot(f, 0:0.01:3)
|
||||
```
|
||||
|
||||
|
||||
|
||||
The parametric form $x = x(t),\ y = y(t)$ can be drawn by passing two functions and a vector of $t$-values to `plot()`.
|
||||
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.
|
||||
|
||||
```{julia}
|
||||
# https://en.wikipedia.org/wiki/Butterfly_curve_(transcendental)
|
||||
@@ -123,16 +123,16 @@ plot(xt, yt, 0:0.01:12π)
|
||||
```
|
||||
|
||||
|
||||
### Plot Themes
|
||||
### Plot-Themen
|
||||
|
||||
> "PlotThemes is a package to spice up the plots made with Plots.jl."\
|
||||
Here is the illustrated [list of themes](https://docs.juliaplots.org/stable/generated/plotthemes/)
|
||||
Hier geht es zur illustrierten [Liste der Themen](https://docs.juliaplots.org/stable/generated/plotthemes/)
|
||||
|
||||
or:
|
||||
oder:
|
||||
```{julia}
|
||||
using PlotThemes
|
||||
|
||||
# list of themes
|
||||
# Liste der Themen
|
||||
keys(PlotThemes._themes)
|
||||
```
|
||||
|
||||
@@ -149,48 +149,48 @@ plot(x, [sx cx 1 ./ (1 .+ x)])
|
||||
```
|
||||
|
||||
|
||||
### Plot Attributes
|
||||
### Plot-Attribute
|
||||
|
||||
The functions of the `Plots.jl` package have a large number of options.
|
||||
`Plots.jl` divides the attributes into 4 groups:
|
||||
Die Funktionen des `Plots.jl`-Paketes haben eine große Anzahl von Optionen.
|
||||
`Plots.jl` teilt die Attribute in 4 Gruppen ein:
|
||||
|
||||
::::{.cell}
|
||||
```{julia}
|
||||
#| output: asis
|
||||
plotattr(:Plot) # attributes for the overall plot
|
||||
plotattr(:Plot) # Attribute für den Gesamtplot
|
||||
```
|
||||
::::
|
||||
|
||||
::::{.cell}
|
||||
```{julia}
|
||||
#| output: asis
|
||||
plotattr(:Subplot) # attributes for a subplot
|
||||
plotattr(:Subplot) # Attribute für einen Teilplot
|
||||
```
|
||||
::::
|
||||
|
||||
::::{.cell}
|
||||
```{julia}
|
||||
#| output: asis
|
||||
plotattr(:Axis) # attributes for an axis
|
||||
plotattr(:Axis) # Attribute für eine Achse
|
||||
```
|
||||
::::
|
||||
|
||||
::::{.cell}
|
||||
```{julia}
|
||||
#| output: asis
|
||||
plotattr(:Series) # attributes for a series, e.g., a line in the plot
|
||||
plotattr(:Series) # Attribute für eine Serie, also zB ein Linienzug im Plot
|
||||
```
|
||||
::::
|
||||
|
||||
One can also ask what the individual attributes mean and which values are allowed:
|
||||
Man kann auch nachfragen, was die einzelnen Attribute bedeuten und welche Werte zulässig sind:
|
||||
```{julia}
|
||||
plotattr("linestyle")
|
||||
```
|
||||
|
||||
|
||||
An example:
|
||||
Ein Beispiel:
|
||||
```{julia}
|
||||
theme(:default) # return to default theme
|
||||
theme(:default) # zurück zum Standardthema
|
||||
|
||||
x = 0:0.05:1
|
||||
y = sin.(2π*x)
|
||||
@@ -200,9 +200,9 @@ plot(x, y, seriestype = :sticks, linewidth = 4, seriescolor = "#00b300",
|
||||
)
|
||||
```
|
||||
|
||||
Many specifications can also be abbreviated significantly, see e.g. the `Aliases:` in the above output of the command `plotattr("linestyle")`.
|
||||
Viele Angaben können auch sehr weit abgekürzt werden, siehe z.B. die Angabe `Aliases:` in der obigen Ausgabe des Kommandos `plotattr("linestyle")`.
|
||||
|
||||
The following `plot()` command is equivalent to the previous one:
|
||||
Das folgende `plot()`-Kommando is äquivalent zum vorherigen:
|
||||
|
||||
```{julia}
|
||||
#| eval: false
|
||||
@@ -210,61 +210,61 @@ plot(x, y, t = :sticks, w = 4, c = "#00b300", m = (:circle, 8, :green ))
|
||||
```
|
||||
|
||||
|
||||
### Additional Extras
|
||||
### Weitere Extras
|
||||
|
||||
```{julia}
|
||||
using Plots # repetition does not hurt
|
||||
using Plots.PlotMeasures # for measurements in mm, cm,...
|
||||
using LaTeXStrings # for LaTeX constructs in plot labels
|
||||
using PlotThemes # predefined themes
|
||||
using Plots # Wiederholung schadet nicht
|
||||
using Plots.PlotMeasures # für Maßangaben in mm, cm,...
|
||||
using LaTeXStrings # für LaTeX-Konstrukte in Plot-Beschriftungen
|
||||
using PlotThemes # vorgefertigte Themen
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
```{julia}
|
||||
xs = range(0, 2π, length = 100)
|
||||
|
||||
data = [sin.(xs) cos.(xs) 2sin.(xs) (x->sin(x^2)).(xs)] # 4 functions
|
||||
data = [sin.(xs) cos.(xs) 2sin.(xs) (x->sin(x^2)).(xs)] # 4 Funktionen
|
||||
|
||||
theme(:ggplot2)
|
||||
|
||||
plot10 = plot(xs, data,
|
||||
fontfamily="Computer Modern",
|
||||
|
||||
# LaTeX string L"..."
|
||||
# LaTeX-String L"..."
|
||||
title = L"Winkelfunktionen $\sin(\alpha), \cos(\alpha), 2\sin(\alpha), \sin(\alpha^2)$",
|
||||
xlabel = L"Winkel $\alpha$",
|
||||
ylabel = "Funktionswert",
|
||||
|
||||
# 1x4-matrices with colors, markers,... for the 4 'series'
|
||||
# 1x4-Matrizen mit Farben, Marker,... für die 4 'Series'
|
||||
color=[:black :green RGB(0.3, 0.8, 0.2) :blue ],
|
||||
markers = [:rect :circle :utriangle :diamond],
|
||||
markersize = [2 1 0 4],
|
||||
linewidth = [1 3 1 2],
|
||||
linestyle = [:solid :dash :dot :solid ],
|
||||
|
||||
# axes
|
||||
# Achsen
|
||||
xlim = (0, 6.6),
|
||||
ylim = (-2, 2.3),
|
||||
yticks = -2:.4:2.3, # with step size
|
||||
yticks = -2:.4:2.3, # mit Schrittweite
|
||||
|
||||
# legend
|
||||
# Legende
|
||||
legend = :bottomleft,
|
||||
label = [ L"\sin(\alpha)" L"\cos(\alpha)" L"2\sin(\alpha)" L"\sin(\alpha^2)"],
|
||||
|
||||
top_margin = 5mm, # here Plots.PlotMeasures is needed
|
||||
top_margin = 5mm, # hier wird Plots.PlotMeasures gebraucht
|
||||
)
|
||||
|
||||
# additional text: annotate!(x-pos, y-pos, text("...", font, fontsize))
|
||||
# Zusatztext: annotate!(x-pos, y-pos, text("...", font, fontsize))
|
||||
|
||||
annotate!(plot10, 4.1, 1.8, text("nicht schön, aber viel","Computer Modern", 10) )
|
||||
```
|
||||
|
||||
### Other Plot Functions
|
||||
### Andere Plot-Funktionen
|
||||
|
||||
So far, we have plotted mainly lines. There are many other types such as _scatter plot, contour, heatmap, histogram, stick,..._
|
||||
Bisher haben wir vor allem Linien geplottet. Es gibt noch viele andere Typen wie _scatter plot, contour, heatmap, histogram, stick,..._
|
||||
|
||||
This can be controlled with the `seriestype` attribute:
|
||||
Dies kann man mit dem `seriestype`-Attribut steuern:
|
||||
|
||||
```{julia}
|
||||
theme(:default)
|
||||
@@ -273,7 +273,7 @@ x = range(0, 2π; length = 50)
|
||||
plot(x, sin.(x), seriestype=:scatter)
|
||||
```
|
||||
|
||||
or by using the specific function named after the `seriestype`:
|
||||
oder indem man die spezielle Funktion benutzt, die so heißt wie der `seriestype`:
|
||||
```{julia}
|
||||
x = range(0, 2π; length = 50)
|
||||
scatter(x, sin.(x))
|
||||
@@ -281,9 +281,9 @@ scatter(x, sin.(x))
|
||||
|
||||
|
||||
|
||||
### Subplots and Layout {#sec-subplot}
|
||||
### Subplots und Layout {#sec-subplot}
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
```{julia}
|
||||
x = range(0, 2π; length = 100)
|
||||
@@ -300,7 +300,7 @@ plot(plots..., layout=(4,1), legend=false, title=["sin" "cos" "tan" "sinc"])
|
||||
```
|
||||
|
||||
|
||||
Layouts can also be nested and explicit width/height proportions can be specified using the `@layout` macro:
|
||||
Man kann Layouts auch schachteln und mit dem `@layout`-Macro explizite Breiten/Höhenanteile vorgeben:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -317,27 +317,27 @@ plot(plots..., layout=mylayout, legend=false, title=["sin" "cos" "tan" "sinc"])
|
||||
|
||||
### Backends
|
||||
|
||||
`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.
|
||||
`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.
|
||||
|
||||
However, not all _backends_ support all plot types and attributes. An overview is available [here](https://docs.juliaplots.org/stable/generated/supported/).
|
||||
Allerdings unterstützen nicht alle _backends_ alle Plot-Typen und -Attribute. Einen Überblick gibt es [hier](https://docs.juliaplots.org/stable/generated/supported/).
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
```{julia}
|
||||
using Plots
|
||||
backend() # display the selected backend, GR is the default
|
||||
backend() # Anzeige des gewählten backends, GR ist der default
|
||||
```
|
||||
|
||||
|
||||
Another example
|
||||
Nochmal ein Beispiel
|
||||
```{julia}
|
||||
x = 1:30
|
||||
y = rand(30)
|
||||
plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Wasserstand")
|
||||
```
|
||||
|
||||
and here the same plot with the `PlotlyJS` backend.
|
||||
und hier derselbe Plot mit dem `PlotlyJS`-Backend.
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -345,22 +345,22 @@ plotlyjs() # change plots backend
|
||||
plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Wasserstand")
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
```{julia}
|
||||
gr() # return to GR as backend
|
||||
gr() # zurück zu GR als backend
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 3D Plots
|
||||
|
||||
The functions `surface()` and `contour()` allow plotting of a function $f(x,y)$. The required arguments are:
|
||||
Die Funktionen `surface()` und `contour()` ermöglichen den Plot einer Funktion $f(x,y)$. Als Argumente werden benötigt:
|
||||
|
||||
- a set (vector) $X$ of $x$-values,
|
||||
- a set (vector) $Y$ of $y$-values and
|
||||
- a function of two variables that is then evaluated on $X \times Y$ and plotted.
|
||||
- eine Menge (Vektor) $X$ von $x$-Werten,
|
||||
- eine Menge (Vektor) $Y$ von $y$-Werten und
|
||||
- eine Funktion von zwei Variablen, die dann auf $X \times Y$ ausgewertet und geplottet wird.
|
||||
|
||||
```{julia}
|
||||
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)
|
||||
```
|
||||
|
||||
Curves (or simply point sets) in three dimensions can be plotted by calling `plot()` with 3 vectors
|
||||
containing the $x$, $y$ and $z$-coordinates of the data points, respectively.
|
||||
Kurven (oder auch einfach Punktmengen) in drei Dimensionen lassen sich plotten, indem man `plot()` mit 3 Vektoren
|
||||
aufruft, die jeweils die $x$, $y$ und $z$-Koordinaten der Datenpunkte enthalten.
|
||||
|
||||
```{julia}
|
||||
plotlyjs()
|
||||
@@ -387,25 +387,25 @@ plot(x, y, z, zcolor=reverse(z), markersize=3, markershape= :circle,
|
||||
|
||||
```
|
||||
|
||||
> We use the `plotlyjs` backend here, so the plot is interactive and can be rotated and zoomed with the mouse.
|
||||
> Wir verwenden mal das `plotlyjs`-Backend, damit ist der Plot interaktiv und kann mit der Maus gedreht und gezoomt werden.
|
||||
|
||||
### Plots.jl and _recipes_
|
||||
### Plots.jl und _recipes_
|
||||
|
||||
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.:
|
||||
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.:
|
||||
|
||||
- `StatsPlots.jl` direct plotting of _Dataframes_, special statistical plots, etc. or
|
||||
- `GraphRecipes.jl` [Plotting of graph structures](https://docs.juliaplots.org/latest/GraphRecipes/examples/)
|
||||
- `StatsPlots.jl` direktes Plotten von _Dataframes_, spezielle statistische Plots usw. oder
|
||||
- `GraphRecipes.jl` [Plotten von Graphstrukturen](https://docs.juliaplots.org/latest/GraphRecipes/examples/)
|
||||
|
||||
|
||||
### A Bar Chart
|
||||
### Ein Säulendiagramm
|
||||
|
||||
For the last example, we load a package that provides over 700 free (_"public domain"_) datasets, including, for example:
|
||||
Für das letzte Beispiel laden wir ein Paket, das über 700 freie (_"public domain"_) Datensätze, darunter z.B:
|
||||
|
||||
- the passenger list of the _Titanic_,
|
||||
- fuel consumption data of American cars from the 70s or
|
||||
- historical exchange rates
|
||||
- die Passagierliste der _Titanic_,
|
||||
- Verbrauchsdaten amerikanischer Autos aus den 70ern oder
|
||||
- historische Währungskurse
|
||||
|
||||
provides:
|
||||
bereitstellt:
|
||||
|
||||
```{julia}
|
||||
using RDatasets
|
||||
@@ -419,13 +419,13 @@ using RDatasets
|
||||
#RDatasets.datasets()
|
||||
```
|
||||
|
||||
The dataset ["Motor Trend Car Road Tests"](https://rdrr.io/r/datasets/mtcars.html)
|
||||
Der Datensatz ["Motor Trend Car Road Tests"](https://rdrr.io/r/datasets/mtcars.html)
|
||||
|
||||
```{julia}
|
||||
cars = dataset("datasets", "mtcars")
|
||||
```
|
||||
|
||||
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!)
|
||||
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!)
|
||||
|
||||
```{julia}
|
||||
theme(:bright)
|
||||
@@ -443,10 +443,10 @@ bar(cars.Model, cars.MPG,
|
||||
```
|
||||
|
||||
|
||||
### What is Missing: Animation
|
||||
### Was noch fehlt: Animation
|
||||
|
||||
Please refer to the [documentation](https://docs.juliaplots.org/latest/animations/) and only an example
|
||||
(from <https://www.juliafordatascience.com/animations-with-plots-jl/>) is given:
|
||||
Hier sei auf die [Dokumentation](https://docs.juliaplots.org/latest/animations/) verwiesen und nur ein Beispiel
|
||||
(von <https://www.juliafordatascience.com/animations-with-plots-jl/>) angegeben:
|
||||
|
||||
```{julia}
|
||||
#| error: false
|
||||
|
||||
@@ -2,18 +2,7 @@
|
||||
engine: julia
|
||||
---
|
||||
|
||||
```{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
|
||||
# Arbeit mit Julia: REPL, Pakete, Introspection
|
||||
|
||||
```{julia}
|
||||
#| error: false
|
||||
@@ -28,36 +17,37 @@ Base.active_module() = myactive_module()
|
||||
# https://github.com/JuliaLang/julia/blob/master/base/show.jl#L3073-L3077
|
||||
```
|
||||
|
||||
## Documentation
|
||||
## Dokumentation
|
||||
|
||||
The official Julia documentation [https://docs.julialang.org/](https://docs.julialang.org/) contains numerous overviews, including:
|
||||
Die offizielle Julia-Dokumentation [https://docs.julialang.org/](https://docs.julialang.org/) enthält zahlreiche Übersichten, darunter:
|
||||
|
||||
- [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)
|
||||
|
||||
After starting Julia in a terminal, you can enter both Julia code and various commands:
|
||||
Nach dem Start von Julia in einem Terminal kann man neben Julia-Code auch verschiedene Kommandos eingeben
|
||||
|
||||
:::{.narrow}
|
||||
| Command | Effect |
|
||||
| Kommando | Wirkung |
|
||||
| :----------------------------| :------------------------ |
|
||||
| `exit()` or `Ctrl-d` | exit Julia |
|
||||
| `exit()` oder `Ctrl-d` | exit Julia |
|
||||
| `Ctrl-c` | interrupt |
|
||||
| `Ctrl-l` | clear screen |
|
||||
| End command with `;` | suppress output |
|
||||
| `include("filename.jl")` | read and execute file with Julia code |
|
||||
| Kommando mit `;` beenden | Ausgabe unterdrückt |
|
||||
| `include("filename.jl")` | Datei mit Julia-Code einlesen und ausführen |
|
||||
|
||||
|
||||
|
||||
The REPL has several modes:
|
||||
|
||||
| Mode | Prompt | Start mode | Exit mode |
|
||||
Der REPL hat verschiedene Modi:
|
||||
|
||||
| Modus | Prompt | Modus starten | Modus verlassen |
|
||||
| :- | :- | :- | :- |
|
||||
| default| `julia>` | | `Ctrl-d` (exits Julia) |
|
||||
| default| `julia>` | | `Ctrl-d` (beendet Julia) |
|
||||
| Package manager | `pkg>` | `]` | `backspace` |
|
||||
| Help | `help?>` | `?`| `backspace `|
|
||||
|Shell | `shell>` | `;` | `backspace`|
|
||||
@@ -65,12 +55,12 @@ The REPL has several modes:
|
||||
:::
|
||||
|
||||
|
||||
## Jupyter Notebooks (IJulia)
|
||||
## Jupyter-Notebooks (IJulia)
|
||||
|
||||
|
||||
In a Jupyter notebook, the modes are usable as single-line commands in their own input cells:
|
||||
In einem Jupyter-Notebook sind die Modi sind als Einzeiler in einer eigenen Input-Zelle nutzbar:
|
||||
|
||||
(i) a package manager command:
|
||||
(i) ein Kommando des Paket-Managers:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -78,7 +68,7 @@ In a Jupyter notebook, the modes are usable as single-line commands in their own
|
||||
] status
|
||||
```
|
||||
|
||||
(ii) a help query:
|
||||
(ii) eine Help-Abfrage:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -86,7 +76,7 @@ In a Jupyter notebook, the modes are usable as single-line commands in their own
|
||||
?sin
|
||||
```
|
||||
|
||||
(iii) a shell command:
|
||||
(iii) Ein Shell-Kommando:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -94,33 +84,33 @@ In a Jupyter notebook, the modes are usable as single-line commands in their own
|
||||
;ls
|
||||
```
|
||||
|
||||
## The Package Manager
|
||||
## Der Paketmanager
|
||||
|
||||
An important part of the _Julia ecosystem_ is the numerous packages that extend Julia.
|
||||
Wichtiger Teil des _Julia Ecosystems_ sind die zahlreichen Pakete, die Julia erweitern.
|
||||
|
||||
- Some packages are part of every Julia installation and only need to be activated with a `using Packagename` statement.
|
||||
- They form the so-called _standard library_, which includes
|
||||
- `LinearAlgebra`, `Statistics`, `SparseArrays`, `Printf`, `Pkg`, and others.
|
||||
- Over 9000 packages are officially registered, see [https://julialang.org/packages/](https://julialang.org/packages/).
|
||||
- These can be downloaded and installed with just a few keystrokes.
|
||||
- The _package manager_ `Pkg` is used for this purpose.
|
||||
- It can be used in two ways:
|
||||
- as normal Julia statements that can also be in a `.jl` program file:
|
||||
- Einige Pakete sind Teil jeder Julia-Installation und müssen nur mit einer `using Paketname`-Anweisung aktiviert werden.
|
||||
- Sie bilden die sogenannte _Standard Library_ und dazu gehören
|
||||
- `LinearAlgebra`, `Statistics`, `SparseArrays`, `Printf`, `Pkg` und andere.
|
||||
- Über 9000 Pakete sind offiziell registriert, siehe [https://julialang.org/packages/](https://julialang.org/packages/).
|
||||
- Diese können mit wenigen Tastendrücken heruntergeladen und installiert werden.
|
||||
- Dazu dient der _package manager_ `Pkg`.
|
||||
- Man kann ihn auf zwei Arten verwenden:
|
||||
- als normale Julia-Anweisungen, die auch in einer `.jl`-Programmdatei stehen können:
|
||||
```
|
||||
using Pkg
|
||||
Pkg.add("PackageXY")
|
||||
Pkg.add("PaketXY")
|
||||
```
|
||||
- in the special pkg-mode of the Julia REPL:
|
||||
- im speziellen pkg-Modus des Julia-REPLs:
|
||||
```
|
||||
] add PackageXY
|
||||
] add PaketXY
|
||||
```
|
||||
- Afterward, the package can be used with `using PackageXY`.
|
||||
- You can also install packages from other sources and self-written packages.
|
||||
- Anschließend kann das Paket mit `using PaketXY` verwendet werden.
|
||||
- Man kann auch Pakete aus anderen Quellen und selbstgeschriebene Pakete installieren.
|
||||
|
||||
|
||||
### Some Package Manager Functions
|
||||
|
||||
### Einige Funktionen des Paketmanagers
|
||||
|
||||
| Function | `pkg` - Mode | Explanation |
|
||||
| Funktion | `pkg` - Mode | Erklärung |
|
||||
|:------------------------|:--------------------------| :-------------------------------------------------------|
|
||||
| `Pkg.add("MyPack")` | `pkg> add MyPack` | add `MyPack.jl` to current environment |
|
||||
| `Pkg.rm("MyPack")` | `pkg> remove MyPack` | remove `MyPack.jl` from current environment |
|
||||
@@ -130,13 +120,13 @@ An important part of the _Julia ecosystem_ is the numerous packages that extend
|
||||
| `Pkg.instantiate()` | `pg> instantiate` | install all packages according to `Project.toml` |
|
||||
|
||||
|
||||
### Installed Packages and Environments
|
||||
### Installierte Pakete und Environments
|
||||
|
||||
- Julia and the package manager maintain
|
||||
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. a list of all packages installed as implicit dependencies in the file `Manifest.toml`.
|
||||
- The directory in which these files are located is the `environment` and is displayed with `Pkg.status()` or `]status`.
|
||||
- In the normal case, this looks like this:
|
||||
- Julia und der Paketmanager verwalten
|
||||
1. eine Liste der mit dem Kommando `Pkg.add()` bzw. `]add` explizit installierten Pakete mit genauer Versionsbezeichnung in einer Datei `Project.toml` und
|
||||
2. eine Liste aller dabei auch als implizite Abhängigkeiten installierten Pakete in der Datei `Manifest.toml`.
|
||||
- Das Verzeichnis, in dem diese Dateien stehen, ist das `environment` und wird mit `Pkg.status()` bzw. `]status` angezeigt.
|
||||
- Im Normalfall sieht das so aus:
|
||||
|
||||
```
|
||||
(@v1.10) pkg> status
|
||||
@@ -147,18 +137,18 @@ An important part of the _Julia ecosystem_ is the numerous packages that extend
|
||||
[295af30f] Revise v3.5.14
|
||||
```
|
||||
|
||||
- You can use separate `environments` for different projects. You can either start Julia with
|
||||
- Man kann für verschiedene Projekte eigene `environments` benutzen. Dazu kann man entweder Julia mit
|
||||
```shell
|
||||
julia --project=path/to/myproject
|
||||
```
|
||||
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`)
|
||||
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`)
|
||||
|
||||
|
||||
### For Installing Packages on Our Jupyter Server `misun103`:
|
||||
### Zum Installieren von Paketen auf unserem Jupyter-Server `misun103`:
|
||||
|
||||
- There is a central repository in which all packages mentioned in this course are already installed.
|
||||
- There you have no write permissions.
|
||||
- However, you can install additional packages in your `HOME`. As a first command, you need to activate the current directory:
|
||||
- Es gibt ein zentrales Repository, in dem alle in diesem Kurs erwähnten Pakete bereits installiert sind.
|
||||
- Dort haben Sie keine Schreibrechte.
|
||||
- Sie können aber zusätzliche Pakete in Ihrem `HOME` installieren. Dazu ist als erster Befehl nötig, das aktuelle Verzeichnis zu aktivieren:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -166,27 +156,26 @@ or activate the environment in Julia with `Pkg.activate("path/to/myproject")`. T
|
||||
] activate .
|
||||
```
|
||||
|
||||
(Note the dot!)
|
||||
(Man beachte den Punkt!)
|
||||
|
||||
|
||||
|
||||
|
||||
After that, you can install packages with `add` in the pkg-mode:
|
||||
Danach können Sie mit `add` im Pkg-Modus auch Pakete installieren:
|
||||
|
||||
```{julia}
|
||||
#| eval: false
|
||||
] add PackageXY
|
||||
] add PaketXY
|
||||
```
|
||||
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
## The Julia JIT _(just in time)_ Compiler: Introspection
|
||||
|
||||
Julia is built on the tools of the _LLVM Compiler Infrastructure Project_.
|
||||
## Der Julia JIT _(just in time)_ Compiler: Introspection
|
||||
|
||||
Julia baut auf die Werkzeuge des _LLVM Compiler Infrastructure Projects_ auf.
|
||||
|
||||
:::{.narrow}
|
||||
Stages of Compilation
|
||||
@@ -246,3 +235,5 @@ walk_tree(p)
|
||||
```{julia}
|
||||
@code_native f(2,4)
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -2,65 +2,73 @@
|
||||
engine: julia
|
||||
---
|
||||
|
||||
# Containers
|
||||
```{julia}
|
||||
#| 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`.
|
||||
|
||||
These containers are:
|
||||
# Container
|
||||
|
||||
- **iterable:** You can iterate over the elements of the container:
|
||||
Julia bietet eine große Auswahl von Containertypen mit weitgehend ähnlichem Interface an.
|
||||
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
|
||||
for x ∈ container ... end
|
||||
```
|
||||
- **indexable:** You can access elements via their index:
|
||||
- **indizierbar:** Man kann auf Elemente über ihren Index zugreifen:
|
||||
```julia
|
||||
x = container[i]
|
||||
```
|
||||
and some are also
|
||||
```
|
||||
und einige sind auch
|
||||
|
||||
- **mutable:** You can add, remove, and modify elements.
|
||||
- **mutierbar**: Man kann Elemente hinzufügen, entfernen und ändern.
|
||||
|
||||
Furthermore, there are several common functions, e.g.,
|
||||
Weiterhin gibt es eine Reihe gemeinsamer Funktionen, z.B.
|
||||
|
||||
- `length(container)` --- number of elements
|
||||
- `eltype(container)` --- type of elements
|
||||
- `isempty(container)` --- test whether container is empty
|
||||
- `empty!(container)` --- empties container (only if mutable)
|
||||
- `length(container)` --- Anzahl der Elemente
|
||||
- `eltype(container)` --- Typ der Elemente
|
||||
- `isempty(container)` --- Test, ob Container leer ist
|
||||
- `empty!(container)` --- leert Container (nur wenn mutierbar)
|
||||
|
||||
|
||||
## Tuples
|
||||
## Tupeln
|
||||
|
||||
A tuple is an immutable container of elements. It is therefore not possible to add new elements or change the value of an element.
|
||||
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.
|
||||
|
||||
|
||||
|
||||
```{julia}
|
||||
t = (33, 4.5, "Hello")
|
||||
|
||||
@show t[2] # indexable
|
||||
@show t[2] # indizierbar
|
||||
|
||||
for i ∈ t println(i) end # iterable
|
||||
for i ∈ t println(i) end # iterierbar
|
||||
```
|
||||
|
||||
A tuple is an **inhomogeneous** type. Each element has its own type, which is reflected in the tuple's type:
|
||||
Ein Tupel ist ein **inhomogener** Typ. Jedes Element hat seinen eigenen Typ und das zeigt sich auch im Typ des Tupels:
|
||||
|
||||
```{julia}
|
||||
typeof(t)
|
||||
```
|
||||
|
||||
|
||||
Tuples are frequently used as function return values to return more than one object.
|
||||
Man verwendet Tupel gerne als Rückgabewerte von Funktionen, um mehr als ein Objekt zurückzulieferen.
|
||||
|
||||
```{julia}
|
||||
# Integer division and remainder:
|
||||
# quotient and remainder are assigned to variables q and r
|
||||
# Ganzzahldivision und Rest:
|
||||
# Quotient und Rest werden den Variablen q und r zugewiesen
|
||||
|
||||
q, r = divrem(71, 6)
|
||||
@show q r;
|
||||
```
|
||||
As you can see here, parentheses can be omitted in certain constructs.
|
||||
This *implicit tuple packing/unpacking* is also commonly used in multiple assignments:
|
||||
Wie man hier sieht, kann man in bestimmten Konstrukten die Klammern auch weglassen.
|
||||
Dieses *implict tuple packing/unpacking* verwendet man auch gerne in Mehrfachzuweisungen:
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -72,59 +80,56 @@ x, y, z = 12, 17, 203
|
||||
y
|
||||
```
|
||||
|
||||
Some functions require tuples as arguments or always return tuples. Then you sometimes need a tuple with a single element.
|
||||
Manche Funktionen bestehen auf Tupeln als Argument oder geben immer Tupeln zurück. Dann braucht man manchmal ein Tupel aus einem Element.
|
||||
|
||||
This is written as:
|
||||
Das notiert man so:
|
||||
|
||||
```{julia}
|
||||
x = (13,) # a 1-element tuple
|
||||
x = (13,) # ein 1-Element-Tupel
|
||||
```
|
||||
|
||||
The comma - not the parentheses - makes the tuple.
|
||||
Das Komma - und nicht die Klammern -- macht das Tupel.
|
||||
|
||||
```{julia}
|
||||
x= (13) # not a tuple
|
||||
x= (13) # kein Tupel
|
||||
```
|
||||
|
||||
|
||||
## Ranges
|
||||
|
||||
We have already used *range* objects in numerical `for` loops.
|
||||
Wir haben *range*-Objekte schon in numerischen `for`-Schleifen verwendet.
|
||||
|
||||
```{julia}
|
||||
r = 1:1000
|
||||
typeof(r)
|
||||
```
|
||||
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()`.
|
||||
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()`.
|
||||
|
||||
The colon is a special syntax.
|
||||
Der Doppelpunkt ist eine spezielle Syntax.
|
||||
|
||||
- `a:b` is parsed as `range(a, b)`
|
||||
- `a:b:c` is parsed as `range(a, c, step=b)`
|
||||
- `a:b` wird vom Parser umgesetzt zu `range(a, b)`
|
||||
- `a:b:c` wird umgesetzt zu `range(a, c, step=b)`
|
||||
|
||||
|
||||
|
||||
*Ranges* are obviously iterable, not mutable, but indexable.
|
||||
*Ranges* sind offensichtlich iterierbar, nicht mutierbar aber indizierbar.
|
||||
|
||||
```{julia}
|
||||
(3:100)[20] # the 20th element
|
||||
(3:100)[20] # das zwanzigste Element
|
||||
```
|
||||
|
||||
|
||||
|
||||
Wir erinnern an die Semantik der `for`-Schleife: `for i in 1:1000` heißt **nicht**:
|
||||
|
||||
Recall the semantics of the `for` loop: `for i in 1:1000` means **not**:
|
||||
- 'Die Schleifenvariable `i` wird bei jedem Durchlauf um eins erhöht' **sondern**
|
||||
- 'Der Schleifenvariable werden nacheinander die Werte 1,2,3,...,1000 aus dem Container zugewiesen'.
|
||||
|
||||
- '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'.
|
||||
Allerdings wäre es sehr ineffektiv, diesen Container tatsächlich explizit anzulegen.
|
||||
|
||||
However, it would be very inefficient to actually create this container explicitly.
|
||||
- _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.
|
||||
- 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`.
|
||||
|
||||
- _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.
|
||||
Das Macro `@allocated` gibt aus, wieviel Bytes an Speicher bei der Auswertung eines Ausdrucks alloziert wurden.
|
||||
|
||||
```{julia}
|
||||
@allocated r = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
|
||||
@@ -137,35 +142,34 @@ The macro `@allocated` outputs how many bytes of memory were allocated during th
|
||||
|
||||
|
||||
|
||||
|
||||
The function `collect()` is used to convert to a "real" vector.
|
||||
Zum Umwandeln in einen 'richtigen' Vektor dient die Funktion `collect()`.
|
||||
|
||||
|
||||
```{julia}
|
||||
collect(20:-3:1)
|
||||
```
|
||||
|
||||
Quite useful, e.g., when preparing data for plotting, is the *range* type `LinRange`.
|
||||
Recht nützlich, z.B. beim Vorbereiten von Daten zum Plotten, ist der *range*-Typ `LinRange`.
|
||||
|
||||
```{julia}
|
||||
LinRange(2, 50, 300)
|
||||
```
|
||||
`LinRange(start, stop, n)` generates an equidistant list of `n` values where the first and last are the specified limits.
|
||||
With `collect()` you can also obtain the corresponding vector if needed.
|
||||
`LinRange(start, stop, n)` erzeugt eine äquidistante Liste von `n` Werten von denen der erste und der letzte die vorgegebenen Grenzen sind.
|
||||
Mit `collect()` kann man bei Bedarf auch daraus den entsprechenden Vektor gewinnen.
|
||||
|
||||
|
||||
## Dictionaries
|
||||
|
||||
- _Dictionaries_ (German: "associative list" or "lookup table" or ...) are special containers.
|
||||
- Entries in a vector `v` are addressable by an index 1,2,3....: `v[i]`
|
||||
- Entries in a _dictionary_ are addressable by more general _keys_.
|
||||
- A _dictionary_ is a collection of _key-value_ pairs.
|
||||
- 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_.
|
||||
- _Dictionaries_ (deutsch: "assoziative Liste" oder "Zuordnungstabelle" oder ...) sind spezielle Container.
|
||||
- Einträge in einem Vektor `v` sind durch einen Index 1,2,3.... addressierbar: `v[i]`
|
||||
- Einträge in einem _dictionary_ sind durch allgemeinere _keys_ addressierbar.
|
||||
- Ein _dictionary_ ist eine Ansammlung von _key-value_-Paaren.
|
||||
- Damit haben _dictionaries_ in Julia den parametrisierten Typ `Dict{S,T}`, wobei `S` der Typ der _keys_ und `T` der Typ der _values_ ist
|
||||
|
||||
|
||||
They can be created explicitly:
|
||||
Man kann sie explizit anlegen:
|
||||
```{julia}
|
||||
# Population in 2020 in millions, source: wikipedia
|
||||
# Einwohner 2020 in Millionen, Quelle: wikipedia
|
||||
|
||||
EW = Dict("Berlin" => 3.66, "Hamburg" => 1.85,
|
||||
"München" => 1.49, "Köln" => 1.08)
|
||||
@@ -176,29 +180,29 @@ EW = Dict("Berlin" => 3.66, "Hamburg" => 1.85,
|
||||
typeof(EW)
|
||||
```
|
||||
|
||||
and indexed with the _keys_:
|
||||
und mit den _keys_ indizieren:
|
||||
|
||||
```{julia}
|
||||
EW["Berlin"]
|
||||
```
|
||||
|
||||
Of course, querying a non-existent _key_ is an error.
|
||||
Das Abfragen eines nicht existierenden _keys_ ist natürlich ein Fehler.
|
||||
```{julia}
|
||||
EW["Leipzig"]
|
||||
```
|
||||
|
||||
You can also ask beforehand...
|
||||
Man kann ja auch vorher mal anfragen...
|
||||
```{julia}
|
||||
haskey(EW, "Leipzig")
|
||||
```
|
||||
|
||||
... or use the function `get(dict, key, default)`, which does not throw an error for non-existent keys but returns the third argument.
|
||||
... oder die Funktion `get(dict, key, default)` benutzen, die bei nicht existierendem Key keinen Fehler wirft sondern das 3. Argument zurückgibt.
|
||||
|
||||
```{julia}
|
||||
@show get(EW, "Leipzig", -1) get(EW, "Berlin", -1);
|
||||
```
|
||||
|
||||
You can also request all `keys` and `values` as special containers.
|
||||
Man kann sich auch alle `keys` und `values` als spezielle Container geben lassen.
|
||||
```{julia}
|
||||
keys(EW)
|
||||
```
|
||||
@@ -209,24 +213,24 @@ values(EW)
|
||||
```
|
||||
|
||||
|
||||
You can iterate over the `keys`...
|
||||
Man kann über die `keys` iterieren...
|
||||
```{julia}
|
||||
for i in keys(EW)
|
||||
n = EW[i]
|
||||
println("The city $i has $n million inhabitants.")
|
||||
println("Die Stadt $i hat $n Millionen Einwohner.")
|
||||
end
|
||||
```
|
||||
|
||||
or directly over `key-value` pairs.
|
||||
odere gleich über `key-value`-Paare.
|
||||
```{julia}
|
||||
for (stadt, ew) ∈ EW
|
||||
println("$stadt : $ew Million.")
|
||||
println("$stadt : $ew Mill.")
|
||||
end
|
||||
```
|
||||
|
||||
### Extending and Modifying
|
||||
### Erweitern und Modifizieren
|
||||
|
||||
You can add additional `key-value` pairs to a `Dict`...
|
||||
Man kann in ein `Dict` zusätzliche `key-value`-Paare eintragen...
|
||||
```{julia}
|
||||
EW["Leipzig"] = 0.52
|
||||
EW["Dresden"] = 0.52
|
||||
@@ -234,42 +238,42 @@ EW
|
||||
```
|
||||
|
||||
|
||||
and change a `value`.
|
||||
und einen `value` ändern.
|
||||
```{julia}
|
||||
# Oh, the Leipzig number was from 2010, not 2020
|
||||
# Oh, das war bei Leipzig die Zahl von 2010, nicht 2020
|
||||
|
||||
EW["Leipzig"] = 0.597
|
||||
EW
|
||||
```
|
||||
|
||||
A pair can also be deleted via its `key`.
|
||||
Ein Paar kann über seinen `key` auch gelöscht werden.
|
||||
```{julia}
|
||||
delete!(EW, "Dresden")
|
||||
```
|
||||
|
||||
Many functions can work with `Dicts` like with other containers.
|
||||
Zahlreiche Funktionen können mit `Dicts` wie mit anderen Containern arbeiten.
|
||||
|
||||
```{julia}
|
||||
maximum(values(EW))
|
||||
```
|
||||
|
||||
### Creating an Empty Dictionary
|
||||
### Anlegen eines leeren Dictionaries
|
||||
|
||||
Without type specification ...
|
||||
Ohne Typspezifikation ...
|
||||
```{julia}
|
||||
d1 = Dict()
|
||||
```
|
||||
|
||||
and with type specification:
|
||||
und mit Typspezifikation:
|
||||
```{julia}
|
||||
d2 = Dict{String, Int}()
|
||||
```
|
||||
|
||||
### Conversion to Vectors: `collect()`
|
||||
### Umwandlung in Vektoren: `collect()`
|
||||
|
||||
- `keys(dict)` and `values(dict)` are special data types.
|
||||
- The function `collect()` converts them to a `Vector` type.
|
||||
- `collect(dict)` returns a list of type `Vector{Pair{S,T}}`
|
||||
- `keys(dict)` und `values(dict)` sind spezielle Datentypen.
|
||||
- Die Funktion `collect()` macht daraus eine Liste vom Typ `Vector`.
|
||||
- `collect(dict)` liefert eine Liste vom Typ `Vector{Pair{S,T}}`
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -281,55 +285,55 @@ collect(EW)
|
||||
collect(keys(EW)), collect(values(EW))
|
||||
```
|
||||
|
||||
### Ordered Iteration over a Dictionary
|
||||
### Geordnetes Iterieren über ein Dictionary
|
||||
|
||||
We sort the keys. As strings, they are sorted alphabetically. With the `rev` parameter, sorting is done in reverse order.
|
||||
Wir sortieren die Keys. Als Strings werden sie alphabetisch sortiert. Mit dem `rev`-Parameter wird rückwärts sortiert.
|
||||
```{julia}
|
||||
for k in sort(collect(keys(EW)), rev = true)
|
||||
n = EW[k]
|
||||
println("$k has $n million inhabitants ")
|
||||
println("$k hat $n Millionen Einw. ")
|
||||
end
|
||||
```
|
||||
|
||||
We sort `collect(dict)`. This is a vector of pairs. With `by` we define what to sort by: the second element of the pair.
|
||||
Wir sortieren `collect(dict)`. Das ist ein Vektor von Paaren. Mit `by` definieren wir, wonach zu sortieren ist: nach dem 2. Element des Paares.
|
||||
|
||||
```{julia}
|
||||
for (k,v) in sort(collect(EW), by = pair -> last(pair), rev=false)
|
||||
println("$k has $v million inhabitants")
|
||||
println("$k hat $v Mill. EW")
|
||||
end
|
||||
```
|
||||
|
||||
### An Application of Dictionaries: Counting Frequencies
|
||||
### Eine Anwendung von Dictionaries: Zählen von Häufigkeiten
|
||||
|
||||
We do "experimental probability" with 2 dice:
|
||||
Wir machen 'experimentelle Stochastik' mit 2 Würfeln:
|
||||
|
||||
Given `l`, a list with the results of 100,000 double dice rolls, i.e., 100,000 numbers between 2 and 12.
|
||||
Gegeben sei `l`, eine Liste mit den Ergebnissen von 100 000 Pasch-Würfen, also 100 000 Zahlen zwischen 2 und 12.
|
||||
|
||||
How frequently do the numbers 2 to 12 occur?
|
||||
Wie häufig sind die Zahlen 2 bis 12?
|
||||
|
||||
|
||||
We (let) roll:
|
||||
Wir (lassen) würfeln:
|
||||
|
||||
```{julia}
|
||||
|
||||
l = rand(1:6, 100_000) .+ rand(1:6, 100_000)
|
||||
```
|
||||
|
||||
We count the frequencies of the events using a dictionary. We take the event as the `key` and its frequency as the `value`.
|
||||
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`.
|
||||
```{julia}
|
||||
# In this case, one could also solve this with a simple vector.
|
||||
# A better illustration would be, e.g., word frequency in
|
||||
# a text. Then i is not an integer but a word=string
|
||||
# In diesem Fall könnte man das auch mit einem einfachen Vektor
|
||||
# lösen. Eine bessere Illustration wäre z.B. Worthäufigkeit in
|
||||
# einem Text. Dann ist i keine ganze Zahl sondern ein Wort=String
|
||||
|
||||
d = Dict{Int,Int}() # the dict for counting
|
||||
d = Dict{Int,Int}() # das Dict zum 'reinzählen'
|
||||
|
||||
for i in l # for each i, d[i] is incremented.
|
||||
for i in l # für jedes i wird d[i] erhöht.
|
||||
d[i] = get(d, i, 0) + 1
|
||||
end
|
||||
d
|
||||
```
|
||||
|
||||
The result:
|
||||
Das Ergebnis:
|
||||
|
||||
```{julia}
|
||||
using Plots
|
||||
@@ -337,6 +341,7 @@ using Plots
|
||||
plot(collect(keys(d)), collect(values(d)), seriestype=:scatter)
|
||||
```
|
||||
|
||||
##### The explanatory image:
|
||||
##### Das Erklär-Bild dazu:
|
||||
|
||||
[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
|
||||
---
|
||||
|
||||
# Functions and Operators
|
||||
# Funktionen und Operatoren
|
||||
|
||||
```{julia}
|
||||
#| error: false
|
||||
@@ -18,36 +18,36 @@ Base.active_module() = myactive_module()
|
||||
```
|
||||
|
||||
|
||||
Functions process their arguments to produce a result, which they return when called.
|
||||
Funktionen verarbeiten ihre Argumente zu einem Ergebnis, das sie beim Aufruf zurückliefern.
|
||||
|
||||
## Forms
|
||||
## Formen
|
||||
|
||||
Functions can be defined in different forms:
|
||||
Funktionen können in verschiedenen Formen definiert werden:
|
||||
|
||||
I. As a `function ... end` block
|
||||
I. Als `function ... end`-Block
|
||||
```{julia}
|
||||
function hyp(x,y)
|
||||
sqrt(x^2+y^2)
|
||||
end
|
||||
```
|
||||
II. As a "single-liner"
|
||||
II. Als "Einzeiler"
|
||||
```{julia}
|
||||
hyp(x, y) = sqrt(x^2 + y^2)
|
||||
```
|
||||
III. As anonymous functions
|
||||
III. Als anonyme Funktionen
|
||||
|
||||
```{julia}
|
||||
(x, y) -> sqrt(x^2 + y^2)
|
||||
```
|
||||
|
||||
|
||||
### Block Form and `return`
|
||||
|
||||
### Block-Form und `return`
|
||||
|
||||
|
||||
- With `return`, function execution is terminated and control returns to the calling context.
|
||||
- Without `return`, the value of the last expression is returned as the function value.
|
||||
- Mit `return` wird die Abarbeitung der Funktion beendet und zum aufrufenden Kontext zurückgekehrt.
|
||||
- Ohne `return` wird der Wert des letzten Ausdrucks als Funktionswert zurückgegeben.
|
||||
|
||||
The two definitions
|
||||
Die beiden Definitionen
|
||||
|
||||
```julia
|
||||
function xsinrecipx(x)
|
||||
@@ -57,7 +57,7 @@ function xsinrecipx(x)
|
||||
return x * sin(1/x)
|
||||
end
|
||||
```
|
||||
and without the second explicit `return` in the last line:
|
||||
und ohne das zweite explizite `return` in der letzten Zeile:
|
||||
|
||||
```julia
|
||||
function xsinrecipx(x)
|
||||
@@ -68,11 +68,11 @@ function xsinrecipx(x)
|
||||
end
|
||||
```
|
||||
|
||||
are therefore equivalent.
|
||||
sind also äquivalent.
|
||||
|
||||
|
||||
- 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`.)
|
||||
- An empty `return` statement is equivalent to `return nothing`.
|
||||
- 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.)
|
||||
- Eine leere `return`-Anweisung ist äquivalent zu `return nothing`.
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -95,27 +95,27 @@ a
|
||||
```
|
||||
|
||||
|
||||
### Single-liner Form
|
||||
### Einzeiler-Form
|
||||
|
||||
The single-liner form is a normal assignment where a function stands on the left side.
|
||||
Die Einzeilerform ist eine ganz normale Zuweisung, bei der links eine Funktion steht.
|
||||
|
||||
```julia
|
||||
hyp(x, y) = sqrt(x^2 + y^2)
|
||||
```
|
||||
|
||||
Julia knows two ways to combine multiple statements into a block that can stand in place of a single statement:
|
||||
Julia kennt zwei Möglichkeiten, mehrere Anweisungen zu einem Block zusammenzufassen, der an Stelle einer Einzelanweisung stehen kann:
|
||||
|
||||
- `begin ... end` block
|
||||
- Parenthesized statements separated by semicolons.
|
||||
- `begin ... end`-Block
|
||||
- Eingeklammerte durch Semikolon getrennte Anweisungen.
|
||||
|
||||
In both cases, the value of the block is the value of the last statement.
|
||||
In beiden Fällen ist der Wert des Blockes der Wert der letzten Anweisung.
|
||||
|
||||
Thus, the following also works:
|
||||
Damit funktioniert auch
|
||||
```julia
|
||||
hyp(x, y) = (z = x^2; z += y^2; sqrt(z))
|
||||
```
|
||||
|
||||
and
|
||||
und
|
||||
```julia
|
||||
hyp(x, y) = begin
|
||||
z = x^2
|
||||
@@ -124,15 +124,15 @@ hyp(x, y) = begin
|
||||
end
|
||||
```
|
||||
|
||||
### Anonymous Functions
|
||||
### Anonyme Funktionen
|
||||
|
||||
Anonymous functions can be "rescued from anonymity" by assigning them a name.
|
||||
Anonyme FUnktionen kann man der Anonymität entreisen, indem man ihnen einen Namen zuweist.
|
||||
```julia
|
||||
hyp = (x,y) -> sqrt(x^2 + y^2)
|
||||
```
|
||||
Their actual application is in calling a *(higher order)* function that expects a function as an argument.
|
||||
Ihre eigentliche Anwendung ist aber im Aufruf einer *(higher order)* Funktion, die eine Funktion als Argument erwartet.
|
||||
|
||||
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:
|
||||
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)`:
|
||||
|
||||
```{julia}
|
||||
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 )
|
||||
```
|
||||
|
||||
Another example is `filter(test, collection)`, where a test is a function that returns a `Bool`.
|
||||
Ein weiteres Beispiel ist `filter(test, collection)`, wobei ein Test eine Funktion ist, die ein `Bool` zurückgibt.
|
||||
```{julia}
|
||||
filter(x -> ( x%3 == 0 && x%5 == 0), 1:100 )
|
||||
```
|
||||
|
||||
## Argument Passing
|
||||
## Argumentübergabe
|
||||
|
||||
|
||||
- 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_.
|
||||
- Functions can therefore effectively modify their arguments if they are _mutable_ objects, such as `Vector` or `Array`.
|
||||
- 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.
|
||||
- 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_.
|
||||
- Funktionen können also ihre Argumente wirksam modifizieren, falls es sich um _mutable_ Objekte, wie z.B. `Vector`, `Array` handelt.
|
||||
- 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.
|
||||
|
||||
```{julia}
|
||||
V = [1, 2, 3]
|
||||
|
||||
W = fill!(V, 17)
|
||||
# '===' is test for identity
|
||||
@show V W V===W; # V and W refer to the same object
|
||||
# '===' ist Test auf Identität
|
||||
@show V W V===W; # V und W benennen dasselbe Objekt
|
||||
```
|
||||
|
||||
```{julia}
|
||||
@@ -175,16 +175,16 @@ U = fill_first!(V, 42)
|
||||
|
||||
|
||||
|
||||
## Variants of Function Arguments
|
||||
## Varianten von Funktionsargumenten
|
||||
|
||||
- There are positional arguments (1st argument, 2nd argument, ...) and _keyword_ arguments, which must be addressed by name when calling.
|
||||
- Both positional and _keyword_ arguments can have _default_ values. These arguments can be omitted when calling.
|
||||
- The order of declaration must be:
|
||||
1. Positional arguments without default value,
|
||||
2. Positional arguments with default value,
|
||||
3. --- semicolon ---,
|
||||
4. comma-separated list of keyword arguments (with or without default value)
|
||||
- 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.
|
||||
- Es gibt Positionsargumente (1. Argument, 2. Argument, ....) und _keyword_-Argumente, die beim Aufruf durch ihren Namen angesprochen werden müssen.
|
||||
- Sowohl Positions- als auch _keyword_-Argumente können _default_-Werte haben. Beim Aufruf können diese Argumente weggelassen werden.
|
||||
- Die Reihenfolge der Deklaration muss sein:
|
||||
1. Positionsargumente ohne Defaultwert,
|
||||
2. Positionsargumente mit Defaultwert,
|
||||
3. --- Semikolon ---,
|
||||
4. kommagetrennte Liste der Keywordargumente (mit oder ohne Defaultwert)
|
||||
- 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.
|
||||
|
||||
```{julia}
|
||||
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)
|
||||
```
|
||||
|
||||
A function with only _keyword_ arguments is declared as follows:
|
||||
Eine Funktion nur mit _keyword_-Argumenten wird so deklariert:
|
||||
|
||||
```{julia}
|
||||
fkw(; x=10, y) = println("x=$x, y=$y")
|
||||
@@ -204,9 +204,9 @@ fkw(y=2)
|
||||
|
||||
|
||||
|
||||
## Functions are Normal Objects
|
||||
## Funktionen sind ganz normale Objekte
|
||||
|
||||
- They can be assigned
|
||||
- Sie können zugewiesen werden
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -215,11 +215,11 @@ f2(2)
|
||||
```
|
||||
|
||||
|
||||
- They can be passed as arguments to functions.
|
||||
- Sie können als Argumente an Funktionen übergeben werden.
|
||||
|
||||
|
||||
```{julia}
|
||||
# very naive numerical integration
|
||||
# sehr naive numerische Integration
|
||||
|
||||
function Riemann_integrate(f, a, b; NInter=1000)
|
||||
delta = (b-a)/NInter
|
||||
@@ -235,7 +235,7 @@ Riemann_integrate(sin, 0, π)
|
||||
```
|
||||
|
||||
|
||||
- They can be created by functions and returned as results.
|
||||
- Sie können von Funktionen erzeugt und als Ergebnis `return`t werden.
|
||||
|
||||
|
||||
|
||||
@@ -263,16 +263,16 @@ h(1)
|
||||
h(2), h(10)
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
```{julia}
|
||||
generate_add_func(x) = y -> x + y
|
||||
```
|
||||
|
||||
|
||||
## Function Composition: the Operators $\circ$ and `|>`
|
||||
## Zusammensetzung von Funktionen: die Operatoren $\circ$ und `|>`
|
||||
|
||||
- Function composition can also be written with the $\circ$ operator (`\circ + Tab`)
|
||||
- Die Zusammensetzung _(composition)_ von Funktionen kann auch mit dem Operator $\circ$ (`\circ + Tab`) geschrieben werden
|
||||
|
||||
$$(f\circ g)(x) = f(g(x))$$
|
||||
|
||||
@@ -289,11 +289,11 @@ f(.2)
|
||||
|
||||
|
||||
```{julia}
|
||||
@show map(uppercase ∘ first, ["one", "a", "green", "leaves"]);
|
||||
@show map(uppercase ∘ first, ["ein", "paar", "grüne", "Blätter"]);
|
||||
```
|
||||
|
||||
|
||||
- There is also an operator with which functions can act "from the right" and be composed (_piping_)
|
||||
- Es gibt auch einen Operator, mit dem Funktionen "von rechts" wirken und zusammengesetzt werden können _(piping)_
|
||||
|
||||
|
||||
```{julia}
|
||||
@@ -306,37 +306,37 @@ f(.2)
|
||||
```
|
||||
|
||||
|
||||
- Of course, you can also 'broadcast' these operators (see @sec-broadcast). Here a vector of functions acts element-wise on a vector of arguments:
|
||||
- Natürlich kann man auch diese Operatoren 'broadcasten' (s. @sec-broadcast). Hier wirkt ein Vektor von Funktionen elementweise auf einen Vektor von Argumenten:
|
||||
|
||||
```{julia}
|
||||
["a", "list", "of", "strings"] .|> [length, uppercase, reverse, titlecase]
|
||||
```
|
||||
|
||||
## The `do` Notation {#sec-do}
|
||||
## Die `do`-Notation {#sec-do}
|
||||
|
||||
A syntactic peculiarity for defining anonymous functions as arguments of other functions is the `do` notation.
|
||||
Eine syntaktische Besonderheit zur Definition anonymer Funktionen als Argumente anderer Funktionen ist die `do`-Notation.
|
||||
|
||||
Let `higherfunc(f,a,...)` be a function whose first argument is a function.
|
||||
Sei `higherfunc(f,a,...)` eine Funktion, deren 1. Argument eine Funktion ist.
|
||||
|
||||
Then you can also call `higherfunc()` without the first argument and instead define the function in an immediately following `do` block:
|
||||
Dann kann man `higherfunc()` auch ohne erstes Argument aufrufen und statt dessen die Funktion in einem unmittelbar folgenden `do`-Block definieren:
|
||||
|
||||
```julia
|
||||
higherfunc(a, b) do x, y
|
||||
body of f(x,y)
|
||||
Körper von f(x,y)
|
||||
end
|
||||
```
|
||||
|
||||
Using `Riemann_integrate()` as an example, this looks like this:
|
||||
Am Beispiel von `Riemann_integrate()` sieht das so aus:
|
||||
|
||||
|
||||
```{julia}
|
||||
# this is the same as Riemann_integrate(x->x^2, 0, 2)
|
||||
# das ist dasselbe wie Riemann_integrate(x->x^2, 0, 2)
|
||||
|
||||
Riemann_integrate(0, 2) do x x^2 end
|
||||
```
|
||||
|
||||
|
||||
The purpose is of course in the application with more complex functions, such as this integrand composed of two parts:
|
||||
Der Sinn besteht natürlich in der Anwendung mit komplexeren Funktionen, wie diesem aus zwei Teilstücken zusammengesetzten Integranden:
|
||||
```{julia}
|
||||
r = Riemann_integrate(0, π) do x
|
||||
z1 = sin(x)
|
||||
@@ -349,12 +349,12 @@ r = Riemann_integrate(0, π) do x
|
||||
end
|
||||
```
|
||||
|
||||
## Function-like Objects
|
||||
## Funktionsartige Objekte
|
||||
|
||||
By defining a suitable method for a type, arbitrary objects can be made *callable*, i.e., callable like functions afterwards.
|
||||
Durch Definition einer geeigneten Methode für einen Typ kann man beliebige Objekte *callable* machen, d.h., sie anschließend wie Funktionen aufrufen.
|
||||
|
||||
```{julia}
|
||||
# struct stores the coefficients of a 2nd degree polynomial
|
||||
# struct speichert die Koeffiziente eines Polynoms 2. Grades
|
||||
struct Poly2Grad
|
||||
a0::Float64
|
||||
a1::Float64
|
||||
@@ -365,13 +365,13 @@ p1 = Poly2Grad(2,5,1)
|
||||
p2 = Poly2Grad(3,1,-0.4)
|
||||
```
|
||||
|
||||
The following method makes this structure `callable`.
|
||||
Die folgende Methode macht diese Struktur `callable`.
|
||||
```{julia}
|
||||
function (p::Poly2Grad)(x)
|
||||
p.a2 * x^2 + p.a1 * x + p.a0
|
||||
end
|
||||
```
|
||||
Now the objects can, if desired, also be used like functions.
|
||||
Jetzt kann man die Objekte, wenn gewünscht, auch wie Funktionen verwenden.
|
||||
|
||||
```{julia}
|
||||
@show p2(5) p1(-0.7) p1;
|
||||
@@ -379,9 +379,9 @@ Now the objects can, if desired, also be used like functions.
|
||||
|
||||
|
||||
|
||||
## Operators and Special Forms
|
||||
## Operatoren und spezielle Formen
|
||||
|
||||
- Infix operators like `+,*,>,∈,...` are functions.
|
||||
- Infix-Operatoren wie `+,*,>,∈,...` sind Funktionen.
|
||||
|
||||
|
||||
|
||||
@@ -399,7 +399,7 @@ f = +
|
||||
f(3, 7)
|
||||
```
|
||||
|
||||
- Even constructions like `x[i]`, `a.x`, `[x; y]` are converted by the parser to function calls.
|
||||
- Auch Konstruktionen wie `x[i]`, `a.x`, `[x; y]` werden vom Parser zu Funktionsaufrufen umgewandelt.
|
||||
|
||||
:::{.narrow}
|
||||
|
||||
@@ -410,53 +410,53 @@ f(3, 7)
|
||||
| a.x | getproperty(a, :x) |
|
||||
| a.x = z | setproperty!(a, :x, z) |
|
||||
| [x; y;...] | vcat(x, y, ...) |
|
||||
:Special Forms [(selection)](https://docs.julialang.org/en/v1/manual/functions/#Operators-With-Special-Names)
|
||||
:Spezielle Formen [(Auswahl)](https://docs.julialang.org/en/v1/manual/functions/#Operators-With-Special-Names)
|
||||
|
||||
:::
|
||||
|
||||
(The colon before a variable makes it into a symbol.)
|
||||
(Der Doppelpunkt vor einer Variablen macht diese zu einem Symbol.)
|
||||
|
||||
:::{.callout-note}
|
||||
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.
|
||||
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.
|
||||
|
||||
In principle, `get/setproperty` can also do things that have nothing to do with an actually existing field of the structure.
|
||||
Prinzipiell können `get/setproperty` auch Dinge tun, die gar nichts mit einem tatsächlich vorhandenen Feld der Struktur zu tun haben.
|
||||
:::
|
||||
|
||||
## Update Form
|
||||
## Update-Form
|
||||
|
||||
All arithmetic infix operators have an update form: The expression
|
||||
Alle arithmetischen Infix-Operatoren haben eine update-Form: Der Ausdruck
|
||||
```julia
|
||||
x = x ⊙ y
|
||||
```
|
||||
can also be written as
|
||||
kann auch geschrieben werden als
|
||||
```julia
|
||||
x ⊙= y
|
||||
```
|
||||
|
||||
Both forms are semantically equivalent. In particular, in both forms, a new object created on the right side is assigned to the variable `x`.
|
||||
Beide Formen sind semantisch äquivalent. Insbesondere wird in beiden Formen der Variablen `x` ein auf der rechten Seite geschaffenes neues Objekt zugewiesen.
|
||||
|
||||
Memory- and time-saving __in-place-update__ of an array/vector/matrix is possible either through explicit indexing
|
||||
Ein Speicherplatz- und Zeit-sparendes __in-place-update__ eines Arrays/Vektors/Matrix ist möglich entweder durch explizite Indizierung
|
||||
```julia
|
||||
for i in eachindex(x)
|
||||
x[i] += y[i]
|
||||
end
|
||||
```
|
||||
or through the semantically equivalent _broadcast_ form (see @sec-broadcast):
|
||||
oder durch die dazu semantisch äquivalente _broadcast_-Form (s. @sec-broadcast):
|
||||
```julia
|
||||
x .= x .+ y
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Operator Precedence and Associativity {#sec-vorrang}
|
||||
## Vorrang und Assoziativität von Operatoren {#sec-vorrang}
|
||||
|
||||
Expressions to be computed
|
||||
Zu berechnende Ausdrücke
|
||||
|
||||
```{julia}
|
||||
-2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2
|
||||
```
|
||||
|
||||
are converted by the parser into a tree structure.
|
||||
werden vom Parser in eine Baumstruktur überführt.
|
||||
```{julia}
|
||||
using TreeView
|
||||
|
||||
@@ -464,75 +464,75 @@ walk_tree(Meta.parse("-2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2"))
|
||||
```
|
||||
|
||||
|
||||
- The evaluation of such expressions is regulated by
|
||||
- precedence and
|
||||
- associativity.
|
||||
- 'Precedence' defines which operators bind more strongly in the sense of "multiplication and division before addition and subtraction".
|
||||
- 'Associativity' determines the evaluation order for operators of equal or same rank.
|
||||
- [Complete documentation](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity)
|
||||
- Die Auswertung solcher Ausdrücke wird durch
|
||||
- Vorrang _(precedence)_ und
|
||||
- Assoziativität geregelt.
|
||||
- 'Vorrang' definiert, welche Operatoren stärker binden im Sinne von "Punktrechnung geht vor Strichrechnung".
|
||||
- 'Assoziativität' bestimmt die Auswertungsreihenfolge bei gleichen oder gleichrangigen Operatoren.
|
||||
- [Vollständige Dokumentation](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity)
|
||||
|
||||
### Associativity
|
||||
### Assoziativität
|
||||
|
||||
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.
|
||||
Sowohl Addition und Subtraktion als auch Multiplikation und Divison sind jeweils gleichrangig und linksassoziativ, d.h. es wird von links ausgewertet.
|
||||
|
||||
```{julia}
|
||||
200/5/2 # evaluated left to right as (200/5)/2
|
||||
200/5/2 # wird von links ausgewertet als (200/5)/2
|
||||
```
|
||||
|
||||
|
||||
```{julia}
|
||||
200/2*5 # evaluated left to right as (200/2)*5
|
||||
200/2*5 # wird von links ausgewertet als (200/2)*5
|
||||
```
|
||||
|
||||
Assignments like `=`, `+=`, `*=`,... are of equal rank and right-associative.
|
||||
Zuweisungen wie `=`, `+=`, `*=`,... sind gleichrangig und rechtsassoziativ.
|
||||
|
||||
```{julia}
|
||||
x = 1
|
||||
y = 10
|
||||
|
||||
# evaluated right to left: x += (y += (z = (a = 20)))
|
||||
# wird von rechts ausgewertet: x += (y += (z = (a = 20)))
|
||||
|
||||
x += y += z = a = 20
|
||||
|
||||
@show x y z a;
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
```{julia}
|
||||
for i in (:/, :+=, :(=), :^)
|
||||
a = Base.operator_associativity(i)
|
||||
println("Operation $i is $(a)-associative")
|
||||
println("Operation $i is $(a)-assoziative")
|
||||
end
|
||||
```
|
||||
|
||||
So the power operator is right-associative.
|
||||
Also ist der Potenzoperator rechtsassoziativ.
|
||||
```{julia}
|
||||
2^3^2 # right-associative, = 2^(3^2)
|
||||
2^3^2 # rechtsassoziativ, = 2^(3^2)
|
||||
```
|
||||
|
||||
### Precedence
|
||||
### Vorrang
|
||||
|
||||
- Julia assigns operator precedence levels from 1 to 17:
|
||||
- Julia ordnet den Operatoren Vorrangstufen von 1 bis 17 zu:
|
||||
|
||||
|
||||
|
||||
```{julia}
|
||||
for i in (:+, :-, :*, :/, :^, :(=))
|
||||
p = Base.operator_precedence(i)
|
||||
println("Precedence of $i = $p")
|
||||
println("Vorrang von $i = $p")
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
- 11 is less than 12, so 'multiplication and division before addition and subtraction'
|
||||
- The power operator `^` has a higher _precedence_.
|
||||
- Assignments have the smallest _precedence_
|
||||
- 11 ist kleiner als 12, also geht 'Punktrechnung vor Strichrechnung'
|
||||
- Der Potenz-Operator `^` hat eine höhere _precedence_.
|
||||
- Zuweisungen haben die kleinste _precedence_
|
||||
|
||||
|
||||
```{julia}
|
||||
# assignment has smallest precedence, therefore evaluation as x = (3 < 4)
|
||||
# Zuweisung hat kleinsten Vorrang, daher Auswertung als x = (3 < 4)
|
||||
|
||||
x = 3 < 4
|
||||
x
|
||||
@@ -540,11 +540,11 @@ x
|
||||
|
||||
|
||||
```{julia}
|
||||
(y = 3) < 4 # parentheses当然 override any precedence
|
||||
(y = 3) < 4 # Klammern schlagen natürlich jeden Vorrang
|
||||
y
|
||||
```
|
||||
|
||||
Once more to the example from the beginning of @sec-vorrang:
|
||||
Nochmal zum Beispiel vom Anfang von @sec-vorrang:
|
||||
|
||||
```{julia}
|
||||
-2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2
|
||||
@@ -557,43 +557,43 @@ for i ∈ (:^, :+, :/, :(==), :&&, :>, :|| )
|
||||
println(Base.operator_precedence(i))
|
||||
end
|
||||
```
|
||||
According to these precedence rules, the example expression is evaluated as follows:
|
||||
Nach diesen Vorrangregeln wird der Beispielausdruck also wie folgt ausgewertet:
|
||||
|
||||
```{julia}
|
||||
((-(2^3)+((500/2)/10)==8) && (13 > (7 + 1))) || (9 < 2)
|
||||
```
|
||||
(This of course corresponds to the *parse-tree* shown above)
|
||||
(Das entspricht natürlich dem oben gezeigten *parse-tree*)
|
||||
|
||||
So the precedence is:
|
||||
Es gilt also für den Vorrang:
|
||||
|
||||
> Power > Multiplication/Division > Addition/Subtraction > Comparisons > logical && > logical || > assignment
|
||||
> Potenz > Multiplikation/Division > Addition/Subtraktion > Vergleiche > logisches && > logisches || > Zuweisung
|
||||
|
||||
Thus, an expression like
|
||||
Damit wird ein Ausdruck wie
|
||||
```julia
|
||||
a = x <= y + z && x > z/2
|
||||
```
|
||||
is sensibly evaluated as `a = ((x <= (y+z)) && (x < (z/2)))`
|
||||
sinnvoll ausgewertet als `a = ((x <= (y+z)) && (x < (z/2)))`
|
||||
|
||||
|
||||
- A special case is still
|
||||
|
||||
- unary operators, in particular `+` and `-` as signs
|
||||
- _juxtaposition_, i.e., numbers directly before variables or parentheses without `*` symbol
|
||||
|
||||
Both have precedence even before multiplication and division.
|
||||
- Eine Besonderheit sind noch
|
||||
|
||||
- unäre Operatoren, also insbesondere `+` und `-` als Vorzeichen
|
||||
- _juxtaposition_, also Zahlen direkt vor Variablen oder Klammern ohne `*`-Symbol
|
||||
|
||||
Beide haben Vorrang noch vor Multiplikation und Division.
|
||||
|
||||
:::{.callout-important}
|
||||
Therefore, the meaning of expressions changes when one applies _juxtaposition_:
|
||||
Damit ändert sich die Bedeutung von Ausdrücken, wenn man _juxtaposition_ anwendet:
|
||||
```{julia}
|
||||
1/2*π, 1/2π
|
||||
```
|
||||
:::
|
||||
|
||||
- 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) ):
|
||||
- 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) ):
|
||||
|
||||
> Unary operators, including juxtaposition, bind tighter than ^ on the right but looser on the left.
|
||||
|
||||
Examples:
|
||||
Beispiele:
|
||||
```{julia}
|
||||
-2^2 # -(2^2)
|
||||
```
|
||||
@@ -615,26 +615,28 @@ x = 5
|
||||
```
|
||||
|
||||
|
||||
- Function application `f(...)` has precedence over all operators
|
||||
- Funktionsanwendung `f(...)` hat Vorrang vor allen Operatoren
|
||||
|
||||
|
||||
```{julia}
|
||||
sin(x)^2 === (sin(x))^2 # not sin(x^2)
|
||||
sin(x)^2 === (sin(x))^2 # nicht sin(x^2)
|
||||
```
|
||||
|
||||
### Additional Operators
|
||||
### Zusätzliche Operatoren
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Thus, for example,
|
||||
So haben z.B.
|
||||
```julia
|
||||
∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛
|
||||
```
|
||||
|
||||
have precedence 12 like multiplication/division (and are left-associative like these)
|
||||
and for example
|
||||
den Vorrang 12 wie Multiplikation/Division (und sind wie diese linksassoziativ)
|
||||
und z.B.
|
||||
```julia
|
||||
⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗
|
||||
⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗
|
||||
```
|
||||
have precedence 11 like addition/subtraction.
|
||||
haben den Vorrang 11 wie Addition/Subtraktion.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,49 +9,48 @@ engine: julia
|
||||
using InteractiveUtils
|
||||
```
|
||||
|
||||
# First Small Programs
|
||||
# Erste Miniprogramme
|
||||
|
||||
|
||||
## What Skills Are Needed for Programming?
|
||||
## Was sollte man zum Programmieren können?
|
||||
|
||||
|
||||
- **Thinking in algorithms:**
|
||||
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?
|
||||
- **Implementation of the algorithm into a program:**
|
||||
What data structures, constructs, functions... does the programming language provide?
|
||||
- **Formal syntax:**
|
||||
Humans understand 'broken English'; computers don't understand 'broken C++' or 'broken Julia'. The syntax must be mastered.
|
||||
- **The "ecosystem" of the language:**
|
||||
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?
|
||||
- **The art of debugging:**
|
||||
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.
|
||||
- **Sense of the efficiency and complexity of algorithms**
|
||||
- **Specifics of computer arithmetic**, especially floating point numbers
|
||||
- **Denken in Algorithmen:**
|
||||
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?
|
||||
- **Umsetzung des Algorithmus in ein Programm:**
|
||||
Welche Datenstrukturen, Konstrukte, Funktionen... stellt die Programmiersprache bereit?
|
||||
- **Formale Syntax:**
|
||||
Menschen verstehen 'broken English'; Computer verstehen kein 'broken C++' oder 'broken Julia'. Die Syntax muss beherrscht werden.
|
||||
- **„Ökosystem“ der Sprache:**
|
||||
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?
|
||||
- **die Kunst des 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.
|
||||
- **Gefühl für die Effizienz und Komplexität von Algorithmen**
|
||||
- **Besonderheiten der Computerarithmetik**, insbesondere der Gleitkommazahlen
|
||||
|
||||
These cannot all be mastered at once. Be patient with yourself and 'play' with the language.
|
||||
|
||||
The following examples should serve as inspiration.
|
||||
Das erschließt sich nicht alles auf einmal. Haben Sie Geduld mit sich und 'spielen' Sie mit der Sprache.
|
||||
|
||||
Das Folgende soll eine kleine Anregung dazu sein.
|
||||
|
||||
## Project Euler
|
||||
|
||||
A nice source for programming tasks with mathematical character and very different levels of difficulty is [Project Euler](https://projecteuler.net/).
|
||||
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.
|
||||
Eine hübsche Quelle für Programmieraufgaben mit mathematischem Charakter und sehr unterschiedlichen Schwierigkeitsgraden ist [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.
|
||||
|
||||
---------
|
||||
|
||||
### Example 1
|
||||
### Beispiel 1
|
||||
|
||||
::::::::{.content-hidden unless-format="xxx"}
|
||||
::::::{.content-hidden unless-format="xxx"}
|
||||
|
||||
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
|
||||
Aufg. 92
|
||||
aufg. 92
|
||||
|
||||
:::
|
||||
|
||||
::: {.callout-note icon=false .titlenormal}
|
||||
## Project Euler Problem No. 1
|
||||
## Project Euler Problem No 1
|
||||
|
||||
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
|
||||
|
||||
@@ -59,36 +58,36 @@ Find the sum of all the multiples of 3 or 5 below 1000.
|
||||
|
||||
:::
|
||||
|
||||
1. Algorithm:
|
||||
- Test all natural numbers <1000 for divisibility by 3 or 5 and
|
||||
- sum the divisible numbers.
|
||||
1. Algorithmus:
|
||||
- Teste alle natürlichen Zahlen <1000 auf Teilbarkeit durch 3 oder durch 5 und
|
||||
- summiere die teilbaren Zahlen auf.
|
||||
|
||||
2. Implementation:
|
||||
2. Umsetzung:
|
||||
|
||||
How does Julia provide the remainder of integer division? Functions like this are typically called `rem()` (for *remainder*) or `mod()`. You can look it up in the documentation or try `?rem` and `?mod` in the Julia REPL. Both functions exist; 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`.
|
||||
|
||||
How does one test a sequence of values and sum them up? There is a standard pattern: `for` loop and accumulator variable:
|
||||
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`.
|
||||
|
||||
Wie testet man eine Reihe von Werten durch und summiert auf? Da gibt es ein Standardmuster: `for`-Schleife und Akkumulatorvariable:
|
||||
|
||||
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
||||
|
||||
## One possible solution:
|
||||
## Eine Lösungsvariante:
|
||||
|
||||
```{julia}
|
||||
s = 0 # initialize accumulator variable
|
||||
for i in 1:999 # loop
|
||||
if i % 3 == 0 || i % 5 == 0 # test
|
||||
s += i # add to accumulator
|
||||
end # end test
|
||||
end # end loop
|
||||
println(" The answer is: $s") # output result
|
||||
s = 0 # Akkumulatorvariable initialisieren
|
||||
for i in 1:999 # Schleife
|
||||
if i % 3 == 0 || i % 5 == 0 # Test
|
||||
s += i # Zu Akkumulator addieren
|
||||
end # Ende Test
|
||||
end # Ende Schleife
|
||||
println(" Die Antwort ist: $s") # Ausgabe des Ergebnisses
|
||||
```
|
||||
:::
|
||||
|
||||
Of course, this can also be done a bit shorter:
|
||||
Natürlich geht das auch etwas kürzer:
|
||||
|
||||
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
||||
|
||||
## Another solution:
|
||||
## Noch eine Lösungsvariante:
|
||||
|
||||
```{julia}
|
||||
sum([i for i in 1:999 if i%3==0||i%5==0])
|
||||
@@ -99,11 +98,11 @@ sum([i for i in 1:999 if i%3==0||i%5==0])
|
||||
|
||||
-----------
|
||||
|
||||
### Example 2
|
||||
### Beispiel 2
|
||||
|
||||
|
||||
::: {.callout-note icon=false .titlenormal}
|
||||
## Project Euler Problem No. 92
|
||||
## Project Euler Problem No 92
|
||||
A number chain is created by continuously adding the square of the digits in a number to form a new number until it has been seen before.
|
||||
|
||||
For example,
|
||||
@@ -116,41 +115,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?
|
||||
:::
|
||||
|
||||
Programs can be developed [*top-down* and *bottom-up*](https://en.wikipedia.org/wiki/Top-down_and_bottom-up_design).
|
||||
*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.)
|
||||
Programme kann man [*top-down* und *bottom-up*](https://de.wikipedia.org/wiki/Top-Down-_und_Bottom-Up-Design) entwickeln.
|
||||
*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.)
|
||||
|
||||
##### Function No. 1
|
||||
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'.
|
||||
##### Funktion Nr. 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.
|
||||
|
||||
|
||||
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
||||
|
||||
## `q2sum(n)` calculates the sum of the squares of the digits of n in the decimal system:
|
||||
## `q2sum(n)` berechnet die Summe der Quadrate der Ziffern von n im Dezimalsystem:
|
||||
|
||||
```{julia}
|
||||
#| output: false
|
||||
function q2sum(n)
|
||||
s = 0 # accumulator for the sum
|
||||
while n > 9 # as long as still multi-digit...
|
||||
q, r = divrem(n, 10) # calculate integer quotient and remainder of division by 10
|
||||
s += r^2 # add squared digit to accumulator
|
||||
n = q # continue with the number divided by 10
|
||||
s = 0 # Akkumulator für die Summe
|
||||
while n > 9 # solange noch mehrstellig...
|
||||
q, r = divrem(n, 10) # berechne Ganzzahlquotient und Rest bei Division durch 10
|
||||
s += r^2 # addiere quadrierte Ziffer zum Akkumulator
|
||||
n = q # mache weiter mit der durch 10 geteilten Zahl
|
||||
end
|
||||
s += n^2 # add the square of the last digit
|
||||
s += n^2 # addiere das Quadrat der letzten Ziffer
|
||||
return s
|
||||
end
|
||||
```
|
||||
|
||||
:::
|
||||
... and let's test it now:
|
||||
... und das testen wir jetzt natürlich:
|
||||
```{julia}
|
||||
for i in [1, 7, 33, 111, 321, 1000, 73201]
|
||||
j = q2sum(i)
|
||||
println("Square digit sum of $i = $j")
|
||||
println("Quadratquersumme von $i = $j")
|
||||
end
|
||||
```
|
||||
|
||||
In the spirit of the task, we apply the function repeatedly:
|
||||
Im Sinne der Aufgabe wenden wir die Funktion wiederholt an:
|
||||
|
||||
```{julia}
|
||||
n = 129956799
|
||||
@@ -159,48 +158,48 @@ for i in 1:14
|
||||
println(n)
|
||||
end
|
||||
```
|
||||
... and we have here hit one of the '89-cycles'.
|
||||
... und haben hier einen der '89er Zyklen' getroffen.
|
||||
|
||||
|
||||
#### Function No. 2
|
||||
#### Funktion Nr. 2
|
||||
|
||||
We need to test whether repeated application of the function `q2sum()` finally leads to **1** or ends in this **89**-cycle.
|
||||
Wir müssen testen, ob die wiederholte Anwendung der Funktion `q2sum()` schließlich zu **1** führt oder in diesem **89er**-Zyklus endet.
|
||||
|
||||
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
||||
|
||||
## `q2test(n)` determines whether repeated square digit sum calculation leads to the 89-cycle:
|
||||
## `q2test(n)` ermittelt, ob wiederholte Quadratquersummenbildung in den 89er-Zyklus führt:
|
||||
|
||||
```{julia}
|
||||
#| output: false
|
||||
function q2test(n)
|
||||
while n !=1 && n != 89 # as long as we have not reached 1 or 89....
|
||||
n = q2sum(n) # repeat
|
||||
while n !=1 && n != 89 # solange wir nicht bei 1 oder 89 angekommen sind....
|
||||
n = q2sum(n) # wiederholen
|
||||
end
|
||||
if n==1 return false end # not an 89-number
|
||||
return true # 89-number found
|
||||
if n==1 return false end # keine 89er-Zahl
|
||||
return true # 89er-Zahl gefunden
|
||||
end
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
... and with this, we can solve the task:
|
||||
... und damit können wir die Aufgabe lösen:
|
||||
|
||||
```{julia}
|
||||
c = 0 # once again an accumulator
|
||||
for i = 1 : 10_000_000 - 1 # this is how you can separate thousands for better readability in Julia
|
||||
if q2test(i) # q2test() returns a boolean, no further test needed
|
||||
c += 1 # 'if x == true' is redundant, 'if x' is perfectly sufficient
|
||||
c = 0 # mal wieder ein Akkumulator
|
||||
for i = 1 : 10_000_000 - 1 # so kann man in Julia Tausenderblöcke zur besseren Lesbarkeit abtrennen
|
||||
if q2test(i) # q2test() gibt einen Boolean zurück, kein weiterer Test nötig
|
||||
c += 1 # 'if x == true' ist redundant, 'if x' reicht völlig
|
||||
end
|
||||
end
|
||||
println("$c numbers below ten million arrive at 89.")
|
||||
```
|
||||
|
||||
Numbers for which the iterative square digit sum calculation ends at 1 are called [happy numbers](https://en.wikipedia.org/wiki/Happy_number); all other numbers eventually reach the 89-cycle.
|
||||
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.
|
||||
|
||||
Here is the complete program again:
|
||||
Hier nochmal das vollständige Programm:
|
||||
|
||||
:::{.callout-caution icon="false" collapse="true" .titlenormal}
|
||||
## our solution to Project Euler No 92:
|
||||
## unsere Lösung von Project Euler No 92:
|
||||
|
||||
```{julia}
|
||||
function q2sum(n)
|
||||
|
||||
129
chapters/Pi2.qmd
129
chapters/Pi2.qmd
@@ -9,68 +9,72 @@ engine: julia
|
||||
using InteractiveUtils
|
||||
```
|
||||
|
||||
```{julia}
|
||||
#| error: false
|
||||
#| echo: false
|
||||
#| output: false
|
||||
flush(stdout)
|
||||
```
|
||||
|
||||
# A Case Study in Floating-Point Arithmetic Stability
|
||||
# Ein Beispiel zur Stabilität von Gleitkommaarithmetik
|
||||
|
||||
## Calculation of $\pi$ According to Archimedes
|
||||
|
||||
A lower bound for $2\pi$—the circumference of the unit circle—is obtained by summing
|
||||
the side lengths of a regular $n$-gon inscribed in the unit circle.
|
||||
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}$$.
|
||||
|
||||
## Berechnung von $\pi$ nach Archimedes
|
||||
|
||||
Eine untere Schranke für $2\pi$, den Umfang des Einheitskreises, erhält man durch die
|
||||
Summe der Seitenlängen eines dem Einheitskreis eingeschriebenen regelmäßigen $n$-Ecks.
|
||||
Die Abbildung links zeigt, wie man beginnend mit einem Viereck der Seitenlänge $s_4=\sqrt{2}$ die Eckenzahl iterativ verdoppelt.
|
||||
|
||||
:::{.narrow}
|
||||
|
||||
| Fig. 1 | Fig. 2 |
|
||||
| Abb. 1 | Abb.2 |
|
||||
| :-: | :-: |
|
||||
|  |  |
|
||||
: {tbl-colwidths="[57,43]"}
|
||||
|
||||
:::
|
||||
|
||||
The second figure shows the geometry of the vertex doubling.
|
||||
|
||||
With
|
||||
$|\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$ respectively yields
|
||||
Die zweite Abbildung zeigt die Geometrie der Eckenverdoppelung.
|
||||
|
||||
Mit
|
||||
$|\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
|
||||
$NBA$ jeweils
|
||||
$$
|
||||
a^2 + \left(\frac{s_{n}}{2}\right)^2 = 1\qquad\text{resp.} \qquad
|
||||
a^2 + \left(\frac{s_{n}}{2}\right)^2 = 1\qquad\text{bzw.} \qquad
|
||||
(1-a)^2 + \left(\frac{s_{n}}{2}\right)^2 = s_{2n}^2
|
||||
$$
|
||||
Elimination of $a$ gives the recursion
|
||||
Elimination von $a$ liefert die Rekursion
|
||||
$$
|
||||
s_{2n} = \sqrt{2-\sqrt{4-s_n^2}} \qquad\text{with initial value}\qquad
|
||||
s_4=\sqrt{2}
|
||||
s_{2n} = \sqrt{2-\sqrt{4-s_n^2}} \qquad\text{mit Startwert}\qquad
|
||||
s_4=\sqrt{2}
|
||||
$$
|
||||
for the length $s_n$ of one side of the inscribed regular
|
||||
$n$-gon.
|
||||
für die Länge $s_n$ **einer** Seite des eingeschriebenen regelmäßigen
|
||||
$n$-Ecks.
|
||||
|
||||
The sequence $(n\cdot s_n)$ converges monotonically from below to the limit $2\pi$:
|
||||
|
||||
Die Folge $(n\cdot s_n)$
|
||||
konvergiert monoton von unten gegen den
|
||||
Grenzwert $2\pi$:
|
||||
$$
|
||||
n\, s_n \rightarrow 2\pi % \qquad\text{and} \qquad {n c_n}\downarrow 2\pi
|
||||
n\, s_n \rightarrow 2\pi % \qquad\text{und} \qquad {n c_n}\downarrow 2\pi
|
||||
$$
|
||||
The relative error of approximating $2\pi$ by an $n$-gon is:
|
||||
Der relative Fehler der Approximation von 2π durch ein $n$-Eck ist:
|
||||
$$
|
||||
\epsilon_n = \left| \frac{n\, s_n-2 \pi}{2\pi} \right|
|
||||
$$
|
||||
|
||||
## Two Iteration Formulas^[by Christoph Überhuber, "Computer-Numerik" Vol. 1, Springer 1995, Chap. 2.3]. The equation
|
||||
|
||||
## Zwei Iterationsvorschriften^[nach: Christoph Überhuber, „Computer-Numerik“ Bd. 1, Springer 1995, Kap. 2.3]
|
||||
Die Gleichung
|
||||
$$
|
||||
s_{2n} = \sqrt{2-\sqrt{4-s_n^2}}\qquad \qquad \text{(Iteration A)}
|
||||
s_{2n} = \sqrt{2-\sqrt{4-s_n^2}}\qquad \qquad \textrm{(Iteration A)}
|
||||
$$
|
||||
is mathematically equivalent to:
|
||||
ist mathematisch äquivalent zu
|
||||
$$
|
||||
s_{2n} = \frac{s_n}{\sqrt{2+\sqrt{4-s_n^2}}} \qquad \qquad \text{(Iteration B)}
|
||||
s_{2n} = \frac{s_n}{\sqrt{2+\sqrt{4-s_n^2}}} \qquad \qquad \textrm{(Iteration B)}
|
||||
$$
|
||||
|
||||
(Please verify!)
|
||||
(Bitte nachrechnen!)
|
||||
|
||||
However, Iteration A is ill-conditioned and numerically unstable, as the following code demonstrates. The output shows the respective approximation for $\pi$.
|
||||
|
||||
|
||||
Allerdings ist Iteration A schlecht konditioniert und numerisch instabil, wie der folgende Code zeigt. Ausgegeben wird die jeweils berechnete Näherung für π.
|
||||
|
||||
```{julia}
|
||||
using Printf
|
||||
@@ -78,19 +82,19 @@ using Printf
|
||||
iterationA(s) = sqrt(2 - sqrt(4 - s^2))
|
||||
iterationB(s) = s / sqrt(2 + sqrt(4 - s^2))
|
||||
|
||||
s_B = s_A = sqrt(2) # initial value
|
||||
s_B = s_A = sqrt(2) # Startwert
|
||||
|
||||
ϵ(x) = abs(x - 2π)/2π # relative error
|
||||
ϵ(x) = abs(x - 2π)/2π # rel. Fehler
|
||||
|
||||
ϵ_A = Float64[] # vectors for the plot
|
||||
ϵ_A = Float64[] # Vektoren für den Plot
|
||||
ϵ_B = Float64[]
|
||||
is = Float64[]
|
||||
is = Float64[]
|
||||
|
||||
@printf """Approx. value of π
|
||||
$n$-gon Iteration A Iteration B
|
||||
@printf """ approx. Wert von π
|
||||
n-Eck Iteration A Iteration B
|
||||
"""
|
||||
|
||||
for $i$ in $3:35$
|
||||
for i in 3:35
|
||||
push!(is, i)
|
||||
s_A = iterationA(s_A)
|
||||
s_B = iterationB(s_B)
|
||||
@@ -98,66 +102,77 @@ for $i$ in $3:35$
|
||||
doublePi_B = 2^i * s_B
|
||||
push!(ϵ_A, ϵ(doublePi_A))
|
||||
push!(ϵ_B, ϵ(doublePi_B))
|
||||
@printf "%14i %20.15f %20.15f\n" 2^i doublePi_A/2 doublePi_B/2
|
||||
@printf "%14i %20.15f %20.15f\n" 2^i doublePi_A/2 doublePi_B/2
|
||||
end
|
||||
```
|
||||
|
||||
While Iteration B stabilizes at a value correct within machine precision, Iteration A becomes unstable. A plot of the relative errors $\epsilon_i$ confirms this:
|
||||
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:
|
||||
|
||||
|
||||
```{julia}
|
||||
using PlotlyJS
|
||||
|
||||
layout = Layout(xaxis_title="Iteration steps", yaxis_title="Relative error",
|
||||
layout = Layout(xaxis_title="Iterationsschritte", yaxis_title="rel. Fehler",
|
||||
yaxis_type="log", yaxis_exponentformat="power",
|
||||
xaxis_tick0=2, xaxis_dtick=2)
|
||||
|
||||
plot([scatter(x=is, y=ϵ_A, mode="markers+lines", name="Iteration A", yscale=:log10),
|
||||
plot([scatter(x=is, y=ϵ_A, mode="markers+lines", name="Iteration A", yscale=:log10),
|
||||
scatter(x=is, y=ϵ_B, mode="markers+lines", name="Iteration B", yscale=:log10)],
|
||||
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}
|
||||
ϵ_B[22:28]
|
||||
```
|
||||
|
||||
Further iterations do not improve the result; it stabilizes at a relative error of approximately 2.5 machine epsilons.
|
||||
Weitere Iterationen verbessern das Ergebnis nicht mehr. Sie stabilisieren sich bei einem relativen Fehler von etwa 2.5 Maschinenepsilon:
|
||||
|
||||
|
||||
```{julia}
|
||||
ϵ_B[end]/eps(Float64)
|
||||
```
|
||||
|
||||
Iteration A is unstable; already at $i=16$, the relative error begins to grow again.
|
||||
|
||||
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}$ is only slightly smaller than 2, and when computing $s_{2n}=\sqrt{2-a_n}$, a typical cancellation effect occurs.
|
||||
Die Form Iteration A ist instabil. Bereits bei $i=16$ beginnt der relative Fehler wieder zu wachsen.
|
||||
|
||||
Ursache ist eine typische Auslöschung. Die Seitenlängen $s_n$ werden sehr schnell klein. Damit ist
|
||||
$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.
|
||||
|
||||
|
||||
```{julia}
|
||||
setprecision(80) # precision for BigFloat
|
||||
setprecision(80) # precision für BigFloat
|
||||
|
||||
s = sqrt(BigFloat(2))
|
||||
|
||||
@printf " a = √(4-s^2) as BigFloat and as Float64\n\n"
|
||||
@printf " a = √(4-s^2) als BigFloat und als Float64\n\n"
|
||||
|
||||
for $$i=$ 3:44$
|
||||
for i = 3:44
|
||||
s = iterationA(s)
|
||||
x = sqrt(4-s^2)
|
||||
if i > 20
|
||||
@printf "%i %30.26f %20.16f \n" i x Float64(x)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
```
|
||||
|
||||
One sees the decrease in the number of significant digits. One also sees that using `BigFloat` with a mantissa length of 80 bits only slightly delays the onset of the cancellation effect.
|
||||
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.
|
||||
|
||||
**Countermeasures against unstable algorithms typically require better, stable algorithms, not more precise machine numbers.**
|
||||
**Gegen instabile Algorithmen helfen in der Regel nur bessere, stabile Algorithmen und nicht genauere Maschinenzahlen!**
|
||||
|
||||
:::{.content-hidden unless-format="xxx"}
|
||||
|
||||
Clearly, the computation of $2-a_n$ already shows a decrease in the number of significant digits (cancellation) relatively early
|
||||
before the computation of $a_n=\sqrt{4-s_n^2}$ itself leads to an unusable result due to cancellation.
|
||||
Offensichtlich tritt bei der Berechnung von $2-a_n$ bereits relativ früh
|
||||
eine Abnahme der Anzahl der signifikanten Ziffern (Auslöschung) auf,
|
||||
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,72 +1,74 @@
|
||||
# Development Environments
|
||||
# Entwicklungsumgebungen
|
||||
|
||||
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 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 long-term work, a personal installation is recommended.
|
||||
Für langfristiges Arbeiten empfiehlt sich eine eigene Installation.
|
||||
|
||||
|
||||
## Installation on Personal Computer (Linux/MacOS/MS Windows)
|
||||
## Installation auf eigenem Rechner (Linux/MacOS/MS Windows)
|
||||
|
||||
1. Install Julia with the installation and update manager **juliaup**: <https://github.com/JuliaLang/juliaup/>
|
||||
2. Install **Visual Studio Code** as editor/IDE: <https://code.visualstudio.com/>
|
||||
3. Install the **Julia language extension** in VS Code: <https://www.julia-vscode.org/docs/stable/gettingStarted/>
|
||||
1. Julia mit dem Installations- und Update-Manager **juliaup** installieren: <https://github.com/JuliaLang/juliaup/>
|
||||
2. als Editor/IDE **Visual Studio Code** installieren: <https://code.visualstudio.com/>
|
||||
3. im VS Code Editor die **Julia language extension** installieren: <https://www.julia-vscode.org/docs/stable/gettingstarted/>
|
||||
|
||||
Entry point:
|
||||
Einstieg:
|
||||
|
||||
- Create a new file with the extension `.jl` in VS Code
|
||||
- Write Julia code
|
||||
- `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
|
||||
- [Key bindings for VS Code](https://code.visualstudio.com/docs/getstarted/keybindings#_keyboard-shortcuts-reference)
|
||||
and [for Julia in VS Code](https://www.julia-vscode.org/docs/stable/userguide/keybindings/)
|
||||
- In VS Code eine neue Datei mit der Endung `.jl` anlegen
|
||||
- Julia-Code schreiben
|
||||
- `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
|
||||
- [Tastenbelegungen für 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/)
|
||||
|
||||
|
||||
### The Julia-REPL
|
||||
### Die Julia-REPL
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
```default
|
||||
$ julia
|
||||
_
|
||||
_ _ _(_)_ | Documentation: https://docs.julialang.org
|
||||
(_) | (_) (_) |
|
||||
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
|
||||
| | | | | | |/ _` | |
|
||||
| | |_| | | | (_| | | Version 1.11.4 (2025-03-10)
|
||||
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|
||||
_
|
||||
_ _ _(_)_ | Documentation: https://docs.julialang.org
|
||||
(_) | (_) (_) |
|
||||
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
|
||||
| | | | | | |/ _` | |
|
||||
| | |_| | | | (_| | | Version 1.11.3 (2025-01-21)
|
||||
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|
||||
|__/ |
|
||||
|
||||
julia>
|
||||
```
|
||||
|
||||
## Working on the [Jupyterhub Webserver](https://misun103.mathematik.uni-leipzig.de/)
|
||||
## Arbeiten auf dem [Jupyterhub-Webserver](https://misun103.mathematik.uni-leipzig.de/)
|
||||
|
||||
### Jupyterhub & Jupyter
|
||||
|
||||
- [JupyterHub](https://de.wikipedia.org/wiki/Project_Jupyter) is a multi-user server for Jupyter notebooks.
|
||||
- Jupyter is a web-based interactive programming environment that
|
||||
- was originally written for and in Python, but now supports many programming languages
|
||||
- In Jupyter, one works with so-called *notebooks*. These are structured text files (JSON), recognizable by the file extension `*.ipynb`.
|
||||
- [Jupyterhub](https://de.wikipedia.org/wiki/Project_Jupyter) ist ein Multi-User-Server für Jupyter.
|
||||
- Jupyter ist eine web-basierte interaktive Programmierumgebung, die
|
||||
- ursprünglich in und für Python geschrieben, inzwischen eine
|
||||
Vielzahl von Programmiersprachen nutzen kann.
|
||||
- In Jupyter bearbeitet man sogenannte *notebooks*. Das sind strukturiere Textdateien (JSON), erkennbar an der Dateiendung
|
||||
`*.ipynb`.
|
||||
|
||||
Our Jupyterhub server: <https://misun103.mathematik.uni-leipzig.de/>
|
||||
Unser Jupyterhub-Server: <https://misun103.mathematik.uni-leipzig.de/>
|
||||
|
||||
After logging into Jupyterhub, a file manager appears:
|
||||
Nach dem Einloggen in Jupyterhub erscheint ein Dateimanager:
|
||||
|
||||
::: {.content-visible when-format="html"}
|
||||

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