2 Commits

Author SHA1 Message Date
59cf7bcc64 Manifest.toml added 2026-02-22 18:21:46 +01:00
6c51a504b9 opencode files added 2026-02-22 18:20:25 +01:00
33 changed files with 2308 additions and 2764 deletions

2
.gitignore vendored
View File

@@ -32,5 +32,3 @@ xelatex.py
nb/*.qmd nb/*.qmd
nb/*.ipynb nb/*.ipynb
.cache/ .cache/
**/*.quarto_ipynb

View File

@@ -1,5 +1,5 @@
{ {
"julia.environmentPath": "/home/hellmund/Julia/Book26/JuliaKurs23/", "julia.environmentPath": "/home/hellmund/Julia/23",
"files.exclude": { "files.exclude": {
"**/.DS_Store": true, "**/.DS_Store": true,
"**/.git": true, "**/.git": true,

193
AGENTS.md
View File

@@ -1,52 +1,24 @@
# AGENTS.md - Guidelines for JuliaKurs23 # AGENTS.md - Guidelines for Agentic Coding in JuliaKurs23
This is a **Quarto-based Julia programming course book**. The book teaches scientific computing with Julia using interactive Jupyter notebooks rendered with Quarto. 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 translated to English. The English needs improvement—focus on making the prose professional, concise, and suitable for mathematicians. **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 ## Project Overview
- **Type**: Educational book (HTML website + PDF) generated from Quarto (.qmd) files - **Type**: Educational book website/PDF generated from Quarto (.qmd) files
- **Language**: English (all content) - **Language**: English (all content)
- **Build System**: Quarto with Julia Jupyter kernel - **Build System**: Quarto with Julia Jupyter kernel
- **Julia Version**: 1.10 - **Julia Version**: 1.10
- **Output**: HTML website and PDF
- **License**: CC BY-NC-SA 4.0 - **License**: CC BY-NC-SA 4.0
--- ---
## Current Task: English Translation Improvement
The English text in this book was translated from German and needs refinement for quality.
### Workflow (one change at a time)
For each chapter file in `chapters/`:
1. I read the file and identify English improvements
2. I present ONE improvement at a time showing:
- The current text
- The proposed improvement
- Explanation of why the change is needed
3. You reply **yes** or **no**
4. If yes, I apply the change; if no, I skip it
5. Repeat until all improvements for that file are done
6. Move to the next chapter file
### What to improve:
- English prose, grammar, word choice
- Clarity and flow for mathematical audience
- Professional tone suitable for mathematicians/scientists
### What NOT to change:
- Julia code
- LaTeX equations
- Markdown formatting
- Quarto cell options (`#| eval:`, etc.)
---
## Build Commands ## Build Commands
### Build the Book
```bash ```bash
# Build HTML website # Build HTML website
quarto render quarto render
@@ -59,10 +31,17 @@ quarto render --to julia-color-pdf
# Preview locally # Preview locally
quarto preview quarto preview
```
### Development Commands
```bash
# Render a specific chapter # Render a specific chapter
quarto render chapters/first_contact.qmd quarto render chapters/first_contact.qmd
# Build with specific output directory
quarto render --output-dir _book
# Run in daemon mode (faster rebuilds) # Run in daemon mode (faster rebuilds)
quarto render --execute-daemon 3600 quarto render --execute-daemon 3600
``` ```
@@ -70,55 +49,135 @@ quarto render --execute-daemon 3600
### Deployment ### Deployment
```bash ```bash
# Deploy to web server (rsync _book/)
./deploy.sh ./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 ## Code Style Guidelines
### Quarto Structure (.qmd files) ### General Structure (.qmd files)
- All `.qmd` files start with YAML front matter: `engine: julia` - All `.qmd` files start with YAML front matter specifying `engine: julia`
- Code blocks use triple backticks with `julia` identifier - Code blocks use triple backticks with `julia` language identifier
- Cell options in comments: `#| option: value` - 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 ### Julia Code Conventions
**Imports:** #### Imports
```julia ```julia
using Statistics, LinearAlgebra, Plots # many exports # Prefer using for packages with many exports
import Base: convert, show # specific exports using Statistics, LinearAlgebra, Plots
# Use import when you need specific exports or module name
import Base: convert, show
``` ```
**Naming:** #### Naming Conventions
- Variables/functions: lowercase with underscores (`my_variable`)
- Types: CamelCase (`MyType`, `AbstractMatrix`)
- Constants: ALL_UPPERCASE (`MAX_ITER`)
- Modules: PascalCase (`Statistics`)
**Formatting:** - **Variables/functions**: lowercase with underscores (`my_variable`, `calculate_mean`)
- 4 spaces indentation - **Types**: CamelCase (`MyType`, `AbstractMatrix`)
- ~92 character line limit - **Constants**: ALL_UPPERCASE (`MAX_ITER`, `PI`)
- Spaces around operators: `a + b` - **Modules**: PascalCase (`Statistics`, `LinearAlgebra`)
- No spaces before commas: `f(a, b)`
**Types:** #### Formatting
- Explicit types for performance/clarity
- Parameterize: `Vector{Float64}`, `Dict{Symbol, Int}` - Use 4 spaces for indentation (Julia default)
- Concrete types for struct fields - 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
**Error Handling:**
```julia ```julia
# Use try-catch for expected errors
try try
parse(Int, user_input) parse(Int, user_input)
catch e catch e
println("Invalid input: $e") println("Invalid input: $e")
end end
# Use assertions for internal checks
@assert x >= 0 "x must be non-negative" @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 ## File Organization
@@ -138,10 +197,20 @@ end
--- ---
## 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 ## Important Notes
1. **All content is in English** professional, concise, suitable for mathematicians 1. **All content is in English** - Comments, documentation, variable names in examples should be English (professional, concise, suitable for mathematicians)
2. **Code, LaTeX, formatting preserved** — only improve English prose 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 cached** — use `#| eval: true` to execute cells 3. **Code execution is cached** - Use `#| eval: true` to execute cells
4. **Freeze mode** — set to `auto` in _quarto.yml; use `freeze: false` to re-run all code 4. **ansi color codes** - The `julia-color` extension handles ANSI escape sequences in output
5. **Keep intermediates**`keep-ipynb`, `keep-tex`, `keep-md` are all true 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

View File

@@ -22,9 +22,9 @@ version = "0.4.5"
[[deps.Adapt]] [[deps.Adapt]]
deps = ["LinearAlgebra", "Requires"] deps = ["LinearAlgebra", "Requires"]
git-tree-sha1 = "35ea197a51ce46fcd01c4a44befce0578a1aaeca" git-tree-sha1 = "7e35fca2bdfba44d797c53dfe63a51fabf39bfc0"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "4.5.0" version = "4.4.0"
weakdeps = ["SparseArrays", "StaticArrays"] weakdeps = ["SparseArrays", "StaticArrays"]
[deps.Adapt.extensions] [deps.Adapt.extensions]
@@ -165,9 +165,9 @@ version = "1.1.1"
[[deps.CairoMakie]] [[deps.CairoMakie]]
deps = ["CRC32c", "Cairo", "Cairo_jll", "Colors", "FileIO", "FreeType", "GeometryBasics", "LinearAlgebra", "Makie", "PrecompileTools"] deps = ["CRC32c", "Cairo", "Cairo_jll", "Colors", "FileIO", "FreeType", "GeometryBasics", "LinearAlgebra", "Makie", "PrecompileTools"]
git-tree-sha1 = "fa072933899aae6dc61dde934febed8254e66c6a" git-tree-sha1 = "5017d6849aff775febd36049f7d926a5fb6677ec"
uuid = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" uuid = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
version = "0.15.9" version = "0.15.8"
[[deps.Cairo_jll]] [[deps.Cairo_jll]]
deps = ["Artifacts", "Bzip2_jll", "CompilerSupportLibraries_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"] deps = ["Artifacts", "Bzip2_jll", "CompilerSupportLibraries_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"]
@@ -286,9 +286,9 @@ version = "1.3.0+1"
[[deps.ComputePipeline]] [[deps.ComputePipeline]]
deps = ["Observables", "Preferences"] deps = ["Observables", "Preferences"]
git-tree-sha1 = "3b4be73db165146d8a88e47924f464e55ab053cd" git-tree-sha1 = "76dab592fa553e378f9dd8adea16fe2591aa3daa"
uuid = "95dc2771-c249-4cd0-9c9f-1f3b4330693c" uuid = "95dc2771-c249-4cd0-9c9f-1f3b4330693c"
version = "0.1.7" version = "0.1.6"
[[deps.ConcurrentUtilities]] [[deps.ConcurrentUtilities]]
deps = ["Serialization", "Sockets"] deps = ["Serialization", "Sockets"]
@@ -423,9 +423,9 @@ uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.2.4+0" version = "2.2.4+0"
[[deps.EnumX]] [[deps.EnumX]]
git-tree-sha1 = "c49898e8438c828577f04b92fc9368c388ac783c" git-tree-sha1 = "7bebc8aad6ee6217c78c5ddcf7ed289d65d0263e"
uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56"
version = "1.0.7" version = "1.0.6"
[[deps.EpollShim_jll]] [[deps.EpollShim_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl"] deps = ["Artifacts", "JLLWrappers", "Libdl"]
@@ -603,9 +603,9 @@ version = "3.4.1+0"
[[deps.GR]] [[deps.GR]]
deps = ["Artifacts", "Base64", "DelimitedFiles", "Downloads", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Preferences", "Printf", "Qt6Wayland_jll", "Random", "Serialization", "Sockets", "TOML", "Tar", "Test", "p7zip_jll"] deps = ["Artifacts", "Base64", "DelimitedFiles", "Downloads", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Preferences", "Printf", "Qt6Wayland_jll", "Random", "Serialization", "Sockets", "TOML", "Tar", "Test", "p7zip_jll"]
git-tree-sha1 = "44716a1a667cb867ee0e9ec8edc31c3e4aa5afdc" git-tree-sha1 = "ee0585b62671ce88e48d3409733230b401c9775c"
uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
version = "0.73.24" version = "0.73.22"
[deps.GR.extensions] [deps.GR.extensions]
IJuliaExt = "IJulia" IJuliaExt = "IJulia"
@@ -615,9 +615,9 @@ version = "0.73.24"
[[deps.GR_jll]] [[deps.GR_jll]]
deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "FreeType2_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Qt6Base_jll", "Zlib_jll", "libpng_jll"] deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "FreeType2_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Qt6Base_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "be8a1b8065959e24fdc1b51402f39f3b6f0f6653" git-tree-sha1 = "7dd7173f7129a1b6f84e0f03e0890cd1189b0659"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9" uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.73.24+0" version = "0.73.22+0"
[[deps.GeometryBasics]] [[deps.GeometryBasics]]
deps = ["EarCut_jll", "Extents", "IterTools", "LinearAlgebra", "PrecompileTools", "Random", "StaticArrays"] deps = ["EarCut_jll", "Extents", "IterTools", "LinearAlgebra", "PrecompileTools", "Random", "StaticArrays"]
@@ -669,9 +669,9 @@ version = "1.3.15+0"
[[deps.Graphs]] [[deps.Graphs]]
deps = ["ArnoldiMethod", "DataStructures", "Inflate", "LinearAlgebra", "Random", "SimpleTraits", "SparseArrays", "Statistics"] deps = ["ArnoldiMethod", "DataStructures", "Inflate", "LinearAlgebra", "Random", "SimpleTraits", "SparseArrays", "Statistics"]
git-tree-sha1 = "7eb45fe833a5b7c51cf6d89c5a841d5967e44be3" git-tree-sha1 = "031d63d09bd3e6e319df66bb466f5c3e8d147bee"
uuid = "86223c79-3864-5bf0-83f7-82e725a168b6" uuid = "86223c79-3864-5bf0-83f7-82e725a168b6"
version = "1.14.0" version = "1.13.4"
weakdeps = ["Distributed", "SharedArrays"] weakdeps = ["Distributed", "SharedArrays"]
[deps.Graphs.extensions] [deps.Graphs.extensions]
@@ -1101,9 +1101,9 @@ version = "0.5.16"
[[deps.Makie]] [[deps.Makie]]
deps = ["Animations", "Base64", "CRC32c", "ColorBrewer", "ColorSchemes", "ColorTypes", "Colors", "ComputePipeline", "Contour", "Dates", "DelaunayTriangulation", "Distributions", "DocStringExtensions", "Downloads", "FFMPEG_jll", "FileIO", "FilePaths", "FixedPointNumbers", "Format", "FreeType", "FreeTypeAbstraction", "GeometryBasics", "GridLayoutBase", "ImageBase", "ImageIO", "InteractiveUtils", "Interpolations", "IntervalSets", "InverseFunctions", "Isoband", "KernelDensity", "LaTeXStrings", "LinearAlgebra", "MacroTools", "Markdown", "MathTeXEngine", "Observables", "OffsetArrays", "PNGFiles", "Packing", "Pkg", "PlotUtils", "PolygonOps", "PrecompileTools", "Printf", "REPL", "Random", "RelocatableFolders", "Scratch", "ShaderAbstractions", "Showoff", "SignedDistanceFields", "SparseArrays", "Statistics", "StatsBase", "StatsFuns", "StructArrays", "TriplotBase", "UnicodeFun", "Unitful"] deps = ["Animations", "Base64", "CRC32c", "ColorBrewer", "ColorSchemes", "ColorTypes", "Colors", "ComputePipeline", "Contour", "Dates", "DelaunayTriangulation", "Distributions", "DocStringExtensions", "Downloads", "FFMPEG_jll", "FileIO", "FilePaths", "FixedPointNumbers", "Format", "FreeType", "FreeTypeAbstraction", "GeometryBasics", "GridLayoutBase", "ImageBase", "ImageIO", "InteractiveUtils", "Interpolations", "IntervalSets", "InverseFunctions", "Isoband", "KernelDensity", "LaTeXStrings", "LinearAlgebra", "MacroTools", "Markdown", "MathTeXEngine", "Observables", "OffsetArrays", "PNGFiles", "Packing", "Pkg", "PlotUtils", "PolygonOps", "PrecompileTools", "Printf", "REPL", "Random", "RelocatableFolders", "Scratch", "ShaderAbstractions", "Showoff", "SignedDistanceFields", "SparseArrays", "Statistics", "StatsBase", "StatsFuns", "StructArrays", "TriplotBase", "UnicodeFun", "Unitful"]
git-tree-sha1 = "68af66ec16af8b152309310251ecb4fbfe39869f" git-tree-sha1 = "d1b974f376c24dad02c873e951c5cd4e351cd7c2"
uuid = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" uuid = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
version = "0.24.9" version = "0.24.8"
[deps.Makie.extensions] [deps.Makie.extensions]
MakieDynamicQuantitiesExt = "DynamicQuantities" MakieDynamicQuantitiesExt = "DynamicQuantities"
@@ -1129,9 +1129,9 @@ version = "0.6.7"
[[deps.MbedTLS]] [[deps.MbedTLS]]
deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"] deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"]
git-tree-sha1 = "8785729fa736197687541f7053f6d8ab7fc44f92" git-tree-sha1 = "c067a280ddc25f196b5e7df3877c6b226d390aaf"
uuid = "739be429-bea8-5141-9913-cc70e7f3736d" uuid = "739be429-bea8-5141-9913-cc70e7f3736d"
version = "1.1.10" version = "1.1.9"
[[deps.MbedTLS_jll]] [[deps.MbedTLS_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl"] deps = ["Artifacts", "JLLWrappers", "Libdl"]
@@ -1496,9 +1496,9 @@ version = "1.3.3"
[[deps.Preferences]] [[deps.Preferences]]
deps = ["TOML"] deps = ["TOML"]
git-tree-sha1 = "8b770b60760d4451834fe79dd483e318eee709c4" git-tree-sha1 = "522f093a29b31a93e34eaea17ba055d850edea28"
uuid = "21216c6a-2e73-6563-6e65-726566657250" uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.5.2" version = "1.5.1"
[[deps.PrettyTables]] [[deps.PrettyTables]]
deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "REPL", "Reexport", "StringManipulation", "Tables"] deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "REPL", "Reexport", "StringManipulation", "Tables"]
@@ -1535,9 +1535,9 @@ uuid = "92933f4c-e287-5a05-a399-4b506db050ca"
version = "1.11.0" version = "1.11.0"
[[deps.PtrArrays]] [[deps.PtrArrays]]
git-tree-sha1 = "4fbbafbc6251b883f4d2705356f3641f3652a7fe" git-tree-sha1 = "1d36ef11a9aaf1e8b74dacc6a731dd1de8fd493d"
uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d" uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d"
version = "1.4.0" version = "1.3.0"
[[deps.QOI]] [[deps.QOI]]
deps = ["ColorTypes", "FileIO", "FixedPointNumbers"] deps = ["ColorTypes", "FileIO", "FixedPointNumbers"]
@@ -1547,33 +1547,27 @@ version = "1.0.2"
[[deps.Qt6Base_jll]] [[deps.Qt6Base_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Vulkan_Loader_jll", "Xorg_libSM_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_cursor_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "libinput_jll", "xkbcommon_jll"] deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Vulkan_Loader_jll", "Xorg_libSM_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_cursor_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "libinput_jll", "xkbcommon_jll"]
git-tree-sha1 = "d7a4bff94f42208ce3cf6bc8e4e7d1d663e7ee8b" git-tree-sha1 = "34f7e5d2861083ec7596af8b8c092531facf2192"
uuid = "c0090381-4147-56d7-9ebc-da0b1113ec56" uuid = "c0090381-4147-56d7-9ebc-da0b1113ec56"
version = "6.10.2+1" version = "6.8.2+2"
[[deps.Qt6Declarative_jll]] [[deps.Qt6Declarative_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Qt6Base_jll", "Qt6ShaderTools_jll", "Qt6Svg_jll"] deps = ["Artifacts", "JLLWrappers", "Libdl", "Qt6Base_jll", "Qt6ShaderTools_jll"]
git-tree-sha1 = "d5b7dd0e226774cbd87e2790e34def09245c7eab" git-tree-sha1 = "da7adf145cce0d44e892626e647f9dcbe9cb3e10"
uuid = "629bc702-f1f5-5709-abd5-49b8460ea067" uuid = "629bc702-f1f5-5709-abd5-49b8460ea067"
version = "6.10.2+1" version = "6.8.2+1"
[[deps.Qt6ShaderTools_jll]] [[deps.Qt6ShaderTools_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Qt6Base_jll"] deps = ["Artifacts", "JLLWrappers", "Libdl", "Qt6Base_jll"]
git-tree-sha1 = "4d85eedf69d875982c46643f6b4f66919d7e157b" git-tree-sha1 = "9eca9fc3fe515d619ce004c83c31ffd3f85c7ccf"
uuid = "ce943373-25bb-56aa-8eca-768745ed7b5a" uuid = "ce943373-25bb-56aa-8eca-768745ed7b5a"
version = "6.10.2+1" version = "6.8.2+1"
[[deps.Qt6Svg_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Qt6Base_jll"]
git-tree-sha1 = "81587ff5ff25a4e1115ce191e36285ede0334c9d"
uuid = "6de9746b-f93d-5813-b365-ba18ad4a9cf3"
version = "6.10.2+0"
[[deps.Qt6Wayland_jll]] [[deps.Qt6Wayland_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Qt6Base_jll", "Qt6Declarative_jll"] deps = ["Artifacts", "JLLWrappers", "Libdl", "Qt6Base_jll", "Qt6Declarative_jll"]
git-tree-sha1 = "672c938b4b4e3e0169a07a5f227029d4905456f2" git-tree-sha1 = "8f528b0851b5b7025032818eb5abbeb8a736f853"
uuid = "e99dba38-086e-5de3-a5b1-6e4c66e897c3" uuid = "e99dba38-086e-5de3-a5b1-6e4c66e897c3"
version = "6.10.2+1" version = "6.8.2+2"
[[deps.QuadGK]] [[deps.QuadGK]]
deps = ["DataStructures", "LinearAlgebra"] deps = ["DataStructures", "LinearAlgebra"]
@@ -1830,9 +1824,9 @@ version = "0.15.8"
[[deps.StringManipulation]] [[deps.StringManipulation]]
deps = ["PrecompileTools"] deps = ["PrecompileTools"]
git-tree-sha1 = "d05693d339e37d6ab134c5ab53c29fce5ee5d7d5" git-tree-sha1 = "a3c1536470bf8c5e02096ad4853606d7c8f62721"
uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e" uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e"
version = "0.4.4" version = "0.4.2"
[[deps.StructArrays]] [[deps.StructArrays]]
deps = ["ConstructionBase", "DataAPI", "Tables"] deps = ["ConstructionBase", "DataAPI", "Tables"]
@@ -1915,9 +1909,9 @@ version = "1.11.0"
[[deps.TiffImages]] [[deps.TiffImages]]
deps = ["ColorTypes", "DataStructures", "DocStringExtensions", "FileIO", "FixedPointNumbers", "IndirectArrays", "Inflate", "Mmap", "OffsetArrays", "PkgVersion", "PrecompileTools", "ProgressMeter", "SIMD", "UUIDs"] deps = ["ColorTypes", "DataStructures", "DocStringExtensions", "FileIO", "FixedPointNumbers", "IndirectArrays", "Inflate", "Mmap", "OffsetArrays", "PkgVersion", "PrecompileTools", "ProgressMeter", "SIMD", "UUIDs"]
git-tree-sha1 = "08c10bc34f4e7743f530793d0985bf3c254e193d" git-tree-sha1 = "98b9352a24cb6a2066f9ababcc6802de9aed8ad8"
uuid = "731e570b-9d59-4bfa-96dc-6df516fadf69" uuid = "731e570b-9d59-4bfa-96dc-6df516fadf69"
version = "0.11.8" version = "0.11.6"
[[deps.TikzGraphs]] [[deps.TikzGraphs]]
deps = ["Graphs", "LaTeXStrings", "TikzPictures"] deps = ["Graphs", "LaTeXStrings", "TikzPictures"]

View File

@@ -6,8 +6,6 @@ SoSe25:
für Plots/plotlyjs für Plots/plotlyjs
26: es reicht, die eine Zeile mit requirejs zu entfernen.
Book25: Versuch ohne quarto-patch: Book25: Versuch ohne quarto-patch:
LaTeX: ansi in stdout not supported, Julia errors werden total LaTeX: ansi in stdout not supported, Julia errors werden total
zerschossen zerschossen

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2026 Posit Software, PBC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,7 +1,7 @@
title: Julia-color title: Julia-color
author: Meik Hellmund author: Meik Hellmund
version: 1.0.0 version: 1.0.0
quarto-required: ">=1.9.0" quarto-required: ">=99.9.0"
contributes: contributes:
formats: formats:
common: common:
@@ -14,18 +14,8 @@ contributes:
- "resources/css/juliamono.css" - "resources/css/juliamono.css"
pdf: pdf:
include-in-header: include-in-header:
- "resources/tex/juliainc.tex" - "resources/tex/juliainc.tex"
typst: typst:
include-in-header: include-in-header:
- "resources/typst/juliainc.typ" - "resources/typst/juliainc.typ"
# the following is from
# quarto-cli/src/resources/extension-subtrees/orange-book/_extensions/orange-book
# comment out for an article
template-partials:
- numbering.typ
- page.typ
- typst-show.typ
filters:
- path: orange-book.lua
at: post-quarto

View File

@@ -1,8 +1,6 @@
-- based on -- based on
-- https://github.com/jupyter/nbconvert/blob/main/nbconvert/filters/ansi.py -- https://github.com/jupyter/nbconvert/blob/main/nbconvert/filters/ansi.py
-- debug: pandoc -t native file.{typst,html,..}.md
local ANSI_COLORS = { local ANSI_COLORS = {
"ansi-black", "ansi-black",
"ansi-red", "ansi-red",
@@ -226,47 +224,18 @@ local function HTMLconverter(fg, bg, bold, light, italic, underline, inverse)
return starttag..">","</span>" return starttag..">","</span>"
end end
local function escapeTypstString(s)
s = s:gsub("\\", "\\\\")
s = s:gsub("%$", "\\$")
s = s:gsub("*", "\\*")
s = s:gsub([["]],[[\"]])
return s
end
local function escapeTypstString2(s)
s = s:gsub("@", "\\@")
s = s:gsub("<", "\\<")
s = s:gsub("#", "\\#")
s = s:gsub(">", "\\>")
--s = s:gsub("]","\\]")
s = s:gsub("\n","\\\n")
s = s:gsub("+","\\+")
s = s:gsub("/","\\/")
s = s:gsub("=","\\=")
return s
end
local function noescapeString(s)
return s
end
local function codeBlockTrans(e) local function codeBlockTrans(e)
local converter, fmt, escapeString local converter, fmt
if quarto.doc.isFormat('latex') then if quarto.doc.isFormat('latex') then
converter = LaTeXconverter converter = LaTeXconverter
fmt = 'latex' fmt = 'latex'
escapeString = noescapeString
elseif quarto.doc.isFormat('html') then elseif quarto.doc.isFormat('html') then
converter = HTMLconverter converter = HTMLconverter
fmt = 'html' fmt = 'html'
escapeString = noescapeString
elseif quarto.doc.isFormat('typst') then elseif quarto.doc.isFormat('typst') then
converter = Typstconverter converter = Typstconverter
fmt = 'typst' fmt = 'typst'
escapeString = escapeTypstString
else else
return return
end end
@@ -295,7 +264,7 @@ local function codeBlockTrans(e)
local out="" local out=""
local text = e.text local text = e.text
-- we remove links (eg in julia ParseErrors. They link to local files, so they are useless anyway) -- we remove links (eg in julia ParseErrors. THey link to local files, so they are useless anyway)
text = text:gsub("\x1b%]8;.-\x1b\\", "") text = text:gsub("\x1b%]8;.-\x1b\\", "")
if string.find(text, "\x1b%[") then if string.find(text, "\x1b%[") then
@@ -336,7 +305,7 @@ local function codeBlockTrans(e)
else else
starttag, endtag = converter(fg, bg, bold, light, italic, underline, inverse) starttag, endtag = converter(fg, bg, bold, light, italic, underline, inverse)
end end
out = out .. starttag .. escapeString(chunk) .. endtag out = out .. starttag .. chunk .. endtag
end end
while next(numbers) ~= nil do while next(numbers) ~= nil do
@@ -390,7 +359,7 @@ local function codeBlockTrans(e)
end end
end end
else else
out = escapeString(text) out = text
end end
if fmt == 'html' then if fmt == 'html' then
return pandoc.RawBlock(fmt, return pandoc.RawBlock(fmt,
@@ -400,11 +369,7 @@ local function codeBlockTrans(e)
return pandoc.RawBlock(fmt, [[\begin{]]..texenv.."}\n"..out.."\n"..[[\end{]].. texenv .. "}") return pandoc.RawBlock(fmt, [[\begin{]]..texenv.."}\n"..out.."\n"..[[\end{]].. texenv .. "}")
end end
if fmt == 'typst' then if fmt == 'typst' then
if texenv == "OutputCell" then return pandoc.RawBlock(fmt, "#"..texenv.."[\n"..out.."\n]")
return pandoc.RawBlock(fmt, "#"..texenv.."[\n" .. escapeTypstString2(out) .. "\n]")
else
return pandoc.RawBlock(fmt, "#"..texenv.."[\n" .. out .. "\n]")
end
end end
@@ -433,52 +398,12 @@ local function divCodeBlockNoHeader1(e)
if el.t == 'Header' then if el.t == 'Header' then
el.level = 6 el.level = 6
end end
-- if el.t == 'CodeBlock' then -- attempt for typst, but we use an extra quarto cell
-- for i,v in ipairs(el.classes) do
-- if v=="julia" or v=="jldoctest" then -- example code and before
-- el.classes:remove(i)
-- end
-- end
-- end
end end
return e return e
end end
-- test if two divs should be merged
local function testmerge(d1, d2)
return d1 and d1.t == "Div" and d1.classes:includes("cell-output") and #d1.content == 1
and d2 and d2.t == "Div" and d2.classes:includes("cell-output") and #d2.content == 1
and d1.content[1].t == "CodeBlock" and not d1.classes:includes("cell-output-stderr")
and d2.content[1].t == "CodeBlock" and not d2.classes:includes("cell-output-stderr")
end
-- merge (div (codecell (text1)), div (codecell(text2))) to div(codecell(text1+text2))
local function blockMerge(es)
local nl = ""
for i = #es-1, 1, -1 do
if testmerge(es[i], es[i+1]) then
str1 = es[i].content[1].text
str2 = es[i+1].content[1].text
nl = "\n"
if es[i].classes:includes("cell-output-stdout") and es[i+1].classes:includes("cell-output-stdout") then
if str1:sub(-1) == "\n" then
nl = ""
end
if str2:sub(1, 1) == "\n" then
nl = ""
end
end
es[i].content[1].text = str1 .. nl .. str2
es:remove(i+1)
end
end
return es
end
return { return {
{Div = divStderr}, {Div = divStderr},
{Div = divCodeBlockNoHeader1}, {Div = divCodeBlockNoHeader1},
{Blocks = blockMerge},
{CodeBlock = codeBlockTrans}, {CodeBlock = codeBlockTrans},
} }

View File

@@ -1,38 +0,0 @@
// Chapter-based numbering for books with appendix support
#let equation-numbering = it => {
let pattern = if state("appendix-state", none).get() != none { "(A.1)" } else { "(1.1)" }
numbering(pattern, counter(heading).get().first(), it)
}
#let callout-numbering = it => {
let pattern = if state("appendix-state", none).get() != none { "A.1" } else { "1.1" }
numbering(pattern, counter(heading).get().first(), it)
}
#let subfloat-numbering(n-super, subfloat-idx) = {
let chapter = counter(heading).get().first()
let pattern = if state("appendix-state", none).get() != none { "A.1a" } else { "1.1a" }
numbering(pattern, chapter, n-super, subfloat-idx)
}
// Theorem configuration for theorion
// Chapter-based numbering (H1 = chapters)
#let theorem-inherited-levels = 1
// Appendix-aware theorem numbering
#let theorem-numbering(loc) = {
if state("appendix-state", none).at(loc) != none { "A.1" } else { "1.1" }
}
// Theorem render function
// Note: brand-color is not available at this point in template processing
#let theorem-render(prefix: none, title: "", full-title: auto, body) = {
block(
width: 100%,
inset: (left: 1em),
stroke: (left: 2pt + black),
)[
#if full-title != "" and full-title != auto and full-title != none {
strong[#full-title]
linebreak()
}
#body
]
}

View File

@@ -1,69 +0,0 @@
-- orange-book.lua
-- Orange-book specific part and appendix handling for Typst books
local function is_typst_book()
local file_state = quarto.doc.file_metadata()
return quarto.doc.is_format("typst") and
file_state ~= nil and
file_state.file ~= nil
end
local header_filter = {
Header = function(el)
local file_state = quarto.doc.file_metadata()
if not is_typst_book() then
return nil
end
if file_state == nil or file_state.file == nil then
return nil
end
local file = file_state.file
local bookItemType = file.bookItemType
if el.level ~= 1 or bookItemType == nil then
return nil
end
-- Handle parts
if bookItemType == "part" then
return pandoc.RawBlock('typst', '#part[' .. pandoc.utils.stringify(el.content) .. ']')
end
-- Handle appendices
if bookItemType == "appendix" then
-- First appendix triggers the show rule with localized "Appendices" title
if file.bookItemNumber == 1 or file.bookItemNumber == nil then
-- Get localized title from language settings
local language = quarto.doc.language
local appendicesTitle = (language and language["section-title-appendices"]) or "Appendices"
-- Use hide-parent: true to work around orange-book bug where unnumbered headings
-- (like Bibliography) trigger duplicate "Appendices" TOC entries.
local appendixStart = pandoc.RawBlock('typst',
'#show: appendices.with("' .. appendicesTitle .. '", hide-parent: true)')
-- If this is the synthetic "Appendices" divider heading (has .unnumbered class),
-- emit our own Appendices heading for TOC display
if el.classes:includes("unnumbered") then
local appendicesHeading = pandoc.RawBlock('typst',
'#heading(level: 1, numbering: none)[' .. appendicesTitle .. ']')
return {appendixStart, appendicesHeading}
end
return {appendixStart, el}
end
end
return nil
end
}
-- Combine with file_metadata_filter so book metadata markers are parsed
-- during this filter's document traversal (needed for bookItemType, etc.)
return quarto.utils.combineFilters({
quarto.utils.file_metadata_filter(),
header_filter
})

View File

@@ -1,15 +0,0 @@
#set page(
paper: $if(papersize)$"$papersize$"$else$"us-letter"$endif$,
$if(margin-geometry)$
// Margins handled by marginalia.setup in typst-show.typ AFTER book.with()
$elseif(margin)$
margin: ($for(margin/pairs)$$margin.key$: $margin.value$,$endfor$),
$else$
margin: (x: 1.25in, y: 1.25in),
$endif$
numbering: $if(page-numbering)$"$page-numbering$"$else$none$endif$,
columns: $if(columns)$$columns$$else$1$endif$,
)
// Logo is handled by orange-book's cover page, not as a page background
// NOTE: marginalia.setup is called in typst-show.typ AFTER book.with()
// to ensure marginalia's margins override the book format's default margins

View File

@@ -2,45 +2,10 @@
#show raw: set text(font: "JuliaMono") #show raw: set text(font: "JuliaMono")
// define cell layout // define cell layout
#let OutputCell = block.with(width:100%, inset: 5pt)
//#let EndLine() = raw("\n") #let AnsiOutputCell = block.with(width: 100%, inset: 5pt)
//#let OutputCell(lines) = {
// let blocks = []
// for ln in lines {
// blocks = blocks + ln + EndLine()
// }
// block(width:100%, inset:(x:5pt, y:0pt), stroke:( left: 2pt + gray), blocks)
//}
#let OutputCell(content) = block(
width: 100%,
inset: (x: 5pt, y: 5pt),
above: 0pt,
below: 8pt,
stroke: (left: 2pt + gray, bottom: .5pt + gray)
)[
#set text(font: "JuliaMono", size:8pt)
#content
]
#let AnsiOutputCell(content) = block(
width: 100%,
inset: (x: 5pt, y: 5pt),
above: 0pt,
below: 8pt,
stroke: (left: 2pt + gray, bottom: .5pt + gray)
)[
#set text(font: "JuliaMono", size:9pt)
#content
]
// does not exist with julia engine
#let StderrOutputCell = block.with(width: 100%, stroke: 1pt + red, inset: 5pt) #let StderrOutputCell = block.with(width: 100%, stroke: 1pt + red, inset: 5pt)
//#set highlight(top-edge: "ascender", bottom-edge: "descender") //#set highlight(top-edge: "ascender", bottom-edge: "descender")
#let invertbox(color, c) = box(outset: (x: 0.05em, y: 0.25em), fill: color, c) #let invertbox(color, c) = box(outset: (x: 0.05em, y: 0.25em), fill: color, c)

View File

@@ -1,61 +0,0 @@
#import "@preview/orange-book:0.7.1": book, part, chapter, appendices
#show: book.with(
$if(title)$
title: [$title$],
$endif$
$if(subtitle)$
subtitle: [$subtitle$],
$endif$
$if(by-author)$
author: "$for(by-author)$$it.name.literal$$sep$, $endfor$",
$endif$
$if(date)$
date: "$date$",
$endif$
$if(lang)$
lang: "$lang$",
$endif$
main-color: brand-color.at("primary", default: blue),
logo: {
let logo-info = brand-logo.at("medium", default: none)
if logo-info != none { image(logo-info.path, alt: logo-info.at("alt", default: none)) }
},
$if(toc-depth)$
outline-depth: $toc-depth$,
$endif$
$if(lof)$
list-of-figure-title: "$if(crossref.lof-title)$$crossref.lof-title$$else$$crossref-lof-title$$endif$",
$endif$
$if(lot)$
list-of-table-title: "$if(crossref.lot-title)$$crossref.lot-title$$else$$crossref-lot-title$$endif$",
$endif$
$if(margin-geometry)$
padded-heading-number: false,
$endif$
)
$if(margin-geometry)$
// Configure marginalia page geometry for book context
// Geometry computed by Quarto's meta.lua filter (typstGeometryFromPaperWidth)
// IMPORTANT: This must come AFTER book.with() to override the book format's margin settings
#import "@preview/marginalia:0.3.1" as marginalia
#show: marginalia.setup.with(
inner: (
far: $margin-geometry.inner.far$,
width: $margin-geometry.inner.width$,
sep: $margin-geometry.inner.separation$,
),
outer: (
far: $margin-geometry.outer.far$,
width: $margin-geometry.outer.width$,
sep: $margin-geometry.outer.separation$,
),
top: $if(margin.top)$$margin.top$$else$1.25in$endif$,
bottom: $if(margin.bottom)$$margin.bottom$$else$1.25in$endif$,
// CRITICAL: Enable book mode for recto/verso awareness
book: true,
clearance: $margin-geometry.clearance$,
)
$endif$

View File

@@ -4,15 +4,15 @@ project:
- fonts/ - fonts/
- images/ - images/
lang: en lang: de
#language: language:
# title-block-published: "Updated" title-block-published: "Updated"
# title-block-author-single: "Autor" title-block-author-single: "Autor"
# toc-title-document: "Auf dieser Seite" toc-title-document: "Auf dieser Seite"
book: book:
title: "Julia for Numerical Analysis" title: "Julia für Numerik"
subtitle: "Introduction to Scientific Computing" subtitle: "Einführung in die wissenschaftliche Programmierung"
author: "Meik Hellmund" author: "Meik Hellmund"
site-url: "https://www.math.uni-leipzig.de/~hellmund/juliabook" site-url: "https://www.math.uni-leipzig.de/~hellmund/juliabook"
favicon: "images/favicon-32x32.png" favicon: "images/favicon-32x32.png"
@@ -23,7 +23,7 @@ book:
- icon: github - icon: github
href: https://gitea.math.uni-leipzig.de/hellmund/JuliaKurs23 href: https://gitea.math.uni-leipzig.de/hellmund/JuliaKurs23
- icon: download - icon: download
href: "Julia-for-Numerical-Analysis.pdf" href: "Julia-f%C3%BCr-Numerik.pdf"
search: true search: true
@@ -56,7 +56,7 @@ book:
- chapters/10_Strings.qmd - chapters/10_Strings.qmd
- chapters/13_IO.qmd - chapters/13_IO.qmd
- chapters/14_Plot.qmd - chapters/14_Plot.qmd
# - chapters/makie.qmd
format: format:
@@ -82,33 +82,12 @@ format:
cap-location: bottom cap-location: bottom
html-math-method: mathjax html-math-method: mathjax
# julia-color-pdf: julia-color-pdf:
# pdf-engine: xelatex pdf-engine: xelatex
# papersize: a4
# documentclass: scrreprt
# classoption: [notitlepage,DIV=16,BCOR=5mm,10pt]
# toc: false
# number-depth: 2
# fig-cap-location: bottom
# fig-pos: H
# tbl-cap-location: bottom
# hyperrefoptions:
# - linktoc=all
# colorlinks: true
# linkcolor: "blue"
# keep-tex: true
# keep-ipynb: true
# keep-md: true
# code-block-bg: "#e0e0e0"
# code-block-border-left: "#e0e0e0"
# code-overflow: wrap
# include-in-header:
# - file: macros.tex
julia-color-typst:
papersize: a4 papersize: a4
toc: true documentclass: scrreprt
toc-depth: 2 classoption: [notitlepage,DIV=16,BCOR=5mm,10pt]
toc: false
number-depth: 2 number-depth: 2
fig-cap-location: bottom fig-cap-location: bottom
fig-pos: H fig-pos: H
@@ -116,12 +95,16 @@ format:
hyperrefoptions: hyperrefoptions:
- linktoc=all - linktoc=all
colorlinks: true colorlinks: true
linkcolor: #0000FF linkcolor: "blue"
keep-typ: true keep-tex: true
keep-ipynb: true
keep-md: true
code-block-bg: "#e0e0e0"
code-block-border-left: "#e0e0e0"
code-overflow: wrap
include-in-header: include-in-header:
- file: macros.typ - file: macros.tex
latex-auto-install: false latex-auto-install: false
execute: execute:
@@ -139,6 +122,8 @@ keep-ipynb: true
keep-tex: true keep-tex: true
keep-md: true keep-md: true
jupyter: julia-1.10
filters: filters:
- code-visibility - code-visibility
- latex-environment - latex-environment

View File

@@ -9,98 +9,98 @@ engine: julia
using InteractiveUtils using InteractiveUtils
import QuartoNotebookWorker import QuartoNotebookWorker
Base.stdout = QuartoNotebookWorker.with_context(stdout) 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 are: Bis heute relevant sind:
### ASCII ### ASCII
The American Standard Code for Information Interchange (ASCII) 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: - Er definiert $2^7=128$ Zeichen, und zwar:
- 33 control characters, such as `newline`, `escape`, `end of transmission/file`, `delete` - 33 Steuerzeichen, wie `newline`, `escape`, `end of transmission/file`, `delete`
- 95 graphically printable characters: - 95 graphisch darstellbare Zeichen:
- 52 Latin letters `a-z, A-Z` - 52 lateinische Buchstaben `a-z, A-Z`
- 10 digits `0-9` - 10 Ziffern `0-9`
- 7 punctuation marks `.,:;?!"` - 7 Satzzeichen `.,:;?!"`
- 1 space ` ` - 1 Leerzeichen ` `
- 6 parentheses `[{()}]` - 6 Klammern `[{()}]`
- 7 mathematical operations `+-*/<>=` - 7 mathematische Operationen `+-*/<>=`
- 12 special characters ``` #$%&'\^_|~`@ ``` - 12 Sonderzeichen ``` #$%&'\^_|~`@ ```
- ASCII is still the "lowest common denominator" in the encoding chaos. - ASCII ist heute noch der "kleinste gemeinsame Nenner" im Codierungs-Chaos.
- The first 128 Unicode characters are identical to ASCII. - Die ersten 128 Unicode-Zeichen sind identisch mit ASCII.
### ISO 8859 Character Sets ### ISO 8859-Zeichensätze
- ASCII uses only 7 bits. - ASCII nutzt nur 7 Bits.
- In a byte, you can fit another 128 characters by setting the 8th bit. - In einem Byte kann man durch Setzen des 8. Bits weitere 128 Zeichen unterbringen.
- In 1987/88, various 1-byte encodings were standardized in ISO 8859, all ASCII-compatible, including: - 1987/88 wurden im ISO 8859-Standard verschiedene 1-Byte-Codierungen festgelegt, die alle ASCII-kompatibel sind, darunter:
:::{.narrow} :::{.narrow}
|Encoding | Region | Languages| |Codierung | Region | Sprachen|
|:-----------|:----------|:-------| |:-----------|:----------|:-------|
|ISO 8859-1 (Latin-1) | Western Europe | German, French,..., Icelandic |ISO 8859-1 (Latin-1) | Westeuropa | Deutsch, Französisch,...,Isländisch
|ISO 8859-2 (Latin-2) | Eastern Europe | Slavic languages with Latin script |ISO 8859-2 (Latin-2) | Osteuropa | slawische Sprachen mit lateinischer Schrift
|ISO 8859-3 (Latin-3) | Southern Europe | Turkish, Maltese,... |ISO 8859-3 (Latin-3) | Südeuropa | Türkisch, Maltesisch,...
|ISO 8859-4 (Latin-4) | Northern Europe | Estonian, Latvian, Lithuanian, Greenlandic, Sami |ISO 8859-4 (Latin-4) | Nordeuropa | Estnisch, Lettisch, Litauisch, Grönländisch, Sami
|ISO 8859-5 (Latin/Cyrillic) | Eastern Europe | Slavic languages with Cyrillic script |ISO 8859-5 (Latin/Cyrillic) | Osteuropa | slawische Sprachen mit kyrillischer Schrift
|ISO 8859-6 (Latin/Arabic) | | |ISO 8859-6 (Latin/Arabic) | |
|ISO 8859-7 (Latin/Greek) | | |ISO 8859-7 (Latin/Greek) | |
|...| | |...| |
|ISO 8859-15 (Latin-9)| | 1999: Revision of Latin-1: now including Euro sign |ISO 8859-15 (Latin-9)| | 1999: Revision von Latin-1: jetzt u.a. mit Euro-Zeichen
::: :::
## Unicode ## Unicode
The goal of the Unicode Consortium is a uniform encoding for all scripts worldwide. Das Ziel des Unicode-Consortiums ist eine einheitliche Codierung für alle Schriften der Welt.
- Unicode version 1 was published in 1991 - Unicode Version 1 erschien 1991
- Unicode version 17 was published in 2025 with 159,801 characters, including: - Unicode Version 15.1 erschien 2023 mit 149 813 Zeichen, darunter:
- 172 scripts - 161 Schriften
- mathematical and technical symbols - mathematische und technische Symbole
- Emojis and other symbols, control and formatting characters - Emojis und andere Symbole, Steuer- und Formatierungszeichen
- Over 90,000 characters are assigned to the CJK scripts (Chinese/Japanese/Korean) - 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`, which is simply a sequential number written hexadecimally Im Standard wird jedes Zeichen beschrieben duch
- either with 4 digit as `U+XXXX` (zeroth plane)
- or with 6 digit as `U+XXXXXX` (further planes)
- Each plane ranges from `U+XY0000` to `U+XYFFFF`, thus containing $2^{16}=65\;534$ characters.
- 17 planes `XY=00` to `XY=10` are provided, giving a 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 have been assigned only from these planes:
- 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`.
- `U+0000` to `U+007F` is identical to ASCII
- `U+0000` to `U+00FF` is identical to ISO 8859-1 (Latin-1)
### 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 Im Unicode-Standard sieht das dann so aus (zur Vereinfachung nur Codepoint und Name):
- 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 (simplified, only codepoint and name):
``` ```
... ...
U+0041 LATIN CAPITAL LETTER A U+0041 LATIN CAPITAL LETTER A
@@ -118,47 +118,45 @@ 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} ```{julia}
'\U21b4' '\U21b4'
``` ```
### A Selection of Scripts ### Eine Auswahl an Schriften
::: {.content-visible when-format="html"} ::: {.content-visible when-format="html"}
:::{.callout-note} :::{.callout-note}
If individual characters or scripts are not displayable in your browser, you must install appropriate Falls im Folgenden einzelne Zeichen oder Schriften in Ihrem Browser nicht darstellbar sind, müssen Sie geeignete
fonts on your computer. 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} ```{julia}
function printuc(c, n) function printuc(c, n)
for i in 1:n for i in 0:n-1
print(c + i -1) print(c + i)
if i%70 == 0 print("\n") end
end end
end end
``` ```
__Cyrillic__ __Kyrillisch__
```{julia} ```{julia}
printuc('\U0400', 100) printuc('\U0400', 100)
``` ```
__Tamil__ __Tamilisch__
:::{.cellmerge} :::{.cellmerge}
```{julia} ```{julia}
@@ -179,21 +177,21 @@ printuc('\U0be7',20)
::: :::
__Chess__ __Schach__
```{julia} ```{julia}
printuc('\U2654', 12) printuc('\U2654', 12)
``` ```
__Mathematical Operators__ __Mathematische Operatoren__
```{julia} ```{julia}
printuc('\U2200', 255) printuc('\U2200', 255)
``` ```
__Runes__ __Runen__
```{julia} ```{julia}
@@ -202,11 +200,12 @@ printuc('\U16a0', 40)
:::{.cellmerge} :::{.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 it represents.
- There is only one single document in this script: the Phaistos Disc from the Bronze Age.
```{julia} ```{julia}
@@ -227,53 +226,55 @@ 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 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. - __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.
- In __UTF-16__, a codepoint is represented either with 2 bytes or with 4 bytes. - Bei __UTF-16__ wird ein Codepoint entweder mit 2 Bytes oder mit 4 Bytes dargestellt.
- In __UTF-8__, a codepoint is represented with 1, 2, 3, or 4 bytes. - Bei __UTF-8__ wird ein Codepoint mit 1,2,3 oder 4 Bytes dargestellt.
- __UTF-8__ is the format with the highest prevalence. Julia also uses it. - __UTF-8__ ist das Format mit der höchsten Verbreitung. Es wird auch von Julia verwendet.
### UTF-8 ### 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, you must be able to recognize which byte sequences belong together: - Bei einer Codierung mit variabler Länge muss man erkennen können, welche Bytefolgen zusammengehören:
- A byte of the form 0xxxxxxx represents an ASCII codepoint of length 1. - Ein Byte der Form 0xxxxxxx steht für einen ASCII-Codepoint der Länge 1.
- A byte of the form 110xxxxx starts a 2-byte code. - Ein Byte der Form 110xxxxx startet einen 2-Byte-Code.
- A byte of the form 1110xxxx starts a 3-byte code. - Ein Byte der Form 1110xxxx startet einen 3-Byte-Code.
- A byte of the form 11110xxx starts a 4-byte code. - Ein Byte der Form 11110xxx startet einen 4-Byte-Code.
- All further bytes of a 2-, 3-, or 4-byte code have the form 10xxxxxx. - Alle weiteren Bytes eines 2-,3- oder 4-Byte-Codes haben die Form 10xxxxxx.
- Thus, the space available for the codepoint (number of x) is: - Damit ist der Platz, der für den Codepoint zur Verfügung steht (Anzahl der x):
- One-byte code: 7 bits - Ein-Byte-Code: 7 Bits
- Two-byte code: 5 + 6 = 11 bits - Zwei-Byte-Code: 5 + 6 = 11 Bits
- Three-byte code: 4 + 6 + 6 = 16 bits - Drei-Byte-Code: 4 + 6 + 6 = 16 Bits
- Four-byte code: 3 + 6 + 6 + 6 = 21 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 (equivalent to 21 bits, resulting in approximately 1.1 million possible characters) currently defined in Unicode are ever depleted, UTF-8 can be extended to include 5- and 6-byte code sequences. - 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.
## Characters and Strings in Julia ## Zeichen und Zeichenketten in Julia
### Characters ### Zeichen: `Char`
The `Char` type encodes a single Unicode character. Der Datentyp `Char` kodiert ein einzelnes Unicode-Zeichen.
- Julia uses single quotes for characters: `'a'`. - Julia verwendet dafür einfache Anführungszeichen: `'a'`.
- A `Char` occupies 4 bytes of memory and - Ein `Char` belegt 4 Bytes Speicher und
- represents a Unicode codepoint. - repräsentiert einen Unicode-Codepoint.
- `Char`s can be converted to/from `UInt`s and - `Char`s können von/zu `UInt`s umgewandelt werden und
- the integer value is equal to the Unicode codepoint. - der Integer-Wert ist gleich dem Unicode-codepoint.
`Char`s can be converted to/from `UInt`s: `Char`s können von/zu `UInt`s umgewandelt werden.
```{julia} ```{julia}
UInt('a') UInt('a')
``` ```
@@ -283,10 +284,10 @@ UInt('a')
b = Char(0x2656) b = Char(0x2656)
``` ```
### Strings ### Zeichenketten: `String`
- In Julia, strings are denoted with double quotes: `"a"`. - Für Strings verwendet Julia doppelte Anführungszeichen: `"a"`.
- These strings are encoded in UTF-8, where a single character may consist of 1 to 4 bytes. - Sie sind UTF-8-codiert, d.h., ein Zeichen kann zwischen 1 und 4 Bytes lang sein.
```{julia} ```{julia}
@@ -296,20 +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} ```{julia}
asciistr = "Hello World!" asciistr = "Hello World!"
@show length(asciistr) ncodeunits(asciistr); @show length(asciistr) ncodeunits(asciistr);
``` ```
(Das Leerzeichen zählt natürlich auch.)
```{julia} ```{julia}
str = "😄 Hellö 🎶" str = "😄 Hellö 🎶"
@show length(str) ncodeunits(str); @show length(str) ncodeunits(str);
``` ```
__Iterating over a string iterates over the characters:__ __Iteration über einen String iteriert über die Zeichen:__
```{julia} ```{julia}
@@ -318,71 +320,76 @@ for i in str
end 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} ```{julia}
str * asciistr * str str * asciistr * str
``` ```
Powers with natural exponents are thus also defined. Damit sind auch Potenzen mit natürlichem Exponenten definiert.
```{julia} ```{julia}
str^3, str^0 str^3, str^0
``` ```
### String Interpolation ### Stringinterpolation
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:
The dollar sign serves a special purpose in strings, frequently utilized within `print()` statements. It enables the interpolation of variables or expressions.
```{julia} ```{julia}
a = 33.4 a = 33.4
b = "x" 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. Der _backslash_ `\` hat in Stringkonstanten ebenfalls eine Sonderfunktion.
Julia uses the backslash codings known from C and other languages for special characters, dollar signs, and backslashes themselves: Julia benutzt die von C und anderen Sprachen bekannten _backslash_-Codierungen für Sonderzeichen und für Dollarzeichen und Backslash selbst:
```{julia} ```{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) print(s)
``` ```
### Triple Quotes ### Triple-Quotes
Man kann Strings auch mit Triple-Quotes begrenzen.
In dieser Form bleiben Zeilenumbrüche und Anführungszeichen erhalten:
Strings may also be enclosed in triple quotes, preserving line breaks and embedded quotes:
```{julia} ```{julia}
s = """ s = """
This should Das soll
be a "longer" ein "längerer"
'text'. 'Text' sein.
""" """
print(s) print(s)
``` ```
### Raw Strings ### Raw strings
In einem `raw string` sind alle backslash-Codierungen außer `\"` abgeschaltet:
In a `raw string`, all backslash escape sequences except for `\"` are disabled:
```{julia} ```{julia}
s = raw"A $ and a \ and two \\ and a 'bla'..." s = raw"Ein $ und ein \ und zwei \\ und ein 'bla'..."
print(s) 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} ```{julia}
@@ -390,9 +397,9 @@ print(s)
@show isnumeric('½') iscntrl('\n') ispunct(';'); @show isnumeric('½') iscntrl('\n') ispunct(';');
``` ```
### Application to Strings ### Anwendung auf Strings
These tests can be used on strings with `all()`, `any()`, or `count()`: Diese Tests lassen sich z.B. mit `all()`, `any()` oder `count()` auf Strings anwenden:
```{julia} ```{julia}
@@ -401,7 +408,7 @@ all(ispunct, ";.:")
```{julia} ```{julia}
any(isdigit, "It is 3 o'clock! 🕒" ) any(isdigit, "Es ist 3 Uhr! 🕒" )
``` ```
@@ -409,7 +416,7 @@ any(isdigit, "It is 3 o'clock! 🕒" )
count(islowercase, "Hello, du!!") count(islowercase, "Hello, du!!")
``` ```
### Other String Functions ### Weitere String-Funktionen
```{julia} ```{julia}
@@ -431,49 +438,50 @@ count(islowercase, "Hello, du!!")
```{julia} ```{julia}
split("π is irrational.") split("π ist irrational.")
``` ```
```{julia} ```{julia}
replace("π is irrational.", "is" => "is allegedly") replace("π ist irrational.", "ist" => "ist angeblich")
``` ```
## Indexing of Strings ## Indizierung von Strings
Strings are immutable but indexable, with a few special features: Strings sind nicht mutierbar aber indizierbar. Dabei gibt es ein paar Besonderheiten.
- The index numbers the bytes of the string. - Der Index nummeriert die Bytes des Strings.
- For a non-ASCII string, not all indices are valid because a valid index always addresses a Unicode character. - 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} ```{julia}
str str
``` ```
The first character Das erste Zeichen
```{julia} ```{julia}
str[1] 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} ```{julia}
str[2] str[2]
``` ```
Only the 5th byte is a new character: Erst das 5. Byte ist ein neues Zeichen:
```{julia} ```{julia}
str[5] 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} ```{julia}
str[1:7] 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} ```{julia}
for i in eachindex(str) for i in eachindex(str)
@@ -482,24 +490,24 @@ for i in eachindex(str)
end end
``` ```
As usual, `collect()` makes an iterator into a vector. Wie üblich macht collect() aus einem Iterator einen Vektor.
```{julia} ```{julia}
collect(eachindex(str)) collect(eachindex(str))
``` ```
The function `nextind()` returns the next valid index. Die Funktion `nextind()` liefert den nächsten gültigen Index.
```{julia} ```{julia}
@show nextind(str, 1) nextind(str, 2); @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., book text), the position `s[123455]` can be found quickly with a byte index. - In einem langen String, z.B. einem Buchtext, ist die Stelle `s[123455]` mit einem Byte-Index schnell zu finden.
- A character index would have to traverse the entire string in UTF-8 encoding to find the n-th character, since characters can be 1, 2, 3, or 4 bytes long. - 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} ```{julia}
@@ -521,8 +529,9 @@ str2 = "αβγδϵ"^3
n = findfirst('γ', str2) n = findfirst('γ', str2)
``` ```
So you 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} ```{julia}
findnext('γ', str2, nextind(str2, n)) findnext('γ', str2, nextind(str2, n))
``` ```

View File

@@ -7,34 +7,17 @@ engine: julia
#| echo: false #| echo: false
#| output: false #| output: false
using InteractiveUtils using InteractiveUtils
#struct M a::Int end; x = M(22); @show x
#should not print "Main.Notebook.M(22)" but only "M(22)"
function Base.show(io::IO, x::T) where T
if parentmodule(T) == @__MODULE__
# Print "TypeName(fields...)" without module prefix
print(io, nameof(T), "(")
fields = fieldnames(T)
for (i, f) in enumerate(fields)
print(io, getfield(x, f))
i < length(fields) && print(io, ", ")
end
print(io, ")")
else
invoke(Base.show, Tuple{IO, Any}, io, x)
end
end
``` ```
# Linear Algebra in Julia # Lineare Algebra in Julia
```{julia} ```{julia}
using LinearAlgebra using LinearAlgebra
``` ```
The `LinearAlgebra` package provides, among other things: Das `LinearAlgebra`-Paket liefert unter anderem:
- additional subtypes of `AbstractMatrix` which are usable like other matrices, among them: - zusätzliche Subtypen von `AbstractMatrix`: genauso verwendbar, wie andere Matrizen, z.B.
- `Tridiagonal` - `Tridiagonal`
- `SymTridiagonal` - `SymTridiagonal`
@@ -42,26 +25,26 @@ The `LinearAlgebra` package provides, among other things:
- `UpperTriangular` - `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: `\` - einen universellen Solver für lineare Gleichungssysteme: `\`
- `x = A \ b` solves $A \mathbf{x}=\mathbf{b}$ by appropriate matrix factorization and forward/backward substitution - `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` - `LU`
- `QR` - `QR`
- `Cholesky` - `Cholesky`
- `SVD` - `SVD`
- ... - ...
- Computation of eigenvalues/eigenvectors - Berechnung von Eigenwerte/-vektoren
- `eigen`, `eigvals`, `eigvecs` - `eigen`, `eigvals`, `eigvecs`
- Access to BLAS/LAPACK functions - Zugriff auf BLAS/LAPACK-Funktionen
## Special Matrix Types ## Matrixtypen
@@ -74,31 +57,31 @@ A = SymTridiagonal(fill(1.0, 4), fill(-0.3, 3))
B = UpperTriangular(A) 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} ```{julia}
A + B A + B
``` ```
Read-only index access is possible, Lesende Indexzugriffe sind möglich,
```{julia} ```{julia}
A[1,4] A[1,4]
``` ```
Write operations are not necessarily possible: schreibende nicht unbedingt:
```{julia} ```{julia}
#| error: true #| error: true
A[1,3] = 17 A[1,3] = 17
``` ```
Conversion to a 'normal' matrix is possible using `collect()`: Die Umwandlung in eine 'normale' Matrix ist z.B. mit `collect()` möglich:
```{julia} ```{julia}
A2 = collect(A) A2 = collect(A)
``` ```
### The Identity Matrix `I` ### Die Einheitsmatrix `I`
`I` denotes an identity matrix (square, diagonal elements = 1, all others = 0) of the required size `I` bezeichnet eine Einheitsmatrix (quadratisch, Diagonalelemente = 1, alle anderen = 0) in der jeweils erforderlichen Größe
```{julia} ```{julia}
@@ -106,39 +89,39 @@ A + 4I
``` ```
## Norms ## Normen
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) := \lVert x-y\rVert 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
$$ $$
\lVert \mathbf{x} \rVert_p = \left(\sum |x_i|^p\right)^\frac{1}{p}, ||\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} :::{.callout-note}
## The Max-Norm $p=\infty$ ## Die Max-Norm $p=\infty$
Let $x_{\text{max}}$ be the component of $\mathbf{x}\in ^n$ with the largest absolute value. Then always Sei $x_{\text{max}}$ die _betragsmäßig_ größte Komponente von $\mathbf{x}\in ^n$. Dann gilt stets
$$ \lvert x_{\text{max}}\rvert \le \lVert\mathbf{x}\rVert_p \le n^\frac{1}{p} \lvert x_{\text{max}}\rvert $$ |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.)
It follows that Damit folgt
$$ $$
\lim_{p \rightarrow \infty} \lVert\mathbf{x}\rVert_p = \lvert x_{\text{max}}\rvert =: \lVert\mathbf{x}\rVert_\infty. \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} ```{julia}
v = [3, 4] v = [3, 4]
@@ -147,10 +130,10 @@ w = [-1, 2, 33.2]
@show norm(v) norm(v, 2) norm(v, 1) norm(v, 4) norm(w, Inf); @show norm(v) norm(v, 2) norm(v, 1) norm(v, 4) norm(w, Inf);
``` ```
- If the 2nd argument `p` is missing, `p=2` is set. - Wenn das 2. Argument `p` fehlt, wird `p=2` gesetzt.
- The 2nd argument can also be `Inf` (i.e., $+\infty$). - Das 2. Argument kann auch `Inf` (also $+\infty$) sein.
- The 1st argument can be any numerical container. The sum $\sum \lvert x_i\rvert^p$ extends over *all* elements of the container. - Das 1. Argument kann ein beliebiger Container voller Zahlen sein. Die Summe $\sum |x_i|^p$ erstreckt sich über *alle* Elemente des Containers.
- Thus, for a matrix `norm(A)` is equal to the _Frobenius norm_ of the matrix `A`. - Damit ist für eine Matrix `norm(A)` gleich der _Frobenius-Norm_ der Matrix `A`.
```{julia} ```{julia}
A = [1 2 3 A = [1 2 3
@@ -161,12 +144,12 @@ norm(A) # Frobenius norm
Since norms are homogeneous under multiplication with scalars, Da Normen homogen unter Multiplikation mit Skalaren sind,
$\lVert\lambda \mathbf{x}\rVert = |\lambda|\cdot\lVert\mathbf{x}\rVert$, 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 $||\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 visible by clicking). (Code durch anklicken sichtbar).
```{julia} ```{julia}
#| code-fold: true #| 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 using Plots
colors=[:purple, :green, :red, :blue,:aqua, :black] colors=[:purple, :green, :red, :blue,:aqua, :black]
@@ -180,35 +163,35 @@ for p ∈ (0.8, 1, 1.5, 2, 3.001, 1000)
end end
fig1 fig1
``` ```
We see that, $p\ge 1$ must hold so that the unit ball is convex and $\lVert.\rVert_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)` also works for parameters `p<1`. 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} ::: {.callout-tip}
## Definition ## Definition
Let $V$ be a vector space with dimension $0<n<\infty$ and Sei $V$ ein Vektorraum mit einer Dimension $0<n<\infty$ und
$A$ an $n\times n$-matrix. Then $A$ eine $n\times n$-Matrix. Dann ist
$$ $$
\lVert A\rVert_p = \max_{\lVert\mathbf{v}\rVert_p=1} \lVert A\mathbf{v}\rVert_p ||A||_p = \max_{||\mathbf{v}||_p=1} ||A\mathbf{v}||_p
$$ $$
::: :::
Induced norms are difficult to calculate 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=1$: Spaltensummennorm
- $p=2$: spectral norm and - $p=2$: Spektralnorm und
- $p=\infty$: row sum norm - $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} ```{julia}
A = [ 0 1 A = [ 0 1
@@ -217,7 +200,7 @@ A = [ 0 1
@show opnorm(A, 1) opnorm(A, Inf) opnorm(A, 2) opnorm(A); @show opnorm(A, 1) opnorm(A, Inf) opnorm(A, 2) opnorm(A);
``` ```
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} ```{julia}
#| error: false #| error: false
@@ -231,10 +214,16 @@ CairoMakie.activate!(type = "svg")
```{julia} ```{julia}
#| code-fold: true #| code-fold: true
#| fig-cap: "Image of the unit ball under $v \\mapsto Av$ with $\\lVert A\\rVert\\approx 2.088$" #| fig-cap: "Bild der Einheitskugel unter $v \\mapsto Av$ mit $||A||\\approx 2.088$"
using CairoMakie using CairoMakie
# Makie bug https://github.com/MakieOrg/Makie.jl/issues/3255
# 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()
])
A = [ 0 1 A = [ 0 1
1.2 1.5 ] 1.2 1.5 ]
@@ -252,60 +241,60 @@ Auv = A * [u,v]
fig2 = Figure(size=(800, 400)) fig2 = Figure(size=(800, 400))
lines(fig2[1, 1], xs, ys, color=t, linewidth=5, colormap=:hsv, axis=(; aspect = 1, limits=(-2,2, -2,2), lines(fig2[1, 1], xs, ys, color=t, linewidth=5, colormap=:hsv, axis=(; aspect = 1, limits=(-2,2, -2,2),
title=L"$\mathbf{v}$", titlesize=30)) title=L"$\mathbf{v}$", titlesize=30))
arrows2d!(fig2[1,1], x, y, u, v, tipwidth=10, colormap=:hsv, shaftcolor=range(0,11), shaftwidth=3) arrows!(fig2[1,1], x, y, u, v, arrowsize=10, arrowhead=tri, colormap=:hsv, linecolor=range(0,11), linewidth=3)
Legend(fig2[1,2], MarkerElement[], String[], L"⟹", width=40, height=30, titlesize=30, framevisible=false) Legend(fig2[1,2], MarkerElement[], String[], L"⟹", width=40, height=30, titlesize=30, framevisible=false)
lines(fig2[1,3], Axys[1], Axys[2], color=t, linewidth=5, colormap=:hsv, axis=(; aspect=1, limits=(-2,2, -2,2), lines(fig2[1,3], Axys[1], Axys[2], color=t, linewidth=5, colormap=:hsv, axis=(; aspect=1, limits=(-2,2, -2,2),
title=L"$A\mathbf{v}$", titlesize=30)) title=L"$A\mathbf{v}$", titlesize=30))
arrows2d!(fig2[1,3], x, y, Auv[1], Auv[2], tipwidth=10, colormap=:hsv, shaftcolor=range(0,11), arrows!(fig2[1,3], x, y, Auv[1], Auv[2], arrowsize=10, arrowhead=tri, colormap=:hsv, linecolor=range(0,11),
shaftwidth=3) linewidth=3)
fig2 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) = \lVert A\rVert_p \cdot \lVert A^{-1}\rVert_p \text{cond}_p(A) = ||A||_p \cdot ||A^{-1}||_p
$$ $$
```{julia} ```{julia}
@show cond(A, 1) cond(A, 2) cond(A) cond(A, Inf); @show cond(A, 1) cond(A, 2) cond(A) cond(A, Inf);
``` ```
## Matrix Factorizations ## Matrixfaktorisierungen
The basic tasks of numerical linear algebra: Basisaufgaben der numerischen linearen Algebra:
- Solve a system of linear equations $A\mathbf{x} = \mathbf{b}$. - Löse ein lineares Gleichungssystem $A\mathbf{x} = \mathbf{b}$.
- If no solution exists, find the best approximation, i.e., the vector $\mathbf{x}$ that minimizes $\lVert A\mathbf{x} - \mathbf{b}\rVert$. - Falls keine Lösung existiert, finde die beste Annäherung, d.h., den Vektor $\mathbf{x}$, der $||A\mathbf{x} - \mathbf{b}||$ minimiert.
- Find eigenvalues and eigenvectors $A\mathbf{x} = \lambda \mathbf{x}$ of $A$. - 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$ - **LU-Zerlegung** $A=L\cdot U$
- factorizes a matrix as a product of a _lower_ and an _upper_ triangular matrix - faktorisiert eine Matrix als Produkt einer _lower_ und einer _upper_ Dreiecksmatrix
- always works (possibly after row exchanges - pivoting) - im Deutschen auch LR-Zerlegung (aber die Julia-Funktion heisst `lu()`)
- **Cholesky decomposition** $A=L\cdot L^*$ - geht (eventuell nach Zeilenvertauschung - Pivoting) immer
- the upper triangular matrix is the conjugate of the lower, - **Cholesky-Zerlegung** $A=L\cdot L^*$
- half the effort compared to LU - die obere Dreiecksmatrix ist die konjugierte der unteren,
- only works if $A$ is Hermitian and positive definite - halber Aufwand im Vergleich zu LU
- **QR decomposition** $A=Q\cdot R$ - geht nur, wenn $A$ hermitesch und positiv definit ist
- decomposes $A$ as a product of an orthogonal (or unitary in the complex case) matrix and an upper triangular matrix - **QR-Zerlegung** $A=Q\cdot R$
- $Q$ is length-preserving (rotations and/or reflections); the scalings are described by $R$ - zerlegt $A$ als Produkt einer orthogonalen (bzw. unitären im komplexen Fall) Matrix und einer oberen Dreiecksmatrix
- always works - $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^*$ - **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$. - $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$.
- 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$. - 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 Gaussian elimination: 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:
:::{.content-visible unless-format="typst"}
$$ $$
A=\left[ A=\left[
\begin{array}{ccc} \begin{array}{ccc}
@@ -314,10 +303,10 @@ A=\left[
-2 & 1 & 5 -2 & 1 & 5
\end{array}\right] \end{array}\right]
~ \begin{array}{c} ~ \begin{array}{c}
~\\ ~\\
Z_2 \mapsto Z_2 \mathbin{\color{red}-}\textcolor{red}{3} Z_1\\ Z_2 \mapsto Z_2 \mathbin{\color{red}-}\textcolor{red}{3} Z_1\\
Z_3 \mapsto Z_3 + \textcolor{red}{2} Z_1 Z_3 \mapsto Z_3 + \textcolor{red}{2} Z_1
\end{array} \quad \Longrightarrow\ \end{array} \quad \Longrightarrow\
\left[ \left[
\begin{array}{ccc} \begin{array}{ccc}
1 &2 &2 \\ 1 &2 &2 \\
@@ -325,10 +314,10 @@ A=\left[
& 5 & 9 & 5 & 9
\end{array}\right] \end{array}\right]
~ \begin{array}{c} ~ \begin{array}{c}
~\\ ~\\
~\\ ~\\
Z_3 \mapsto Z_3 + \textcolor{red}{\frac{1}{2}} Z_2 Z_3 \mapsto Z_3 + \textcolor{red}{\frac{1}{2}} Z_2
\end{array} \quad \Longrightarrow\ \end{array} \quad \Longrightarrow\
\left[ \left[
\begin{array}{ccc} \begin{array}{ccc}
1 &2 &2 \\ 1 &2 &2 \\
@@ -336,44 +325,6 @@ A=\left[
& & 8 & & 8
\end{array}\right] = U \end{array}\right] = U
$$ $$
:::
:::{.content-hidden unless-format="typst"}
```{=typst}
$
A = mat(
1, 2, 2;
3, -4, 4;
-2, 1, 5; delim:"["
)
script(vec(
#h(0pt),#h(0pt),#h(0pt),
Z_2 arrow.bar Z_2 text(fill:#red, -) text(fill:#red, 3) Z_1,
Z_3 arrow.bar Z_3 + text(fill:#red, 2) Z_1, delim:#none
))
&arrow.double.long
mat(
1, 2, 2;
, -10, -2;
, 5, 9
)
script(vec(
#h(0pt),
#h(0pt),
#h(0pt),#h(0pt),
Z_3 arrow.bar Z_3 + text(fill:#red, 1/2) Z_2, delim:#none
))
&arrow.double.long
mat(
1, 2, 2;
, -10, -2;
, , 8
) = U
$
```
:::
:::{.content-visible unless-format="typst"}
$$ $$
A = \left[ A = \left[
\begin{array}{ccc} \begin{array}{ccc}
@@ -389,31 +340,13 @@ A = \left[
& & 8 & & 8
\end{array}\right] \end{array}\right]
$$ $$
:::
:::{.content-hidden unless-format="typst"}
```{=typst}
$
A = mat(
1,,;
text(fill:#red, +3),1,;
text(fill:#red, -2),text(fill:#red, -1/2),1
) dot.c
mat(
1,2,3;
,-10,-2;
,,8
)
$
```
:::
- In practice, it is often necessary to solve $A\mathbf{x}=\mathbf{b}$ for a fixed matrix $A$ and multiple right-hand sides $\mathbf{b}$. - Häufig in der Praxis: $A\mathbf{x}=\mathbf{b}$ muss für ein $A$ und viele rechte Seiten $\mathbf{b}$ gelöst werden.
- The factorization of $A$, which has a cubic complexity $\sim n^3$ relative to the size $n$ of the matrix, needs to be performed only once. - Die Faktorisierung, deren Aufwand kubisch $\sim n^3$ mit der Matrixgröße $n$ wächst, muss nur einmal gemacht werden.
- For each subsequent right-hand side $\mathbf{b}$, the forward and backward substitution steps have quadratic complexity $\sim n^2$. - 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} ```{julia}
A = [ 1 2 2 A = [ 1 2 2
3 -4 4 3 -4 4
@@ -428,9 +361,7 @@ display(U)
#### Pivoting #### Pivoting
Let's look at one step of Gaussian elimination: Sehen wir uns einen Schritt der Gauß-Elimination an:
:::{.content-visible unless-format="typst"}
$$ $$
\left[ \left[
\begin{array}{cccccc} \begin{array}{cccccc}
@@ -444,64 +375,37 @@ $$
\end{array} \end{array}
\right] \right]
$$ $$
::: Ziel ist es, als nächstes den Eintrag $a_{i+1,j}$ zum Verschwinden zu bringen, indem zur Zeile $Z_{i+1}$ ein geeignetes Vielfaches von Zeile $Z_i$ addiert wird. Das geht nur, wenn das _Pivotelement_ $\textcolor{red}{a_{ij}}$ nicht Null ist. Falls $\textcolor{red}{a_{ij}}=0$, müssen wir Zeilen vertauschen um dies zu beheben.
:::{.content-hidden unless-format="typst"} 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
```{=typst} in der entsprechenden Spalte der noch zu bearbeitenden Umtermatrix ist. Beim (Zeilen-)Pivoting wird bei jedem Schritt durch Zeilenvertauschung sichergestellt, dass
$ gilt:
mat(
*, dots.c, *, *, dots.c, *;
, dots.down, dots.v, dots.v, , dots.v;
, , *, *, dots.c, *;
, , , text(fill: #red, a_(i j)), dots.c, a_(i n);
, , , text(fill: #blue, a_(i+1, j)), dots.c, a_(i+1, n);
, , , text(fill: #blue, dots.v), , dots.v;
, , , text(fill: #blue, a_(m j)), dots.c, a_(m n)
)
$
```
:::
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* ${\color{red}a_{ij}}$ is not zero. If ${\color{red}a_{ij}}=0$, we must exchange rows to fix this.
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 to ensure that
:::{.content-visible unless-format="typst"}
$$ $$
|\textcolor{red}{a_{ij}}|=\max_{k=i,...,m} |\textcolor{blue}{a_{kj}}| |\textcolor{red}{a_{ij}}|=\max_{k=i,...,m} |\textcolor{blue}{a_{kj}}|
$$ $$
:::
:::{.content-hidden unless-format="typst"}
```{=typst}
$
|text(fill:#red, a_(i j))| = max_(k=1,...,m) | text(fill:#blue, a_(k j)) |
$
```
:::
#### LU in Julia #### LU in Julia
- The factorizations in Julia return a special object that contains the matrix factors and additional information. - Die Faktorisierungen in Julia geben ein spezielles Objekt zurück, das die Matrixfaktoren und weitere
- The Julia function `lu(A)` performs an LU factorization with pivoting. Informationen enthält.
- Die Julia-Funktion `lu(A)` führt eine LU-Faktorisierung mit Pivoting durch.
```{julia} ```{julia}
F = lu(A) F = lu(A)
typeof(F) typeof(F)
``` ```
Elements of the object: Elemente des Objekts:
```{julia} ```{julia}
@show F.L F.U F.p; @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} ```{julia}
L, U, p = lu(A); L, U, p = lu(A);
p p
``` ```
The permutation vector indicates how the rows of the matrix have been permuted. It holds: $$ L\cdot U = P A$$ 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's syntax of indirect indexing allows applying the row permutation with the notation `A[p,:]`:
```{julia} ```{julia}
display(A) display(A)
display(A[p,:]) display(A[p,:])
@@ -509,27 +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} ```{julia}
b = [1, 2, 3] b = [1, 2, 3]
x = F \ b x = F \ b
``` ```
Verification: Probe:
```{julia} ```{julia}
A * x - b A * x - b
``` ```
In Julia, the `\` operator hides a quite universal "matrix solver" which perfoms implicitely an appropriate matrix factorization: In Julia verbirgt sich hinter dem `\`-Operator ein ziemlich universeller "matrix solver" und man kann ihn auch direkt anwenden:
```{julia} ```{julia}
A \ b A \ b
``` ```
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 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 an optimized form](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#man-linalg-abstractq). Conversion to a "normal" matrix is, as always, possible with `collect()` if needed. [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} ```{julia}
F = qr(A) F = qr(A)
@show typeof(F) typeof(F.Q) @show typeof(F) typeof(F.Q)
@@ -537,10 +442,13 @@ display(collect(F.Q))
display(F.R) display(F.R)
``` ```
### Appropriate Factorization ### Passende Faktorisierung
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:
The function `factorize()` returns a factorization appropriate for the given matrix type; see [documentation](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#LinearAlgebra.factorize) for details. This factorization can subsequently be utilized for multiple right-hand sides $\mathbf{b_1}, \mathbf{b_2},\ldots$.
```{julia} ```{julia}
Af = factorize(A) Af = factorize(A)
``` ```
@@ -554,3 +462,4 @@ Af \ [1, 2, 3]
```{julia} ```{julia}
Af \ [5, 7, 9] Af \ [5, 7, 9]
``` ```

View File

@@ -2,23 +2,7 @@
engine: julia engine: julia
--- ---
```{julia} # Ein- und Ausgabe
#| error: false
#| echo: false
#| output: false
using InteractiveUtils
import QuartoNotebookWorker
Base.stdout = QuartoNotebookWorker.with_context(stdout)
```
```{julia}
#| error: false
#| echo: false
#| output: false
flush(stdout)
```
# Input and Output
```{julia} ```{julia}
@@ -38,49 +22,51 @@ Base.active_module() = myactive_module()
``` ```
## Console ## Konsole
The operating system typically provides three channels (_streams_) for a program: Das Betriebssystem stellt für ein Programm üblicherweise 3 Kanäle _(streams)_ zur Verfügung:
- Standard input (`stdin`) - Standardeingabekanal `stdin`
- Standard output (`stdout`) - Standardausgabekanal `stdout` und
- Standard error (`stderr`) - Standardfehlerausgabekanal `stderr`.
When executed in a terminal, console, or shell, the program reads keyboard input through `stdin` and outputs to the terminal via `stdout` and `stderr`. 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()` - Schreiben nach `stdout`: `print()`,`println()`,`printstyled()`
- Writing to `stderr`: `print(stderr,...)`, `println(stderr,...)`, `printstyled(stderr,...)` - Schreiben nach `stderr`: `print(strerr,...)`, `println(stderr,...)`, `printstyled(stderr,...)`
- Reading from `stdin`: `readline()` - Lesen von `stdin`: `readline()`
### Input ### Eingaben
The _Python_ language provides an `input()` function: Die Sprache _Python_ stellt eine Funktion `input()` zur Verfügung:
```{.python} ```{.python}
ans = input("Please enter a positive number!") ans = input("Bitte eine positive Zahl eingeben!")
``` ```
It prints the prompt, waits for input, and returns 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} ```{julia}
function input(prompt = "Input:") function input(prompt = "Eingabe:")
println(prompt) println(prompt)
flush(stdout) flush(stdout)
return chomp(readline()) return chomp(readline())
end end
``` ```
**Comments** **Anmerkungen**
- Write operations are buffered by modern operating systems. `flush(stdout)` empties the buffer and forces the write operation to complete immediately. - Schreibanweisungen werden von modernen Betriebssystemen gebuffert. Mit `flush(stdout)` wird die Leerung des Buffers und sofortige Schreiboperation erzwungen.
- `readline()` returns a string ending with a newline (`\n`). The function `chomp()` removes a trailing line break from the string. - `readline()` liefert einen String zurück, der mit einer Newline `\n` endet. Die Funktion `chomp()` entfernt einen eventuellen Zeilenumbruch vom Ende eines Strings.
```{julia} ```{julia}
#| eval: false #| eval: false
a = input("Please enter two numbers!") a = input("Bitte 2 Zahlen eingeben!")
``` ```
```{julia} ```{julia}
#| echo: false #| echo: false
@@ -88,61 +74,73 @@ a = "34 56"
``` ```
### Processing the Input ### Verarbeitung der Eingabe
> `split(str)` splits a string into "words", returning a string array: > `split(str)` zerlegt einen String in "Wörter" und liefert einen _(array of strings)_:
```{julia} ```{julia}
av = split(a) av = split(a)
``` ```
> `parse(T, str)` tries to convert `str` to type `T`: > `parse(T, str)` versucht, `str` in den Typ `T` umzuwandeln:
```{julia} ```{julia}
v = parse.(Int, av) v = parse.(Int, av)
``` ```
`parse()` throws an error if the string cannot be parsed as type `T`. You can catch the error with `parse()` erzeugt einen Fehler, wenn der String sich nicht als Wertangabe von Typ `T` parsen lässt. Man kann den Fehler mit
`try/catch`, or use `tryparse(T, str)`, which returns `nothing` in such cases. Test the result with `isnothing()`. `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.
## Formatted Output with the `Printf` Macro ### Einzelne Tastenanschläge einlesen
You often need to output numbers or strings with strict formatting: total length, decimal places, alignment, etc. - `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)
For this purpose, the `Printf` package defines the macros `@sprintf` and `@printf`, which work similarly to the corresponding C functions.
## Formatierte Ausgabe mit dem `Printf`-Makro
Oft möchte man Zahlen oder Strings mit einer strikten Formatvorgabe - Gesamtlänge, Nachkommastellen, rechts/linksbündig usw - ausgeben.
Dazu definiert das Paket `Printf` die Makros `@sprintf` und `@printf`, welche sehr ähnlich wie die gleichnamigen C-Funktionen arbeiten.
```{julia} ```{julia}
using Printf using Printf
x = 123.7876355638734 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.3f`) for the variables, followed by the variables themselves. 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 %[flags][width][.precision]type
``` ```
where entries in square brackets are optional. wobei die Angaben in eckigen Klammern alle optional sind.
**Type specifications in placeholders** **Typangaben im Platzhalter**
| | | | | |
|:--|:------------| |:--|:------------|
|`%s`| `string`| |`%s`| `string`|
|`%i`| `integer`| |`%i`| `integer`|
|`%o`| `integer, octal (base 8)`| |`%o`| `integer octal (base=8)`|
|`%x, %X`| `integer, hexadecimal (base 16), digits 0-9a-f or 0-9A-F`| |`%x, %X`| `integer hexadecimal (base=16) with digits 0-9abcdef or 0-9ABCDEF, resp.`|
|`%f`| `floating point`| |`%f`| `floating point number`|
|`%e`| `floating point, scientific notation`| |`%e`| `floating point number, scientific representation`|
|`%g`| `floating point, %f or %e as appropriate`| |`%g`| `floating point, uses %f or %e depending on value`|
: {.striped .hover} : {.striped .hover}
@@ -151,9 +149,9 @@ where entries in square brackets are optional.
| | | | | |
|:----|:-----| |:----|:-----|
|Plus sign| right-aligned (default) | |Pluszeichen| rechtsbündig (Standard)|
|Minus sign| left-aligned | |Minuszeichen| linksbündig|
|Zero| adds leading zeros | |Null| mit führenden Nullen|
: {.striped .hover} : {.striped .hover}
@@ -161,37 +159,37 @@ where entries in square brackets are optional.
**Width** **Width**
``` ```
Minimum number of characters used (more will be taken if necessary) Anzahl der minimal verwendeten Zeichen (wenn nötig, werden auch mehr genommen)
``` ```
### Examples ### Beispiele:
```{julia} ```{julia}
using Printf # Load the package first using Printf # Paket laden nicht vergessen!
``` ```
```{julia} ```{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 indicate the output field boundaries. Die senkrechten Striche sind nicht Teil des Platzhalters. Sie sollen die Begrenzung des Ausgabefeldes anzeigen.
```{julia} ```{julia}
@printf("|%10s|", "Hello") # Minimum length, right-aligned @printf("|%10s|", "Hallo") # Minimallänge, rechtsbündig
``` ```
```{julia} ```{julia}
@printf("|%-10s|", "Hello") # left-aligned @printf("|%-10s|", "Hallo") # linksbündig
``` ```
```{julia} ```{julia}
@printf("|%3s|", "Hello") # Length specification can be exceeded @printf("|%3s|", "Hallo") # Längenangabe kann überschritten werden
# Better a badly formatted table than wrong values! # besser eine 'kaputt formatierte' Tabelle als falsche Werte!
``` ```
@@ -200,34 +198,37 @@ j = 123
k = 90019001 k = 90019001
l = 3342678 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: `@printf` und `@sprintf` können wie alle Makros wie Funktionen aufgerufen werden:
```{julia} ```{julia}
@printf("%i %i", 22, j) @printf("%i %i", 22, j)
``` ```
or as macros, i.e., without parentheses or commas: -- oder wie Makros, also ohne Funktionsklammern und ohne Komma:
```{julia} ```{julia}
@printf "%i %i" 22 j @printf "%i %i" 22 j
``` ```
`@printf` can take a stream as its first argument; otherwise, the argument list consists of: `@printf` kann als erstes Argument noch einen Stream übergeben bekommen.
- format string with placeholders Ansonsten besteht die Argumentliste aus
- variables matching the placeholders in number and type
- Formatstring mit Platzhaltern
- Variablen in der Reihenfolge der Platzhalter, in Anzahl und Typ zu den Platzhaltern passend
```{julia} ```{julia}
@printf(stderr, "First result: %i %s\nSecond result %i", @printf(stderr, "Erstes Resultat: %i %s\nZweites Resultat %i",
j, "(estimated)", k) j, "(geschätzt)" ,k)
``` ```
The macro `@sprintf` does not print; it returns the formatted string: Das Makro `@sprintf` druckt nichts, sondern liefert den ausgefüllten formatierten String zurück:
```{julia} ```{julia}
@@ -239,54 +240,55 @@ str = @sprintf("x = %10.6f", π );
str str
``` ```
### Formatting Floating-Point Numbers ### Formatierung der Gleitkommazahlen:
The _precision_ value specifies: Bedeutung des _Precision_-Wertes:
- `%f` and `%e` formats: maximum decimal places - `%f` und `%e`-Format: maximale Anzahl der Nachkommastellen
- `%g` format: maximum total digits (integer part + decimal places) - `%g`-Format: maximale Anzahl von ausgegebenen Ziffern (Vor- + Nachkommastellen)
```{julia} ```{julia}
x = 123456.7890123456 x = 123456.7890123456
@printf("%20.4f %20.4e", x, x) # 4 decimal places @printf("%20.4f %20.4e", x, x) # 4 Nachkommastellen
``` ```
```{julia} ```{julia}
@printf("%20.7f %20.7e", x, x) # 7 decimal places @printf("%20.7f %20.7e", x, x) # 7 Nachkommastellen
``` ```
```{julia} ```{julia}
@printf("%20.7g %20.4g", x, x) # 7 and 4 digits total, respectively @printf("%20.7g %20.4g", x, x) # insgesamt 7 bzw. 4 Stellen
``` ```
## File Operations ## Dateioperationen
Files are handled by: Dateien werden
- Opening $\Longrightarrow$ creation of a new _stream_ object (in addition to `stdin`, `stdout`, `stderr`) - geöffnet $\Longrightarrow$ dabei ensteht ein neues _stream_-Objekt (zusätzlich zu `stdin, stdout, stderr`)
- Reading from and writing to this _stream_ - dann kann dieser _stream_ gelesen und geschrieben werden
- Closing $\Longrightarrow$ detachment of the _stream_ object from the file - geschlossen $\Longrightarrow$ _stream_-Objekt wird von Datei getrennt
```{.julia}
stream = open(path, mode)
```
- path: Dateiname/pfad
- mode:
``` ```
stream = open(path, mode) "r" read, öffnet am Dateianfang
``` "w" write, öffnet am Dateianfang (Datei wird neu angelegt oder überschrieben)
"a" append, öffnet zum Weiterschreiben am Dateiende
- path: filename or path ```
- 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
```
Let's write a file: Schreiben wir mal eine Datei:
```{julia} ```{julia}
file = open("myfile.txt", "w") file = open("datei.txt", "w")
``` ```
@@ -296,7 +298,7 @@ file = open("myfile.txt", "w")
```{julia} ```{julia}
println(file, " second line") println(file, " zweite Zeile")
``` ```
@@ -304,58 +306,59 @@ println(file, " second line")
close(file) close(file)
``` ```
Let's look at the file: Schauen wir uns die Datei an:
```{julia} ```{julia}
;cat myfile.txt ;cat datei.txt
``` ```
...and now we open it again for reading: ...und jetzt öffnen wir sie wieder zum Einlesen:
```{julia} ```{julia}
stream = open("myfile.txt", "r") stream = open("datei.txt", "r")
``` ```
`readlines(stream)` returns all lines of a text file as a string vector. `readlines(stream)` liefert alle Zeilen einer Textdatei als Vector von Strings.
`eachline(stream)` returns an iterator over the file lines. `eachline(stream)` liefert einen Iterator über die Zeilen der Datei.
```{julia} ```{julia}
n = 0 n = 0
for line in eachline(stream) # Read line by line for line in eachline(stream) # Lese zeilenweise
n += 1 n += 1
println(n, line) # Print with line number println(n, line) # Drucke mit Zeilennummer
end end
close(stream) close(stream)
``` ```
## Packages for File Formats ## Pakete für Dateiformate
Julia packages for various file formats include: 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 formatted tables - [PrettyTables.jl](https://ronisbr.github.io/PrettyTables.jl/stable/) Ausgabe von formatierten Tabellen
- [DelimitedFiles.jl](https://docs.julialang.org/en/v1/stdlib/DelimitedFiles/) Read and write matrices - [DelimitedFiles.jl](https://docs.julialang.org/en/v1/stdlib/DelimitedFiles/) Ein- und Ausgabe von Matrizen u.ä.
- [CSV.jl](https://csv.juliadata.org/stable/) Read and write CSV files - [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/) Read and write Excel files - [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 ### DelimitedFiles.jl
This package offers convenient functions for saving and reading matrices using `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} ```{julia}
using DelimitedFiles using DelimitedFiles
``` ```
Generate a 200×3 matrix of random numbers: Wir erzeugen eine 200×3-Matrix von Zufallszahlen
```{julia} ```{julia}
A = rand(200,3) A = rand(200,3)
``` ```
and save it: und speichern diese
```{julia} ```{julia}
f = open("data2.txt", "w") f = open("data2.txt", "w")
writedlm(f, A) writedlm(f, A)
@@ -363,21 +366,23 @@ close(f)
``` ```
The written file starts like this: Die geschriebene Datei fängt so an:
```{julia} ```{julia}
;head data2.txt ;head data2.txt
``` ```
Reading it back is simple: Das Wiedereinlesen ist noch einfacher:
```{julia} ```{julia}
B = readdlm("data2.txt") B = readdlm("data2.txt")
``` ```
Noch ein Punkt: Beim Umgang mit Dateien wird in Julia oft die `do`-Notation verwendet, s. @sec-do.
In Julia, the `do` notation is frequently utilized for file handling (see @sec-do). The `open()` function includes methods where the first argument is a `function(iostream)`. This function is applied to the stream, which is automatically closed afterward. The `do` notation allows to define this function anonymously: 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} ```{julia}
open("data2.txt", "w") do io open("data2.txt", "w") do io
@@ -385,16 +390,18 @@ open("data2.txt", "w") do io
end 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 provides tables readable by MS Excel and other applications.
- Example: the weather and climate database _Meteostat_.
- The [DataFrames.jl](https://dataframes.juliadata.org/stable/) package handles tabular data conveniently.
```{julia} ```{julia}
using CSV, DataFrames, Downloads 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" url = "https://bulk.meteostat.net/v2/hourly/10018.csv.gz"
http_response = Downloads.download(url) http_response = Downloads.download(url)
@@ -402,26 +409,25 @@ file = CSV.File(http_response, header=false);
``` ```
The data looks like this: Die Daten sehen so aus:
```{julia} ```{julia}
# https://dev.meteostat.net/bulk/hourly.html#endpoints # https://dev.meteostat.net/bulk/hourly.html#endpoints
# #
# Column 1 Date # Spalte 1 Datum
# 2 Time (hour) # 2 Uhrzeit (Stunde)
# 3 Temperature # 3 Temp
# 5 Humidity # 5 Luftfeuchtigkeit
# 6 Precipitation # 6 Niederschlag
# 8 Wind direction # 8 Windrichtung
# 9 Wind speed # 9 Windstärke
df = DataFrame(file) df = DataFrame(file)
``` ```
```{julia} ```{julia}
#| error: false #| error: false
#| echo: false #| echo: false
@@ -432,18 +438,18 @@ describe(df)
Zum bequemen Plotten und zum Umgang mit den Datums- und Zeitformaten in der Wettertabelle
For convenient plotting and date/time handling, we load two packages: laden wir noch 2 Helferlein:
```{julia} ```{julia}
using StatsPlots, Dates 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} ```{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); df[!, :datetime] = DateTime.(df.Column1) .+ Hour.(df.Column2);
``` ```
@@ -460,12 +466,14 @@ df[!, :datetime] = DateTime.(df.Column1) .+ Hour.(df.Column2);
@df df plot(:datetime, :Column3) @df df plot(:datetime, :Column3)
``` ```
The resulting plot: Und nun zum Plot:
```{julia} ```{julia}
@df df plot(:datetime, [:Column9, :Column6, :Column3], @df df plot(:datetime, [:Column9, :Column6, :Column3],
xlims = (DateTime(2023,9,1), DateTime(2024,5,30)), xlims = (DateTime(2023,9,1), DateTime(2024,5,30)),
layout=(3,1), title=["Wind" "Rain" "Temp"], layout=(3,1), title=["Wind" "Regen" "Temp"],
legend=:none, size=(800,800)) legend=:none, size=(800,800))
``` ```

View File

@@ -10,41 +10,41 @@ using InteractiveUtils
``` ```
# Plots and Data Visualization in Julia: _Plots.jl_ # Plots und Datenvisualisierung in Julia: _Plots.jl_
Julia has numerous graphics packages. Two frequently used ones are [Makie.jl](https://docs.makie.org/stable/) and 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/). Before presenting `Plots.jl` in detail, we list some others. [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://docs.juliaplots.org/latest/gallery/gr/) | designed as a unified interface to various _backends_ (graphics libraries) | |[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 (vector graphics), OpenGL, WebGL | | [Makie.jl](https://docs.makie.org/stable/) | [Basic tutorial](https://docs.makie.org/v0.21/tutorials/basic-tutorial) | [Beautiful Makie](https://beautiful.makie.org/) | "data visualization ecosystem for Julia", Backends: Cairo (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 to the [Plotly](https://plotly.com/graphing-libraries/) JavaScript graphics library | |[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/) | [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/)" | | [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/) | | [Gallery](https://cjdoris.github.io/Bokeh.jl/stable/gallery/)| Julia frontend for [Bokeh](https://bokeh.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 for [Vega-Lite](https://vega.github.io/vega-lite/)| |[VegaLite.jl](https://www.queryverse.org/VegaLite.jl/stable/) | [Tutorial](https://www.queryverse.org/VegaLite.jl/stable/gettingstarted/tutorial/)| [Examples](https://www.queryverse.org/VegaLite.jl/stable/examples/examples_barcharts/)| Julia-Frontend für [Vega-Lite](https://vega.github.io/vega-lite/)|
| [Luxor.jl](https://juliagraphics.github.io/LuxorManual/stable/) |[Tutorial](https://juliagraphics.github.io/LuxorManual/stable/tutorial/helloworld/)|[Examples](https://juliagraphics.github.io/LuxorManual/stable/example/moreexamples/)| General vector graphics/illustrations | | [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/)| *Animated* vector graphics | [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"| | [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 ## 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 - als erstes Argument einen Vektor von $x$-Werten der Länge $n$ und
- as the second argument a vector of the same length with the corresponding $y$-values. - als zweites Argument einen gleichlangen Vektor mit den dazugehörigen $y$-Werten.
- The second argument can also be an $n\times m$ matrix. Each column is treated as a separate graph (called a `series` in the documentation), plotting $m$ curves: - 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} ```{julia}
@@ -57,16 +57,16 @@ cx = @. cos(2x^(1/2))
plot(x, [sx cx]) plot(x, [sx cx])
``` ```
- Functions like `plot()`, `scatter()`, `contour()`, `heatmap()`, `histogram()`, `bar()`, etc. from _Plots.jl_ all start a new plot. - Die Funktionen des _Plots.jl_-Paketes wie `plot(), scatter(), contour(), heatmap(), histogram(), bar(),...` usw. starten alle einen neuen Plot.
- The versions `plot!()`, `scatter!()`, `contour!()`, `heatmap!()`, `histogram!()`, `bar!()`, etc. extend an existing plot: - Die Versionen `plot!(), scatter!(), contour!(), heatmap!(), histogram!(), bar!(),...` erweitern einen existierenden Plot:
```{julia} ```{julia}
plot(x, sx) # plot only sin(x) plot(x, sx) # plot only sin(x)
plot!(x, cx) # add second graph plot!(x, cx) # add second graph
plot!(x, sqrt.(x)) # add a 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} ```{julia}
plot1 = plot(x, [sx cx]) plot1 = plot(x, [sx cx])
@@ -74,7 +74,7 @@ plot1a = deepcopy(plot1) # plot objects are quite deep structures
scatter!(plot1, x, sx) # add scatter plot, i.e. unconnected data points scatter!(plot1, x, sx) # add scatter plot, i.e. unconnected data points
``` ```
The copied version `plot1a` remains unchanged by the `scatter!` call and can be used independently: Die kopierte Version `plot1a` ist durch die `scatter!`-Anweisung nicht modifiziert worden und kann unabhängig weiterverwendet werden:
```{julia} ```{julia}
plot!(plot1a, x, 2 .* sx) 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, etc.): Plot-Objekte kann man als Grafikdateien (PDF, SVG, PNG,...) abspeichern:
```{julia} ```{julia}
@@ -94,13 +94,13 @@ savefig(plot1, "plot.png")
;ls -l 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} ```{julia}
# https://mzrg.com/math/graphs.shtml # 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) plot(f, 0:0.01:3)
``` ```
The parametric form $x = x(t),\ y = y(t)$ is plotted 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} ```{julia}
# https://en.wikipedia.org/wiki/Butterfly_curve_(transcendental) # https://en.wikipedia.org/wiki/Butterfly_curve_(transcendental)
@@ -123,15 +123,16 @@ plot(xt, yt, 0:0.01:12π)
``` ```
### Plot Themes ### Plot-Themen
> "PlotThemes is a package to spice up plots made with Plots.jl."\ > "PlotThemes is a package to spice up the plots made with Plots.jl."\
See 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/)
oder:
```{julia} ```{julia}
using PlotThemes using PlotThemes
# list of themes # Liste der Themen
keys(PlotThemes._themes) keys(PlotThemes._themes)
``` ```
@@ -148,48 +149,48 @@ plot(x, [sx cx 1 ./ (1 .+ x)])
``` ```
### Plot Attributes ### Plot-Attribute
The `Plots.jl` functions have numerous options. Die Funktionen des `Plots.jl`-Paketes haben eine große Anzahl von Optionen.
Attributes are divided into 4 groups: `Plots.jl` teilt die Attribute in 4 Gruppen ein:
::::{.cell} ::::{.cell}
```{julia} ```{julia}
#| output: asis #| output: asis
plotattr(:Plot) # attributes for the overall plot plotattr(:Plot) # Attribute für den Gesamtplot
``` ```
:::: ::::
::::{.cell} ::::{.cell}
```{julia} ```{julia}
#| output: asis #| output: asis
plotattr(:Subplot) # attributes for a subplot plotattr(:Subplot) # Attribute für einen Teilplot
``` ```
:::: ::::
::::{.cell} ::::{.cell}
```{julia} ```{julia}
#| output: asis #| output: asis
plotattr(:Axis) # attributes for an axis plotattr(:Axis) # Attribute für eine Achse
``` ```
:::: ::::
::::{.cell} ::::{.cell}
```{julia} ```{julia}
#| output: asis #| 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
``` ```
:::: ::::
You can also query what individual attributes mean and which values are allowed: Man kann auch nachfragen, was die einzelnen Attribute bedeuten und welche Werte zulässig sind:
```{julia} ```{julia}
plotattr("linestyle") plotattr("linestyle")
``` ```
An example: Ein Beispiel:
```{julia} ```{julia}
theme(:default) # return to default theme theme(:default) # zurück zum Standardthema
x = 0:0.05:1 x = 0:0.05:1
y = sin.(2π*x) y = sin.(2π*x)
@@ -199,9 +200,9 @@ plot(x, y, seriestype = :sticks, linewidth = 4, seriescolor = "#00b300",
) )
``` ```
Many specifications can be abbreviated significantly; see, e.g., the `Aliases:` in the output of `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} ```{julia}
#| eval: false #| eval: false
@@ -209,61 +210,61 @@ plot(x, y, t = :sticks, w = 4, c = "#00b300", m = (:circle, 8, :green ))
``` ```
### Additional Extras ### Weitere Extras
```{julia} ```{julia}
using Plots # no harm in repeating using Plots # Wiederholung schadet nicht
using Plots.PlotMeasures # for measurements in mm, cm,... using Plots.PlotMeasures # für Maßangaben in mm, cm,...
using LaTeXStrings # for LaTeX constructs in plot labels using LaTeXStrings # für LaTeX-Konstrukte in Plot-Beschriftungen
using PlotThemes # predefined themes using PlotThemes # vorgefertigte Themen
``` ```
The `LaTeXStrings.jl` package provides the `L"..."` string constructor. These strings can contain LaTeX constructs, especially formulas. Without explicit dollar signs, they are 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} ```{julia}
xs = range(0, 2π, length = 100) xs = range(0, 2π, length = 100)
data = [sin.(xs) cos.(xs) 2sin.(xs) (x->sin(x^2)).(xs)] # 4 functions data = [sin.(xs) cos.(xs) 2sin.(xs) (x->sin(x^2)).(xs)] # 4 Funktionen
theme(:ggplot2) theme(:ggplot2)
plot10 = plot(xs, data, plot10 = plot(xs, data,
fontfamily="Computer Modern", fontfamily="Computer Modern",
# LaTeX string L"..." # LaTeX-String L"..."
title = L"Trigonometric functions $\sin(\alpha), \cos(\alpha), 2\sin(\alpha), \sin(\alpha^2)$", title = L"Winkelfunktionen $\sin(\alpha), \cos(\alpha), 2\sin(\alpha), \sin(\alpha^2)$",
xlabel = L"angle $\alpha$", xlabel = L"Winkel $\alpha$",
ylabel = "value", 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 ], color=[:black :green RGB(0.3, 0.8, 0.2) :blue ],
markers = [:rect :circle :utriangle :diamond], markers = [:rect :circle :utriangle :diamond],
markersize = [2 1 0 4], markersize = [2 1 0 4],
linewidth = [1 3 1 2], linewidth = [1 3 1 2],
linestyle = [:solid :dash :dot :solid ], linestyle = [:solid :dash :dot :solid ],
# axes # Achsen
xlim = (0, 6.6), xlim = (0, 6.6),
ylim = (-2, 2.3), ylim = (-2, 2.3),
yticks = -2:.4:2.3, # with step size yticks = -2:.4:2.3, # mit Schrittweite
# legend # Legende
legend = :bottomleft, legend = :bottomleft,
label = [ L"\sin(\alpha)" L"\cos(\alpha)" L"2\sin(\alpha)" L"\sin(\alpha^2)"], label = [ L"\sin(\alpha)" L"\cos(\alpha)" L"2\sin(\alpha)" L"\sin(\alpha^2)"],
top_margin = 5mm, # 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("Some remark","Computer Modern", 10) ) 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 mainly plotted lines. Many other types exist, such as _scatter plots, contours, heatmaps, histograms, sticks_, etc. 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} ```{julia}
theme(:default) theme(:default)
@@ -272,7 +273,7 @@ x = range(0, 2π; length = 50)
plot(x, sin.(x), seriestype=:scatter) 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} ```{julia}
x = range(0, 2π; length = 50) x = range(0, 2π; length = 50)
scatter(x, sin.(x)) scatter(x, sin.(x))
@@ -280,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)` arranges plots in an $m\times n$ grid: 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} ```{julia}
x = range(0, 2π; length = 100) x = range(0, 2π; length = 100)
@@ -299,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} ```{julia}
@@ -316,50 +317,50 @@ plot(plots..., layout=mylayout, legend=false, title=["sin" "cos" "tan" "sinc"])
### Backends ### Backends
`Plots.jl` provides a unified interface to various _backends_ (graphics engines). You can switch backends 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, we have used the default backend: [GR](https://gr-framework.org/about.html), a graphics engine developed at the Jülich Research Center, 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} ```{julia}
using Plots 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} ```{julia}
x = 1:30 x = 1:30
y = rand(30) y = rand(30)
plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Water level") plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Wasserstand")
``` ```
The same plot with the `PlotlyJS` backend: und hier derselbe Plot mit dem `PlotlyJS`-Backend.
```{julia} ```{julia}
plotlyjs() # change plots backend plotlyjs() # change plots backend
plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Water level") plot(x, y, linecolor =:green, bg_inside =:lightblue1, line =:solid, label = "Wasserstand")
``` ```
This backend enables interactivity via JavaScript. Hovering over the image allows zooming and panning; 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} ```{julia}
gr() # return to GR as backend gr() # zurück zu GR als backend
``` ```
### 3D Plots ### 3D Plots
The `surface()` and `contour()` functions plot a function $f(x,y)$. 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, - eine Menge (Vektor) $X$ von $x$-Werten,
- a set (vector) $Y$ of $y$-values and - eine Menge (Vektor) $Y$ von $y$-Werten und
- a function of two variables that is then evaluated on $X \times Y$ and plotted. - eine Funktion von zwei Variablen, die dann auf $X \times Y$ ausgewertet und geplottet wird.
```{julia} ```{julia}
f(x,y) = (1 - x/2 + x^5 + y^3) * exp(-x^2 - y^2) f(x,y) = (1 - x/2 + x^5 + y^3) * exp(-x^2 - y^2)
@@ -371,8 +372,8 @@ surface( -3:0.02:3, -3:0.02:3, f)
contour( -3:0.02:3, -3:0.02:3, f, fill=true, colormap=:summer, levels=20, contour_labels=false) contour( -3:0.02:3, -3:0.02:3, f, fill=true, colormap=:summer, levels=20, contour_labels=false)
``` ```
Curves (or point sets) in three dimensions are plotted by calling `plot()` with three vectors Kurven (oder auch einfach Punktmengen) in drei Dimensionen lassen sich plotten, indem man `plot()` mit 3 Vektoren
containing the $x$, $y$, and $z$ coordinates of the data points. aufruft, die jeweils die $x$, $y$ und $z$-Koordinaten der Datenpunkte enthalten.
```{julia} ```{julia}
plotlyjs() plotlyjs()
@@ -386,23 +387,25 @@ plot(x, y, z, zcolor=reverse(z), markersize=3, markershape= :circle,
``` ```
> The `plotlyjs` backend makes the plot interactive: it 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 `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. - `StatsPlots.jl` direktes Plotten von _Dataframes_, spezielle statistische Plots usw. oder
- `GraphRecipes.jl`: [plotting of graph structures](https://docs.juliaplots.org/latest/GraphRecipes/examples/) - `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 providing over 700 free (_"public domain"_) datasets, including: Für das letzte Beispiel laden wir ein Paket, das über 700 freie (_"public domain"_) Datensätze, darunter z.B:
- the _Titanic_ passenger list, - die Passagierliste der _Titanic_,
- fuel consumption data for American cars from the 70s, or - Verbrauchsdaten amerikanischer Autos aus den 70ern oder
- historical exchange rates: - historische Währungskurse
bereitstellt:
```{julia} ```{julia}
using RDatasets using RDatasets
@@ -416,13 +419,13 @@ using RDatasets
#RDatasets.datasets() #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} ```{julia}
cars = dataset("datasets", "mtcars") cars = dataset("datasets", "mtcars")
``` ```
We only need two columns for the plot: `cars.Model` and `cars.MPG`, the fuel consumption in _miles per gallon_ (higher is 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} ```{julia}
theme(:bright) theme(:bright)
@@ -440,10 +443,10 @@ bar(cars.Model, cars.MPG,
``` ```
### What is Missing: Animation ### Was noch fehlt: Animation
See the [documentation](https://docs.juliaplots.org/latest/animations/); here is an example Hier sei auf die [Dokumentation](https://docs.juliaplots.org/latest/animations/) verwiesen und nur ein Beispiel
(from <https://www.juliafordatascience.com/animations-with-plots-jl/>): (von <https://www.juliafordatascience.com/animations-with-plots-jl/>) angegeben:
```{julia} ```{julia}
#| error: false #| error: false
@@ -462,7 +465,7 @@ gif(anim, fps=50)
``` ```
:::: {.content-visible when-format="typst"} :::: {.content-visible when-format="pdf"}
```{julia} ```{julia}
#| echo: false #| echo: false
Random.seed!(123) Random.seed!(123)

View File

@@ -1,34 +1,8 @@
--- ---
engine: julia engine: julia
julia:
exeflags: ["--color=yes"]
--- ---
```{julia} # Arbeit mit Julia: REPL, Pakete, Introspection
#| error: false
#| echo: false
#| output: false
using InteractiveUtils
#struct M a::Int end; x = M(22); @show x
#should not print "Main.Notebook.M(22)" but only "M(22)"
function Base.show(io::IO, x::T) where T
if parentmodule(T) == @__MODULE__
# Print "TypeName(fields...)" without module prefix
print(io, nameof(T), "(")
fields = fieldnames(T)
for (i, f) in enumerate(fields)
print(io, getfield(x, f))
i < length(fields) && print(io, ", ")
end
print(io, ")")
else
invoke(Base.show, Tuple{IO, Any}, io, x)
end
end
```
# Working with Julia: The REPL, Packages, and Introspection
```{julia} ```{julia}
#| error: false #| error: false
@@ -43,49 +17,50 @@ Base.active_module() = myactive_module()
# https://github.com/JuliaLang/julia/blob/master/base/show.jl#L3073-L3077 # https://github.com/JuliaLang/julia/blob/master/base/show.jl#L3073-L3077
``` ```
## Official Documentation ## Dokumentation
The official Julia documentation [https://docs.julialang.org/](https://docs.julialang.org/) contains several 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) ## 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} :::{.narrow}
| Command | Action | | Kommando | Wirkung |
| :----------------------------| :------------------------ | | :----------------------------| :------------------------ |
| `exit()` or `Ctrl-d` | exit Julia | | `exit()` oder `Ctrl-d` | exit Julia |
| `Ctrl-c` | interrupt | | `Ctrl-c` | interrupt |
| `Ctrl-l` | clear screen | | `Ctrl-l` | clear screen |
| End command with `;` | suppress output | | Kommando mit `;` beenden | Ausgabe unterdrückt |
| `include("filename.jl")` | read and execute file with Julia code | | `include("filename.jl")` | Datei mit Julia-Code einlesen und ausführen |
The REPL supports 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` | | Package manager | `pkg>` | `]` | `backspace` |
| Help | `help?>` | `?`| `backspace`| | Help | `help?>` | `?`| `backspace `|
|Shell | `shell>` | `;` | `backspace`| |Shell | `shell>` | `;` | `backspace`|
::: :::
## 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} ```{julia}
@@ -93,7 +68,7 @@ In a Jupyter notebook, the modes are usable as single-line commands in their own
] status ] status
``` ```
(ii) a help query: (ii) eine Help-Abfrage:
```{julia} ```{julia}
@@ -101,7 +76,7 @@ In a Jupyter notebook, the modes are usable as single-line commands in their own
?sin ?sin
``` ```
(iii) a shell command: (iii) Ein Shell-Kommando:
```{julia} ```{julia}
@@ -109,71 +84,71 @@ In a Jupyter notebook, the modes are usable as single-line commands in their own
;ls ;ls
``` ```
## The Package Manager ## Der Paketmanager
An important part of the _Julia ecosystem_ is the extensive collection of packages that extend Julia's functionality. 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 `using Packagename`. - Einige Pakete sind Teil jeder Julia-Installation und müssen nur mit einer `using Paketname`-Anweisung aktiviert werden.
- They form the so-called _standard library_, which includes - Sie bilden die sogenannte _Standard Library_ und dazu gehören
- `LinearAlgebra`, `Statistics`, `SparseArrays`, `Printf`, `Pkg`, and others. - `LinearAlgebra`, `Statistics`, `SparseArrays`, `Printf`, `Pkg` und andere.
- Over 10000 packages are officially registered, see [https://julialang.org/packages/](https://julialang.org/packages/). - Über 9000 Pakete sind offiziell registriert, siehe [https://julialang.org/packages/](https://julialang.org/packages/).
- These can be downloaded and installed with just a few keystrokes using the _package manager_ `Pkg`. - Diese können mit wenigen Tastendrücken heruntergeladen und installiert werden.
- `Pkg` can be called in two ways: - Dazu dient der _package manager_ `Pkg`.
- as normal Julia statements that can also be in a `.jl` program file: - Man kann ihn auf zwei Arten verwenden:
```{.Julia} - als normale Julia-Anweisungen, die auch in einer `.jl`-Programmdatei stehen können:
```
using Pkg using Pkg
Pkg.add("PackageXY") Pkg.add("PaketXY")
``` ```
- in the special pkg-mode of the Julia REPL: - im speziellen pkg-Modus des Julia-REPLs:
```{.julia}
] add PackageXY
``` ```
- Afterward, the package can be used with `using PackageXY`. ] add PaketXY
- 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("PackageXY")` | `pkg> add PackageXY` | add to current environment | | `Pkg.add("MyPack")` | `pkg> add MyPack` | add `MyPack.jl` to current environment |
| `Pkg.rm("PackageXY")` | `pkg> remove PackageXY` | remove from current environment | | `Pkg.rm("MyPack")` | `pkg> remove MyPack` | remove `MyPack.jl` from current environment |
| `Pkg.update()` | `pkg> update` | update packages in current environment | | `Pkg.update()` | `pkg> update` | update packages in current environment |
| `Pkg.activate("mydir")` | `pkg> activate mydir` | activate directory as current environment | | `Pkg.activate("mydir")` | `pkg> activate mydir` | activate directory as current environment |
| `Pkg.status()` | `pkg> status` | list packages | | `Pkg.status()` | `pkg> status` | list packages |
| `Pkg.instantiate()` | `pkg> instantiate` | install all packages according to `Project.toml` | | `Pkg.instantiate()` | `pg> instantiate` | install all packages according to `Project.toml` |
: {tbl-colwidths="[35,40,25]"}
### Installed Packages and Environments ### Installierte Pakete und Environments
- Julia's package manager maintains: - Julia und der Paketmanager verwalten
1. a list of packages explicitly installed with the command `Pkg.add()` or `]add` with exact version specifications in a file `Project.toml` and 1. eine Liste der mit dem Kommando `Pkg.add()` bzw. `]add` explizit installierten Pakete mit genauer Versionsbezeichnung in einer Datei `Project.toml` und
2. a list of all packages installed as implicit dependencies in the file `Manifest.toml`. 2. eine Liste aller dabei auch als implizite Abhängigkeiten installierten Pakete in der Datei `Manifest.toml`.
- The directory in which these files are located is the `environment` and is displayed with `Pkg.status()` or `]status`. - Das Verzeichnis, in dem diese Dateien stehen, ist das `environment` und wird mit `Pkg.status()` bzw. `]status` angezeigt.
- Without an expplicit project environment, this looks as follows: - Im Normalfall sieht das so aus:
``` ```
(@v1.10) pkg> status (@v1.10) pkg> status
Status `~/.julia/environments/v1.12/Project.toml` Status `~/.julia/environments/v1.10/Project.toml`
[6e4b80f9] BenchmarkTools v1.6.3 [6e4b80f9] BenchmarkTools v1.5.0
[5fb14364] OhMyREPL v0.5.29 [5fb14364] OhMyREPL v0.5.24
[91a5bcdd] JuliaFormatter v2.3.0 [91a5bcdd] Plots v1.40.4
[295af30f] Revise v3.13.2 [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 ```shell
julia --project=path/to/myproject julia --project=path/to/myproject
``` ```
or activate the environment in Julia with `Pkg.activate("path/to/myproject")`. Then `Project.toml` and `Manifest.toml` files 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`)
### Installing Packages on our Jupyter Server `misun103`: ### Zum Installieren von Paketen auf unserem Jupyter-Server `misun103`:
- A central repository already contains all packages mentioned in this course. - Es gibt ein zentrales Repository, in dem alle in diesem Kurs erwähnten Pakete bereits installiert sind.
- You have no write permissions there. - Dort haben Sie keine Schreibrechte.
- However, you can install additional packages in your `HOME`. As a first command, you need to activate the current directory: - Sie können aber zusätzliche Pakete in Ihrem `HOME` installieren. Dazu ist als erster Befehl nötig, das aktuelle Verzeichnis zu aktivieren:
```{julia} ```{julia}
@@ -181,27 +156,26 @@ or activate the environment in Julia with `Pkg.activate("path/to/myproject")`. T
] activate . ] activate .
``` ```
(Note the dot!) (Man beachte den Punkt!)
Danach können Sie mit `add` im Pkg-Modus auch Pakete installieren:
After that, you can install packages with `add` in the pkg-mode:
```{julia} ```{julia}
#| eval: false #| eval: false
] add PackageXY ] add PaketXY
``` ```
Package installation can take a significant amount of 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
The Julia compiler is based on 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} :::{.narrow}
Stages of Compilation Stages of Compilation
@@ -227,7 +201,7 @@ end
```{julia} ```{julia}
p = Meta.parse( "function f(x,y); z=x^2+log(y); return 2x; end") p = Meta.parse( "function f(x,y); z=x^2+log(y); return 2x; end ")
``` ```
@@ -261,3 +235,5 @@ walk_tree(p)
```{julia} ```{julia}
@code_native f(2,4) @code_native f(2,4)
``` ```

View File

@@ -2,65 +2,73 @@
engine: julia engine: julia
--- ---
# Containers ```{julia}
#| error: false
#| echo: false
#| output: false
using InteractiveUtils
```
Julia offers a wide selection of container types with largely similar interfaces.
This chapter introduces `Tuple`, `Range`, and `Dict`; the next chapter covers `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 ```julia
for x ∈ container ... end for x ∈ container ... end
``` ```
- **indexable:** You can access elements via their index: - **indizierbar:** Man kann auf Elemente über ihren Index zugreifen:
```julia ```julia
x = container[i] 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 - `length(container)` --- Anzahl der Elemente
- `eltype(container)` --- element type - `eltype(container)` --- Typ der Elemente
- `isempty(container)` --- test if container is empty - `isempty(container)` --- Test, ob Container leer ist
- `empty!(container)` --- empties the container (if mutable) - `empty!(container)` --- leert Container (nur wenn mutierbar)
## Tuples ## Tupeln
A tuple is an immutable container of elements. You cannot add new elements or change existing values. 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} ```{julia}
t = (33, 4.5, "Hello") 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} ```{julia}
typeof(t) 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} ```{julia}
# Integer division and remainder: # Ganzzahldivision und Rest:
# Assign quotient and remainder to variables `q` and `r`: # Quotient und Rest werden den Variablen q und r zugewiesen
q, r = divrem(71, 6) q, r = divrem(71, 6)
@show q r; @show q r;
``` ```
Parentheses can be omitted in certain constructs. Wie man hier sieht, kann man in bestimmten Konstrukten die Klammern auch weglassen.
This *implicit tuple packing/unpacking* is commonly used in multiple assignments: Dieses *implict tuple packing/unpacking* verwendet man auch gerne in Mehrfachzuweisungen:
```{julia} ```{julia}
@@ -72,54 +80,56 @@ x, y, z = 12, 17, 203
y y
``` ```
Some functions require tuples as arguments or always return tuples. A single-element tuple is written as: Manche Funktionen bestehen auf Tupeln als Argument oder geben immer Tupeln zurück. Dann braucht man manchmal ein Tupel aus einem Element.
Das notiert man so:
```{julia} ```{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} ```{julia}
x= (13) # not a tuple x= (13) # kein Tupel
``` ```
## Ranges ## Ranges
We have already used *range* objects in numerical `for` loops. Wir haben *range*-Objekte schon in numerischen `for`-Schleifen verwendet.
```{julia} ```{julia}
r = 1:1000 r = 1:1000
typeof(r) typeof(r)
``` ```
There are various *range* types. `UnitRange`, for example, is a *range* with step size 1. Their constructors are typically all 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` wird vom Parser umgesetzt zu `range(a, b)`
- `a:b:c` is parsed as `range(a, c, step=b)` - `a:b:c` wird umgesetzt zu `range(a, c, step=b)`
*Ranges* sind offensichtlich iterierbar, nicht mutierbar aber indizierbar.
*Ranges* are iterable, immutable, and indexable.
```{julia} ```{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` does **not** mean 'increment the loop variable `i` by one each iteration'; **rather**, it means 'successively assign the values 1, 2, 3, ..., 1000 to the loop variable from the container'. - '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'.
Creating this container explicitly would be very inefficient. Allerdings wäre es sehr ineffektiv, diesen Container tatsächlich explizit anzulegen.
- _Ranges_ are "lazy" vectors never stored as concrete lists. This makes them ideal as `for` loop iterators: memory-efficient and fast. - _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.
- They are "recipes" or generators that respond to the query "Give me your next element!". - Sie sind 'Rezepte' oder Generatoren, die auf die Abfrage 'Gib mir dein nächstes Element!' antworten.
- In fact, the supertype `AbstractRange` is a subtype of `AbstractVector`. - Tatsächlich ist der Muttertyp `AbstractRange` ein Subtyp von `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} ```{julia}
@allocated r = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] @allocated r = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
@@ -132,196 +142,198 @@ The macro `@allocated` outputs how many bytes of memory were allocated during th
Zum Umwandeln in einen 'richtigen' Vektor dient die Funktion `collect()`.
The `collect()` function converts a range to a concrete vector.
```{julia} ```{julia}
collect(20:-3:1) 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} ```{julia}
LinRange(2, 50, 300) LinRange(2, 50, 300)
``` ```
`LinRange(start, stop, n)` generates `n` equidistant values from start to stop. Use `collect()` to 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
- _Dictionaries_ (also known as associative arrays or lookup tables) are special containers. - _Dictionaries_ (deutsch: "assoziative Liste" oder "Zuordnungstabelle" oder ...) sind spezielle Container.
- Whereas vector entries are addressed by integer indices: `v[i]`; dictionary entries are addressed by more general _keys_. - Einträge in einem Vektor `v` sind durch einen Index 1,2,3.... addressierbar: `v[i]`
- A dictionary is a collection of _key-value_ pairs with parameterized type `Dict{S,T}`, where `S` is the key type and `T` is the value type. - 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
Create a dictionary explicitly: Man kann sie explizit anlegen:
```{julia} ```{julia}
# Population in 2020 in millions, source: wikipedia # Einwohner 2020 in Millionen, Quelle: wikipedia
Ppl = Dict("Berlin" => 3.66, "Hamburg" => 1.85, EW = Dict("Berlin" => 3.66, "Hamburg" => 1.85,
"München" => 1.49, "Köln" => 1.08) "München" => 1.49, "Köln" => 1.08)
``` ```
```{julia} ```{julia}
typeof(Ppl) typeof(EW)
``` ```
and indexed with the _keys_: und mit den _keys_ indizieren:
```{julia} ```{julia}
Ppl["Berlin"] EW["Berlin"]
``` ```
Querying a non-existent _key_ throws an error. Das Abfragen eines nicht existierenden _keys_ ist natürlich ein Fehler.
```{julia} ```{julia}
Ppl["Leipzig"] EW["Leipzig"]
``` ```
Check beforehand with `haskey()`... Man kann ja auch vorher mal anfragen...
```{julia} ```{julia}
haskey(Ppl, "Leipzig") haskey(EW, "Leipzig")
``` ```
Or use `get(dict, key, default)`, which returns the default value instead of throwing an error. ... oder die Funktion `get(dict, key, default)` benutzen, die bei nicht existierendem Key keinen Fehler wirft sondern das 3. Argument zurückgibt.
```{julia} ```{julia}
@show get(Ppl, "Leipzig", -1) get(Ppl, "Berlin", -1); @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} ```{julia}
keys(Ppl) keys(EW)
``` ```
```{julia} ```{julia}
values(Ppl) values(EW)
``` ```
Iterate over the `keys`... Man kann über die `keys` iterieren...
```{julia} ```{julia}
for i in keys(Ppl) for i in keys(EW)
n = Ppl[i] n = EW[i]
println("The city $i has $n million inhabitants.") println("Die Stadt $i hat $n Millionen Einwohner.")
end end
``` ```
Or iterate directly over `key-value` pairs. odere gleich über `key-value`-Paare.
```{julia} ```{julia}
for (city, pop) ∈ Ppl for (stadt, ew) ∈ EW
println("$city : $pop Million.") println("$stadt : $ew Mill.")
end end
``` ```
### Extending and Modifying ### Erweitern und Modifizieren
Add `key-value` pairs to a `Dict`... Man kann in ein `Dict` zusätzliche `key-value`-Paare eintragen...
```{julia} ```{julia}
Ppl["Leipzig"] = 0.52 EW["Leipzig"] = 0.52
Ppl["Dresden"] = 0.52 EW["Dresden"] = 0.52
Ppl EW
``` ```
Change a `value`: und einen `value` ändern.
```{julia} ```{julia}
# Update: Leipzig data was from 2010, not 2020 # Oh, das war bei Leipzig die Zahl von 2010, nicht 2020
Ppl["Leipzig"] = 0.597 EW["Leipzig"] = 0.597
Ppl EW
``` ```
Delete a pair by its `key`: Ein Paar kann über seinen `key` auch gelöscht werden.
```{julia} ```{julia}
delete!(Ppl, "Dresden") delete!(EW, "Dresden")
``` ```
Many functions work with `Dicts` like other containers. Zahlreiche Funktionen können mit `Dicts` wie mit anderen Containern arbeiten.
```{julia} ```{julia}
maximum(values(Ppl)) maximum(values(EW))
``` ```
### Creating an Empty Dictionary ### Anlegen eines leeren Dictionaries
Without explicit types: Ohne Typspezifikation ...
```{julia} ```{julia}
d1 = Dict() d1 = Dict()
``` ```
With explicit types: und mit Typspezifikation:
```{julia} ```{julia}
d2 = Dict{String, Int}() d2 = Dict{String, Int}()
``` ```
### Conversion to Vectors: `collect()` ### Umwandlung in Vektoren: `collect()`
- `keys(dict)` and `values(dict)` return special container types. - `keys(dict)` und `values(dict)` sind spezielle Datentypen.
- `collect()` converts them to `Vector`s. - Die Funktion `collect()` macht daraus eine Liste vom Typ `Vector`.
- `collect(dict)` returns a `Vector{Pair{S,T}}`. - `collect(dict)` liefert eine Liste vom Typ `Vector{Pair{S,T}}`
```{julia} ```{julia}
collect(Ppl) collect(EW)
``` ```
```{julia} ```{julia}
collect(keys(Ppl)), collect(values(Ppl)) 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} ```{julia}
for k in sort(collect(keys(Ppl)), rev = true) for k in sort(collect(keys(EW)), rev = true)
n = Ppl[k] n = EW[k]
println("$k has $n million inhabitants ") println("$k hat $n Millionen Einw. ")
end end
``` ```
Let's sort `collect(dict)`, a vector of pairs. Use `by` to specify the sort key: the second element of each 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} ```{julia}
for (k,v) in sort(collect(Ppl), by = pair -> last(pair), rev=false) 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 end
``` ```
### An Application of Dictionaries: Counting Frequencies ### Eine Anwendung von Dictionaries: Zählen von Häufigkeiten
Let's do "experimental stochastics" with 2 dice: Wir machen 'experimentelle Stochastik' mit 2 Würfeln:
Let `l` be a vector containing 100,000 sums of two dice rolls (numbers from 2 to 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 does each number from 2 to 12 occur? Wie häufig sind die Zahlen 2 bis 12?
Roll the dice: Wir (lassen) würfeln:
```{julia} ```{julia}
l = rand(1:6, 100_000) .+ rand(1:6, 100_000) l = rand(1:6, 100_000) .+ rand(1:6, 100_000)
``` ```
Count event frequencies using a dictionary. Use 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} ```{julia}
# In this case, a simple vector would also work. # In diesem Fall könnte man das auch mit einem einfachen Vektor
# A better use case for dictionaries is word frequency in texts, # lösen. Eine bessere Illustration wäre z.B. Worthäufigkeit in
# where keys are strings instead of integers. # einem Text. Dann ist i keine ganze Zahl sondern ein Wort=String
d = Dict{Int,Int}() # dictionary for counting d = Dict{Int,Int}() # das Dict zum 'reinzählen'
for i in l # for each i, increment d[i] for i in l # für jedes i wird d[i] erhöht.
d[i] = get(d, i, 0) + 1 d[i] = get(d, i, 0) + 1
end end
d d
``` ```
Result: Das Ergebnis:
```{julia} ```{julia}
using Plots using Plots
@@ -329,6 +341,7 @@ using Plots
plot(collect(keys(d)), collect(values(d)), seriestype=:scatter) plot(collect(keys(d)), collect(values(d)), seriestype=:scatter)
``` ```
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) [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

View File

@@ -2,62 +2,52 @@
engine: julia engine: julia
--- ---
# Functions and Operators # Funktionen und Operatoren
```{julia} ```{julia}
#| error: false #| error: false
#| echo: false #| echo: false
#| output: false #| output: false
using InteractiveUtils using InteractiveUtils
import QuartoNotebookWorker
#struct M a::Int end; x = M(22); @show x Base.stdout = QuartoNotebookWorker.with_context(stdout)
#should not print "Main.Notebook.M(22)" but only "M(22)" myactive_module() = Main.Notebook
function Base.show(io::IO, x::T) where T Base.active_module() = myactive_module()
if parentmodule(T) == @__MODULE__ # https://github.com/JuliaLang/julia/blob/master/base/show.jl#L516-L520
# Print "TypeName(fields...)" without module prefix # https://github.com/JuliaLang/julia/blob/master/base/show.jl#L3073-L3077
print(io, nameof(T), "(")
fields = fieldnames(T)
for (i, f) in enumerate(fields)
print(io, getfield(x, f))
i < length(fields) && print(io, ", ")
end
print(io, ")")
else
invoke(Base.show, Tuple{IO, Any}, io, x)
end
end
``` ```
Functions process their arguments to produce and return a result when called. Funktionen verarbeiten ihre Argumente zu einem Ergebnis, das sie beim Aufruf zurückliefern.
## Forms of function definitions ## Formen
Funktionen können in verschiedenen Formen definiert werden:
I. Block form: `function ... end` I. Als `function ... end`-Block
```{julia} ```{julia}
function hyp(x,y) function hyp(x,y)
sqrt(x^2+y^2) sqrt(x^2+y^2)
end end
``` ```
II. Single-line form II. Als "Einzeiler"
```{julia} ```{julia}
hyp(x, y) = sqrt(x^2 + y^2) hyp(x, y) = sqrt(x^2 + y^2)
``` ```
III. Anonymous functions III. Als anonyme Funktionen
```{julia} ```{julia}
(x, y) -> sqrt(x^2 + y^2) (x, y) -> sqrt(x^2 + y^2)
``` ```
### Block Form and `return` Statement ### Block-Form und `return`
- With `return`, function execution terminates and control returns to the calling context. - Mit `return` wird die Abarbeitung der Funktion beendet und zum aufrufenden Kontext zurückgekehrt.
- Without `return`, the value of the last expression is returned as the function value. - Ohne `return` wird der Wert des letzten Ausdrucks als Funktionswert zurückgegeben.
The two definitions Die beiden Definitionen
```julia ```julia
function xsinrecipx(x) function xsinrecipx(x)
@@ -67,7 +57,7 @@ function xsinrecipx(x)
return x * sin(1/x) return x * sin(1/x)
end end
``` ```
and the equivalent version without explicit `return` in the last line: und ohne das zweite explizite `return` in der letzten Zeile:
```julia ```julia
function xsinrecipx(x) function xsinrecipx(x)
@@ -78,11 +68,11 @@ function xsinrecipx(x)
end end
``` ```
are therefore equivalent. sind also äquivalent.
- A function that returns `nothing` (_void functions_ in C) returns a `nothing` value of type `Nothing`. (Just as a `Bool` object has two values, `true` and `false`, a `Nothing` object has only one: `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.)
- An empty `return` statement is equivalent to `return nothing`. - Eine leere `return`-Anweisung ist äquivalent zu `return nothing`.
```{julia} ```{julia}
@@ -105,27 +95,27 @@ a
``` ```
### Single-liner Form ### Einzeiler-Form
The single-liner form looks like a simple assignment: Die Einzeilerform ist eine ganz normale Zuweisung, bei der links eine Funktion steht.
```julia ```julia
hyp(x, y) = sqrt(x^2 + y^2) hyp(x, y) = sqrt(x^2 + y^2)
``` ```
Julia provides 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 - `begin ... end`-Block
- Parenthesized statements separated by semicolons. - 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 ```julia
hyp(x, y) = (z = x^2; z += y^2; sqrt(z)) hyp(x, y) = (z = x^2; z += y^2; sqrt(z))
``` ```
and und
```julia ```julia
hyp(x, y) = begin hyp(x, y) = begin
z = x^2 z = x^2
@@ -134,15 +124,15 @@ hyp(x, y) = begin
end 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 ```julia
hyp = (x,y) -> sqrt(x^2 + y^2) 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 include `map(f, collection)`, which applies a function to every element of a collection. Julia also supports `map(f, collection1, collection2)` with multiple collections: 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} ```{julia}
map( (x,y) -> sqrt(x^2 + y^2), [3, 5, 8], [4, 12, 15]) map( (x,y) -> sqrt(x^2 + y^2), [3, 5, 8], [4, 12, 15])
@@ -152,24 +142,24 @@ map( (x,y) -> sqrt(x^2 + y^2), [3, 5, 8], [4, 12, 15])
map( x->3x^3, 1:8 ) map( x->3x^3, 1:8 )
``` ```
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} ```{julia}
filter(x -> ( x%3 == 0 && x%5 == 0), 1:100 ) filter(x -> ( x%3 == 0 && x%5 == 0), 1:100 )
``` ```
## Argument Passing ## Argumentübergabe
- When calling a function, Julia does not copy objects passed as arguments. Function arguments refer to the original objects. Julia calls this concept _pass_by_sharing_. - 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_.
- Consequently, functions can modify their arguments if they are mutable (e.g., `Vector` or `Array`). - Funktionen können also ihre Argumente wirksam modifizieren, falls es sich um _mutable_ Objekte, wie z.B. `Vector`, `Array` handelt.
- By convention, functions that modify their arguments end with an exclamation mark. The modified argument is typically the first argument and is also returned. - 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} ```{julia}
V = [1, 2, 3] V = [1, 2, 3]
W = fill!(V, 17) W = fill!(V, 17)
# '===' tests for identity # '===' ist Test auf Identität
@show V W V===W; # V and W refer to the same object @show V W V===W; # V und W benennen dasselbe Objekt
``` ```
```{julia} ```{julia}
@@ -185,16 +175,16 @@ U = fill_first!(V, 42)
## Function Argument Variants ## Varianten von Funktionsargumenten
- There are positional arguments (1st argument, 2nd argument, ...) and _keyword_ arguments, which must be addressed by name when calling. - Es gibt Positionsargumente (1. Argument, 2. Argument, ....) und _keyword_-Argumente, die beim Aufruf durch ihren Namen angesprochen werden müssen.
- Both positional and _keyword_ arguments can have _default_ values. These arguments can be omitted when calling. - Sowohl Positions- als auch _keyword_-Argumente können _default_-Werte haben. Beim Aufruf können diese Argumente weggelassen werden.
- The order of declaration must be: - Die Reihenfolge der Deklaration muss sein:
1. Positional arguments without default values, 1. Positionsargumente ohne Defaultwert,
2. Positional arguments with default values, 2. Positionsargumente mit Defaultwert,
3. --- semicolon ---, 3. --- Semikolon ---,
4. comma-separated list of keyword arguments (with or without default values) 4. kommagetrennte Liste der Keywordargumente (mit oder ohne Defaultwert)
- When calling, keyword arguments can appear in any order at any position. They can be separated from positional arguments with a semicolon, but this is optional. - 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} ```{julia}
fa(x, y=42; a) = println("x=$x, y=$y, a=$a") fa(x, y=42; a) = println("x=$x, y=$y, a=$a")
@@ -204,7 +194,7 @@ fa(6, 7; a=4)
fa(a=-2, 6) fa(a=-2, 6)
``` ```
A function with only _keyword_ arguments is declared as follows: Eine Funktion nur mit _keyword_-Argumenten wird so deklariert:
```{julia} ```{julia}
fkw(; x=10, y) = println("x=$x, y=$y") fkw(; x=10, y) = println("x=$x, y=$y")
@@ -214,9 +204,9 @@ fkw(y=2)
## Functions are just Objects ## Funktionen sind ganz normale Objekte
- Functions can be assigned to variables - Sie können zugewiesen werden
```{julia} ```{julia}
@@ -225,11 +215,11 @@ f2(2)
``` ```
- Functions can be passed as arguments to other functions. - Sie können als Argumente an Funktionen übergeben werden.
```{julia} ```{julia}
# naive Riemann integration example # sehr naive numerische Integration
function Riemann_integrate(f, a, b; NInter=1000) function Riemann_integrate(f, a, b; NInter=1000)
delta = (b-a)/NInter delta = (b-a)/NInter
@@ -245,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.
@@ -273,16 +263,16 @@ h(1)
h(2), h(10) h(2), h(10)
``` ```
The above function `generate_add_func()` can also be defined more briefly. The inner function name `addx` is local and inaccessible outside. An anonymous function can be used instead. 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} ```{julia}
generate_add_func(x) = y -> x + y 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))$$ $$(f\circ g)(x) = f(g(x))$$
@@ -299,11 +289,11 @@ f(.2)
```{julia} ```{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} ```{julia}
@@ -316,37 +306,37 @@ f(.2)
``` ```
- These operators can also be broadcast (see @sec-broadcast). A vector of functions is applied element-wise to 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} ```{julia}
["a", "list", "of", "strings"] .|> [length, uppercase, reverse, titlecase] ["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.
The function can be called without the first argument, with the function body defined in a 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 ```julia
higherfunc(a, b) do x, y higherfunc(a, b) do x, y
body of f(x,y) Körper von f(x,y)
end end
``` ```
Using `Riemann_integrate()` as an example, this looks like this: Am Beispiel von `Riemann_integrate()` sieht das so aus:
```{julia} ```{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 Riemann_integrate(0, 2) do x x^2 end
``` ```
The `do` notation is especially useful for complex function bodies, such as this integrand defined in multiple steps: Der Sinn besteht natürlich in der Anwendung mit komplexeren Funktionen, wie diesem aus zwei Teilstücken zusammengesetzten Integranden:
```{julia} ```{julia}
r = Riemann_integrate(0, π) do x r = Riemann_integrate(0, π) do x
z1 = sin(x) z1 = sin(x)
@@ -359,12 +349,12 @@ r = Riemann_integrate(0, π) do x
end end
``` ```
## Function-like Objects ## Funktionsartige Objekte
By defining a method for a type, objects become *callable* like functions. Durch Definition einer geeigneten Methode für einen Typ kann man beliebige Objekte *callable* machen, d.h., sie anschließend wie Funktionen aufrufen.
```{julia} ```{julia}
# struct stores coefficients of a second-degree polynomial # struct speichert die Koeffiziente eines Polynoms 2. Grades
struct Poly2Grad struct Poly2Grad
a0::Float64 a0::Float64
a1::Float64 a1::Float64
@@ -375,13 +365,13 @@ p1 = Poly2Grad(2,5,1)
p2 = Poly2Grad(3,1,-0.4) p2 = Poly2Grad(3,1,-0.4)
``` ```
The following method makes this structure callable: Die folgende Methode macht diese Struktur `callable`.
```{julia} ```{julia}
function (p::Poly2Grad)(x) function (p::Poly2Grad)(x)
p.a2 * x^2 + p.a1 * x + p.a0 p.a2 * x^2 + p.a1 * x + p.a0
end end
``` ```
Objects can now be used like functions: Jetzt kann man die Objekte, wenn gewünscht, auch wie Funktionen verwenden.
```{julia} ```{julia}
@show p2(5) p1(-0.7) p1; @show p2(5) p1(-0.7) p1;
@@ -389,9 +379,9 @@ Objects can now be used like functions:
## Operators and Special Forms ## Operatoren und spezielle Formen
- Infix operators such as `+`, `*`, `>`, `∈` are functions. - Infix-Operatoren wie `+,*,>,∈,...` sind Funktionen.
@@ -409,7 +399,7 @@ f = +
f(3, 7) f(3, 7)
``` ```
- 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} :::{.narrow}
@@ -420,53 +410,53 @@ f(3, 7)
| a.x | getproperty(a, :x) | | a.x | getproperty(a, :x) |
| a.x = z | setproperty!(a, :x, z) | | a.x = z | setproperty!(a, :x, z) |
| [x; y;...] | vcat(x, y, ...) | | [x; y;...] | vcat(x, y, ...) |
: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} :::{.callout-note}
For these functions, too, van be extended/overwritten by new 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 ```julia
x = x ⊙ y x = x ⊙ y
``` ```
can also be written as kann auch geschrieben werden als
```julia ```julia
x ⊙= y x ⊙= y
``` ```
Both forms are semantically equivalent: a new object created on the right is assigned to `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-efficient *in-place updates* of arrays use explicit indexing: Ein Speicherplatz- und Zeit-sparendes __in-place-update__ eines Arrays/Vektors/Matrix ist möglich entweder durch explizite Indizierung
```julia ```julia
for i in eachindex(x) for i in eachindex(x)
x[i] += y[i] x[i] += y[i]
end end
``` ```
or semantically equivalent broadcast form (see @sec-broadcast): oder durch die dazu semantisch äquivalente _broadcast_-Form (s. @sec-broadcast):
```julia ```julia
x .= x .+ y x .= x .+ y
``` ```
## Operator Precedence and Associativity {#sec-vorrang} ## Vorrang und Assoziativität von Operatoren {#sec-vorrang}
Expressions like Zu berechnende Ausdrücke
```{julia} ```{julia}
-2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2 -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} ```{julia}
using TreeView using TreeView
@@ -474,75 +464,75 @@ walk_tree(Meta.parse("-2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2"))
``` ```
- Expression evaluation is governed by - Die Auswertung solcher Ausdrücke wird durch
- precedence and - Vorrang _(precedence)_ und
- associativity. - Assoziativität geregelt.
- Precedence determines which operators bind more tightly, such as multiplication before addition. - 'Vorrang' definiert, welche Operatoren stärker binden im Sinne von "Punktrechnung geht vor Strichrechnung".
- Associativity determines the evaluation order for operators of equal precedence. - 'Assoziativität' bestimmt die Auswertungsreihenfolge bei gleichen oder gleichrangigen Operatoren.
- [Complete documentation](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity) - [Vollständige Dokumentation](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity)
### Associativity ### Assoziativität
Addition/subtraction and multiplication/division have equal precedence and are left-associative (evaluated 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} ```{julia}
200/5/2 # evaluated left to right as (200/5)/2 200/5/2 # wird von links ausgewertet als (200/5)/2
``` ```
```{julia} ```{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} ```{julia}
x = 1 x = 1
y = 10 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 x += y += z = a = 20
@show x y z a; @show x y z a;
``` ```
Julia provides functions to query associativity. These functions are not exported from `Base`, so the module name must be specified. 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} ```{julia}
for i in (:/, :+=, :(=), :^) for i in (:/, :+=, :(=), :^)
a = Base.operator_associativity(i) a = Base.operator_associativity(i)
println("Operation $i is $(a)-associative") println("Operation $i is $(a)-assoziative")
end end
``` ```
Thus, the power operator is right-associative: Also ist der Potenzoperator rechtsassoziativ.
```{julia} ```{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} ```{julia}
for i in (:+, :-, :*, :/, :^, :(=)) for i in (:+, :-, :*, :/, :^, :(=))
p = Base.operator_precedence(i) p = Base.operator_precedence(i)
println("Precedence of $i = $p") println("Vorrang von $i = $p")
end end
``` ```
- Precedence 11 < 12 explains why multiplication/division bind tighter than addition/subtraction. - 11 ist kleiner als 12, also geht 'Punktrechnung vor Strichrechnung'
- The power operator `^` has higher precedence. - Der Potenz-Operator `^` hat eine höhere _precedence_.
- Assignments have the lowest precedence. - Zuweisungen haben die kleinste _precedence_
```{julia} ```{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 = 3 < 4
x x
@@ -550,11 +540,11 @@ x
```{julia} ```{julia}
(y = 3) < 4 # parentheses override any precedence (y = 3) < 4 # Klammern schlagen natürlich jeden Vorrang
y y
``` ```
Returning to the example above: Nochmal zum Beispiel vom Anfang von @sec-vorrang:
```{julia} ```{julia}
-2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2 -2^3+500/2/10==8 && 13 > 7 + 1 || 9 < 2
@@ -567,43 +557,43 @@ for i ∈ (:^, :+, :/, :(==), :&&, :>, :|| )
println(Base.operator_precedence(i)) println(Base.operator_precedence(i))
end end
``` ```
These rules evaluate the expression as: Nach diesen Vorrangregeln wird der Beispielausdruck also wie folgt ausgewertet:
```{julia} ```{julia}
((-(2^3)+((500/2)/10)==8) && (13 > (7 + 1))) || (9 < 2) ((-(2^3)+((500/2)/10)==8) && (13 > (7 + 1))) || (9 < 2)
``` ```
(as shown in the parse tree 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 ```julia
a = x <= y + z && x > z/2 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 - Eine Besonderheit sind noch
- unary operators, in particular `+` and `-` as signs - unäre Operatoren, also insbesondere `+` und `-` als Vorzeichen
- _juxtaposition_, i.e., numbers directly before variables or parentheses without `*` symbol - _juxtaposition_, also Zahlen direkt vor Variablen oder Klammern ohne `*`-Symbol
Both have precedence even before multiplication and division. Beide haben Vorrang noch vor Multiplikation und Division.
:::{.callout-important} :::{.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} ```{julia}
1/2*π, 1/2π 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. > Unary operators, including juxtaposition, bind tighter than ^ on the right but looser on the left.
Examples: Beispiele:
```{julia} ```{julia}
-2^2 # -(2^2) -2^2 # -(2^2)
``` ```
@@ -625,26 +615,28 @@ x = 5
``` ```
- Function application `f(...)` has precedence over all operators - Funktionsanwendung `f(...)` hat Vorrang vor allen Operatoren
```{julia} ```{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 ```julia
∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛
``` ```
have precedence 12 like multiplication/division (and are left-associative like these) den Vorrang 12 wie Multiplikation/Division (und sind wie diese linksassoziativ)
and for example und z.B.
```julia ```julia
⊕ ⊖ ⊞ ⊟ |++| ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⊕ ⊖ ⊞ ⊟ |++| ⊔ ± ∓ ∔ ∸ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗
``` ```
have precedence 11 like addition/subtraction. haben den Vorrang 11 wie Addition/Subtraktion.

View File

@@ -1,7 +1,5 @@
--- ---
engine: julia engine: julia
julia:
exeflags: ["--color=yes"]
--- ---
```{julia} ```{julia}
@@ -11,48 +9,48 @@ julia:
using InteractiveUtils using InteractiveUtils
``` ```
# A Small Example Program # Erste Miniprogramme
## What Skills Are Needed for Programming?
- **Thinking in algorithms:** ## Was sollte man zum Programmieren können?
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?
- **Implementing the algorithm in 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, finding, and fixing errors in the algorithm must now be done.
- **Intuition for the efficiency and complexity of algorithms**
- **Specifics of computer arithmetic**, especially floating point numbers
These cannot all be mastered at once. Be patient with yourself and 'play' with the language.
The following examples should serve as inspiration. - **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
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 ## Project Euler
A nice source for programming tasks with mathematical character and very different levels of difficulty is [Project Euler](https://projecteuler.net/). Eine hübsche Quelle für Programmieraufgaben mit mathematischem Charakter und sehr unterschiedlichen Schwierigkeitsgraden ist [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. 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://github.com/luckytoilet/projecteuler-solutions/blob/master/Solutions.md
https://math.stackexchange.com/questions/3370978/iterating-sum-of-squares-of-decimal-digits-of-an-integer-how-big-can-it-grow https://math.stackexchange.com/questions/3370978/iterating-sum-of-squares-of-decimal-digits-of-an-integer-how-big-can-it-grow
Aufg. 92 aufg. 92
::: :::
::: {.callout-note icon=false .titlenormal} ::: {.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. 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.
@@ -60,36 +58,36 @@ Find the sum of all the multiples of 3 or 5 below 1000.
::: :::
1. Algorithm: 1. Algorithmus:
- Test all natural numbers <1000 for divisibility by 3 or 5 and - Teste alle natürlichen Zahlen <1000 auf Teilbarkeit durch 3 oder durch 5 und
- sum the divisible numbers. - 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`. Wie liefert Julia den Rest der Ganzzahldivision? Solche Funktionen heißen typischerweise `rem()` (für *remainder*) oder `mod()`. [Nachlesen in der Doku](https://docs.julialang.org/en/v1/base/math/#Base.rem) oder ausprobieren von `?rem` und `?mod` in der Julia-REPL zeigt, dass es beides gibt. Der Unterschied liegt in der Behandlung negativer ganzer Zahlen. Für natürliche Zahlen `n,m` liefern `mod(n,m)` und `rem(n,m)` dasselbe und letzteres hat auch noch die Infix-Form `n % m`.
How does one test a sequence of values and sum them up? There is a standard pattern: `for` loop and accumulator variable: 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} :::{.callout-caution icon="false" collapse="true" .titlenormal}
## One possible solution: ## Eine Lösungsvariante:
```{julia} ```{julia}
s = 0 # initialize accumulator variable s = 0 # Akkumulatorvariable initialisieren
for i in 1:999 # loop for i in 1:999 # Schleife
if i % 3 == 0 || i % 5 == 0 # test if i % 3 == 0 || i % 5 == 0 # Test
s += i # add to accumulator s += i # Zu Akkumulator addieren
end # end test end # Ende Test
end # end loop end # Ende Schleife
println("The answer is: $s") # output result 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} :::{.callout-caution icon="false" collapse="true" .titlenormal}
## Another solution: ## Noch eine Lösungsvariante:
```{julia} ```{julia}
sum([i for i in 1:999 if i%3==0||i%5==0]) sum([i for i in 1:999 if i%3==0||i%5==0])
@@ -100,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} ::: {.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. 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, For example,
@@ -117,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? 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). Programme kann man [*top-down* und *bottom-up*](https://de.wikipedia.org/wiki/Top-Down-_und_Bottom-Up-Design) entwickeln.
*Top-down* would probably mean here: "We start with a loop `for i = 1:9999999`." The other approach works through individually testable components and is often more effective. (And with a certain project size, one approaches the goal from both 'top' and 'bottom' simultaneously.) *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 ##### Funktion Nr. 1
We want to investigate how numbers behave under repeated calculation of the 'square digit sum' (sum of squares of digits). Therefore, write and test a function that calculates this 'square digit sum'. 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} :::{.callout-caution icon="false" collapse="true" .titlenormal}
## `q2sum(n)` calculates the sum of the squares of the digits of n in base 10: ## `q2sum(n)` berechnet die Summe der Quadrate der Ziffern von n im Dezimalsystem:
```{julia} ```{julia}
#| output: false #| output: false
function q2sum(n) function q2sum(n)
s = 0 # accumulator for the sum s = 0 # Akkumulator für die Summe
while n > 9 # as long as n is still multi-digit... while n > 9 # solange noch mehrstellig...
q, r = divrem(n, 10) # calculate integer quotient and remainder of division by 10 q, r = divrem(n, 10) # berechne Ganzzahlquotient und Rest bei Division durch 10
s += r^2 # add squared digit to accumulator s += r^2 # addiere quadrierte Ziffer zum Akkumulator
n = q # continue with the number divided by 10 n = q # mache weiter mit der durch 10 geteilten Zahl
end end
s += n^2 # add the square of the last digit s += n^2 # addiere das Quadrat der letzten Ziffer
return s return s
end end
``` ```
::: :::
Let's test it now: ... und das testen wir jetzt natürlich:
```{julia} ```{julia}
for i in [1, 7, 33, 111, 321, 1000, 73201] for i in [1, 7, 33, 111, 321, 1000, 73201]
j = q2sum(i) j = q2sum(i)
println("Square digit sum of $i = $j") println("Quadratquersumme von $i = $j")
end end
``` ```
In the spirit of the task, we apply the function repeatedly: Im Sinne der Aufgabe wenden wir die Funktion wiederholt an:
```{julia} ```{julia}
n = 129956799 n = 129956799
@@ -160,48 +158,48 @@ for i in 1:14
println(n) println(n)
end end
``` ```
... and we have now 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} :::{.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} ```{julia}
#| output: false #| output: false
function q2test(n) function q2test(n)
while n !=1 && n != 89 # as long as we have not reached 1 or 89... while n !=1 && n != 89 # solange wir nicht bei 1 oder 89 angekommen sind....
n = q2sum(n) # repeat n = q2sum(n) # wiederholen
end end
if n == 1 return false end # not an 89 cycle if n==1 return false end # keine 89er-Zahl
return true # 89 cycle found return true # 89er-Zahl gefunden
end end
``` ```
::: :::
... and with this, we can solve the task: ... und damit können wir die Aufgabe lösen:
```{julia} ```{julia}
c = 0 # once again an accumulator c = 0 # mal wieder ein Akkumulator
for i = 1 : 10_000_000 - 1 # this is how you can separate thousands for better readability for i = 1 : 10_000_000 - 1 # so kann man in Julia Tausenderblöcke zur besseren Lesbarkeit abtrennen
if q2test(i) # q2test() returns a boolean, no further test needed if q2test(i) # q2test() gibt einen Boolean zurück, kein weiterer Test nötig
c += 1 # 'if x == true' is redundant, 'if x' is perfectly sufficient c += 1 # 'if x == true' ist redundant, 'if x' reicht völlig
end end
end end
println("$c numbers below ten million arrive at 89.") 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} :::{.callout-caution icon="false" collapse="true" .titlenormal}
## Our solution to Project Euler No 92: ## unsere Lösung von Project Euler No 92:
```{julia} ```{julia}
function q2sum(n) function q2sum(n)

View File

@@ -9,71 +9,72 @@ engine: julia
using InteractiveUtils using InteractiveUtils
``` ```
```{julia}
#| error: false
#| echo: false
#| output: false
flush(stdout)
```
# A Case Study on Floating-Point Arithmetic Stability # Ein Beispiel zur Stabilität von Gleitkommaarithmetik
This chapter is inspired by the example in *Christoph Überhuber*, "Computer-Numerik" Vol. 1, Springer 1995, Chap. 2.3.
## Calculation of $\pi$ According to Archimedes
A lower bound for $2\pi$ -- the circumference of the unit circle -- is obtained by summing ## Berechnung von $\pi$ nach Archimedes
the side lengths of a regular $n$-gon inscribed in the unit circle.
The figure on the left illustrates the iterative doubling of the number of vertices starting from a square with side length $$s_4=\sqrt{2}$$. 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} :::{.narrow}
| Fig. 1 | Fig. 2 | | Abb. 1 | Abb.2 |
| :-: | :-: | | :-: | :-: |
| ![](../images/pi1.png) | ![](../images/pi2.png) | | ![](../images/pi1.png) | ![](../images/pi2.png) |
: {tbl-colwidths="[57,43]"} : {tbl-colwidths="[57,43]"}
::: :::
The second figure shows the geometry of the vertex doubling.
With Die zweite Abbildung zeigt die Geometrie der Eckenverdoppelung.
$|\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 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{and } \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 (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_{2n} = \sqrt{2-\sqrt{4-s_n^2}} \qquad\text{mit Startwert}\qquad
s_4=\sqrt{2} 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| \epsilon_n = \left| \frac{n\, s_n-2 \pi}{2\pi} \right|
$$ $$
## Two Iteration Formulas
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)}
$$ $$
(Bitte nachrechnen!)
However, Iteration A is ill-conditioned and numerically unstable, as the following code demonstrates. The output shows the approximation for $\pi$ for both formulae iteration. Allerdings ist Iteration A schlecht konditioniert und numerisch instabil, wie der folgende Code zeigt. Ausgegeben wird die jeweils berechnete Näherung für π.
```{julia} ```{julia}
using Printf using Printf
@@ -81,16 +82,16 @@ using Printf
iterationA(s) = sqrt(2 - sqrt(4 - s^2)) iterationA(s) = sqrt(2 - sqrt(4 - s^2))
iterationB(s) = s / sqrt(2 + sqrt(4 - s^2)) iterationB(s) = s / sqrt(2 + sqrt(4 - s^2))
s_B = s_A = sqrt(2) # 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[] ϵ_B = Float64[]
is = Float64[] is = Float64[]
@printf """Approx. value of π @printf """ approx. Wert von π
n-gon Iteration A Iteration B n-Eck Iteration A Iteration B
""" """
for i in 3:35 for i in 3:35
@@ -101,67 +102,77 @@ for i in 3:35
doublePi_B = 2^i * s_B doublePi_B = 2^i * s_B
push!(ϵ_A, ϵ(doublePi_A)) push!(ϵ_A, ϵ(doublePi_A))
push!(ϵ_B, ϵ(doublePi_B)) 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 end
``` ```
While Iteration B stabilizes to a value accurate within machine precision, Iteration A is unstable and diverges. 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} ```{julia}
using PlotlyJS 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", yaxis_type="log", yaxis_exponentformat="power",
xaxis_tick0=2, xaxis_dtick=2) 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)], scatter(x=is, y=ϵ_B, mode="markers+lines", name="Iteration B", yscale=:log10)],
layout) layout)
``` ```
## Stability and Cancellation
At $i=26$, Iteration B reaches a relative error on the order of machine epsilon:
## Stabilität und Auslöschung
Bei $i=26$ erreicht Iteration B einen relativen Fehler in der Größe des Maschinenepsilons:
```{julia} ```{julia}
ϵ_B[22:28] ϵ_B[22:28]
``` ```
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} ```{julia}
ϵ_B[end]/eps(Float64) ϵ_B[end]/eps(Float64)
``` ```
Iteration A is unstable; already at $i=16$, the relative error begins to grow again.
The cause is a typical numerical cancellation effect. The side lengths $s_n$ become very small very quickly. Thus Die Form Iteration A ist instabil. Bereits bei $i=16$ beginnt der relative Fehler wieder zu wachsen.
$a_n=\sqrt{4-s_n^2}$ is only slightly smaller than 2, and computing $s_{2n}=\sqrt{2-a_n}$ leads to a catastrophic cancellation.
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} ```{julia}
setprecision(80) # precision for BigFloat setprecision(80) # precision für BigFloat
s = sqrt(BigFloat(2)) 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) s = iterationA(s)
x = sqrt(4-s^2) x = sqrt(4-s^2)
if i > 20 if i > 20
@printf "%i %30.26f %20.16f \n" i x Float64(x) @printf "%i %30.26f %20.16f \n" i x Float64(x)
end end
end end
``` ```
This demonstrates the loss of significant digits. It also shows that using `BigFloat` with 80 bits of precission (mantissa length) only slightly delays 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.
the onset of the cancellation effect.
**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"} :::{.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 Offensichtlich tritt bei der Berechnung von $2-a_n$ bereits relativ früh
before the computation of $a_n=\sqrt{4-s_n^2}$ itself leads to an unusable result due to cancellation. 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.
::: :::

View File

@@ -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.
## Installing on Your Own 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/>. 1. Julia mit dem Installations- und Update-Manager **juliaup** installieren: <https://github.com/JuliaLang/juliaup/>
2. Install **Visual Studio Code** as editor/IDE: <https://code.visualstudio.com/>. 2. als Editor/IDE **Visual Studio Code** installieren: <https://code.visualstudio.com/>
3. Install the **Julia language extension** in VS Code: <https://www.julia-vscode.org/docs/stable/gettingstarted/>. 3. im VS Code Editor die **Julia language extension** installieren: <https://www.julia-vscode.org/docs/stable/gettingstarted/>
Getting started: Einstieg:
- Create a new file with the extension `.jl` in VS Code - In VS Code eine neue Datei mit der Endung `.jl` anlegen
- Write Julia code - Julia-Code schreiben
- `Shift-Enter` or `Ctrl-Enter` at the end of a statement or block starts a Julia-REPL: the code is copied to the REPL and executed - `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
- [Key bindings for VS Code](https://code.visualstudio.com/docs/getstarted/keybindings#_keyboard-shortcuts-reference) - [Tastenbelegungen für 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/) 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 from the command line, the [Julia-REPL](https://docs.julialang.org/en/v1/stdlib/REPL/) (*read-eval-print* loop) opens, allowing interactive work. 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 ```default
$ julia $ julia
_ _
_ _ _(_)_ | Documentation: https://docs.julialang.org _ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) | (_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | | | | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.12.5 (2026-02-09) | | |_| | | | (_| | | Version 1.11.4 (2025-03-10)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release _/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ | |__/ |
julia> 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 & Jupyter
- [JupyterHub](https://de.wikipedia.org/wiki/Project_Jupyter) is a multi-user server for Jupyter notebooks. - [Jupyterhub](https://de.wikipedia.org/wiki/Project_Jupyter) ist ein Multi-User-Server für Jupyter.
- Jupyter is a web-based interactive programming environment - Jupyter ist eine web-basierte interaktive Programmierumgebung, die
- Originally written for and in Python, but now supports many programming languages - ursprünglich in und für Python geschrieben, inzwischen eine
- In Jupyter, one works with so-called *notebooks*: structured text files (JSON) with the file extension `*.ipynb`. 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="html"}
![](../images/notebook001.png) ![](../images/notebook001.png)
::: :::
::: {.content-visible when-format="typst"} ::: {.content-visible when-format="pdf"}
![Jupyterhub file manager](../images/notebook001.png){width=50%} ![Jupyterhub Dateimanager](../images/notebook001.png){width=50%}
::: :::
This can be used to: Mit diesem kann man:
- open existing *notebooks*, - vorhandene *notebooks* öffnen,
- create new *notebooks*, - neue *notebooks* anlegen,
- upload files, e.g., notebooks, from your local computer, - Dateien, z.B. *notebooks*, vom lokalen Rechner hochladen,
- log out when finished (Please don't forget this!) - die Sitzung mit `Logout` beenden (bitte nicht vergessen!).
### Jupyter notebooks ### Jupyter notebooks
@@ -75,37 +77,37 @@ This can be used to:
![](../images/notebook003.png) ![](../images/notebook003.png)
::: :::
::: {.content-visible when-format="typst"} ::: {.content-visible when-format="pdf"}
![Jupyter Notebook](../images/notebook003.png){width=50%} ![Jupyter Notebook](../images/notebook003.png){width=50%}
::: :::
*Notebooks* consist of cells. Cells can contain *Notebooks* bestehen aus Zellen. Zellen können
- Code, or - Code oder
- Text/documentation (Markdown) - 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 } ::: {.callout-tip }
Please check the `User Interface Tour` and `Keyboard Shortcuts` topics 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} :::{.narrow}
| | *Command mode* | *Edit mode* | | | *Command mode* | *Edit mode* |
|:-------|:---------------:|:-----------:| |:-------|:---------------:|:-----------:|
| Activate mode | `ESC` | Double-click or `Enter` in cell | | Mode aktivieren | `ESC` | Doppelklick oder `Enter` in Zelle |
| New cell | `b` | `Alt-Enter` | | neue Zelle | `b` | `Alt-Enter` |
| Delete cell | `dd` | | | Zelle löschen | `dd` | |
| Save notebook | `s` | `Ctrl-s` | | Notebook speichern | `s` | `Ctrl-s` |
| Rename notebook | `Menu -> File -> Rename` | `Menu -> File -> Rename` | | Notebook umbenennen | `Menu -> File -> Rename` | `Menu -> File -> Rename` |
| Close notebook | `Menu -> File -> Close & Halt` | `Menu -> File -> Close & Halt` | | Notebook schließen | `Menu -> File -> Close & Halt` | `Menu -> File -> Close & Halt` |
| *Run cell* | `Ctrl-Enter` | `Ctrl-Enter` | | *run cell* | `Ctrl-Enter` | `Ctrl-Enter` |
| *Run cell, move to next cell* | `Shift-Enter` | `Shift-Enter` | | *run cell, move to next cell* | `Shift-Enter` | `Shift-Enter` |
| *Run cell, insert new cell below* | `Alt-Enter` | `Alt-Enter` | | *run cell, insert new cell below* | `Alt-Enter` | `Alt-Enter` |
: {.striped} : {.striped}
@@ -115,28 +117,30 @@ The cell currently being worked on can be in `command mode` or `edit mode`.
![](../images/notebook002.png) ![](../images/notebook002.png)
::: :::
::: {.content-visible when-format="typst"} ::: {.content-visible when-format="pdf"}
![Julia working...](../images/notebook002.png){width=50%} ![Julia arbeitet...](../images/notebook002.png){width=50%}
::: :::
When a cell is working, its cell number becomes a `*` and
the `kernel busy` indicator appears (solid black dot at the top right next to the
Julia version). If this takes too long (an *infinite loop*
can easily happen):
- click `Menu -> Kernel -> Interrupt`. If this doesn't work, Wenn eine Zelle \"arbeitet\", wird ihre Zellen-Nummer zu einem `*` und
- click `Menu -> Kernel -> Restart`. 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 } ::: {.callout-important }
After a `kernel restart`, all cells containing the required definitions, Nach einem `kernel restart` müssen alle Zellen, die weiterhin benötigte Definitionen,
`using` statements, etc. must be executed again. `using`-Anweisungen etc enthalten, wieder ausgeführt werden.
**At the end of each session, please always:** **Am Ende der Arbeit bitte immer:**
- `Menu -> File -> Save & Checkpoint` - `Menu -> File -> Save & Checkpoint`
- `Menu -> File -> Close & Halt` - `Menu -> File -> Close & Halt`
- `Logout` - `Logout`
::: :::

View File

@@ -1,7 +1,5 @@
--- ---
engine: julia engine: julia
julia:
exeflags: ["--color=yes"]
--- ---
```{julia} ```{julia}
@@ -13,10 +11,10 @@ using InteractiveUtils
# First Contact # First Contact
This chapter helps you get started. It omits many details, and the code examples are often not optimal. 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} ```{julia}
#| eval: true #| eval: true
@@ -35,7 +33,7 @@ function Tab(s)
dc = map(x->x.name, REPL.doc_completions(s)) dc = map(x->x.name, REPL.doc_completions(s))
l = filter(x->startswith(x,s), dc) l = filter(x->startswith(x,s), dc)
println.(l) println.(l)
return # return nothing, since broadcasting println produces an empty vector return # return nothing, since broadcast println produces empty vector
end end
▷ = |> ▷ = |>
@@ -43,23 +41,23 @@ end
# IJulia.set_verbose(true) # IJulia.set_verbose(true)
``` ```
Compute the following: $\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} ```{julia}
12^(1/3) + 3sqrt(2) / (sin(.5) - cos(pi/4)*log(3)) + exp(5) 12^(1/3) + 3sqrt(2) / (sin(.5) - cos(pi/4)*log(3)) + exp(5)
``` ```
Note that: Man beachte:
- Powers are written as `a^b`. - Potenzen schreibt man `a^b`.
- The constant `π` is predefined. - Die Konstante `pi` ist vordefiniert.
- `log()` is the natural logarithm. - `log()` ist der natürliche Logarithmus.
- The multiplication operator `*` can be omitted after a number when followed by a variable, function, or opening parenthesis. - 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, press the Tab key as soon as you've typed 23 letters of a word. Potential completions are then displayed or completed if the completion is unique. This saves time and you learn a lot about Julia. 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} ```{julia}
lo = "lo" #| hide_line lo = "lo" #| hide_line
@@ -71,41 +69,33 @@ pri = "pri" #| hide_line
pri ▷ Tab pri ▷ Tab
``` ```
Julia's built-in help system `?name` provides comprehensive documentation for all functions and constructs. Here is a relatively brief example: Die eingebaute Julia-Hilfe `?name` zu allen Funktionen und Konstrukten ist sehr umfassend. Hier ein eher kurzes Beispiel:
:::{.content-visible unless-format="typst"}
```{julia} ```{julia}
?for ?for
``` ```
:::
:::{.content-hidden unless-format="typst"} :::{.content-hidden unless-format="xxx"}
::: {.cell } ::: {.cell }
```{.julia .cell-code} ``` {.julia .cell-code}
?for ?for
``` ```
::: {.cell-output .cell-output-stdout} ::: {.cell-output .cell-output-stdout}
``` ```
search: for nor xor foldr floor Core sort search: for foreach foldr floor mapfoldr factorial EOFError OverflowError
for for loops repeatedly evaluate a block of statements while iterating over a sequence of values.
for loops repeatedly evaluate a block of statements while iterating over a sequence of values. Examples
The iteration variable is always a new variable, even if a variable of the same name exists in the enclosing scope. Use outer to reuse an existing local variable for iteration. julia> for i in [1, 4, 0]
println(i)
Examples end
======== 1
4
julia> for i in [1, 4, 0] 0
println(i)
end
1
4
0
``` ```
::: :::
@@ -113,104 +103,101 @@ search: for nor xor foldr floor Core sort
::: :::
## Variables and Assignments ## Variablen und Zuweisungen
Variables are created through assignment with the assignment operator `=`. Variablen entstehen durch Zuweisung *(assignment)* mit dem Zuweisungsoperator `=` . Danach können sie in weiteren Anweisungen verwendet werden.
```{julia} ```{julia}
x = 1 + sqrt(5) x = 1 + sqrt(5)
y = x / 2 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} :::{.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 - berechne die rechte Seite und
- Assign the result to the left side. - 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 Julia ist eine [stark typisierte](https://de.wikipedia.org/wiki/Starke_Typisierung) Sprache. Alle Objekte haben einen Typ.
where every object has a type. Among the fundamental types are: So gibt es unter anderem die Basistypen
- Ganze Zahlen *(integers)*,
- Gleitkommazahlen *(floating point numbers)*,
- Zeichenketten *(strings)* und
- Wahrheitswerte *(booleans)*.
- Integers Den Typ einer Variablen kann man mit der Funktion `typeof()` ermitteln.
- Floating-point numbers
- Strings
- Booleans.
The type of a variable can be determined using the `typeof()` function.
```{julia} ```{julia}
#| warning: true #| warning: true
#| error: true #| error: true
for x ∈ (42, 12.0, 3.3e4, "Hello!", true) for x ∈ (42, 12.0, 3.3e4, "Hallo!", true)
println("x = ", x, " ... Type: ", typeof(x)) println("x = ", x, " ..... Typ: ", typeof(x))
end 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. Julia ist eine [dynamisch typisierte](https://de.wikipedia.org/wiki/Dynamische_Typisierung) Sprache.
Variables have no type; they are typeless references (pointers) to typed objects. Variablen haben keinen Typ. Sie sind typlose Referenzen (Zeiger) auf Objekte.
When people speak of the "type of a variable", they mean the type of the object currently assigned to the variable. Wenn man vom „Typ einer Variablen“ spricht, meint man den Typ des Objektes, das der Variablen gerade zugewiesen ist.
```{julia} ```{julia}
x = sqrt(2) 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 ## Druckanweisungen
The `println()` function adds a line break at the end; `print()` does not. Die Funktion `println()` unterscheidet sich von `print()` dadurch, dass sie am Ende einen Zeilenvorschub ausgibt.
```{julia} ```{julia}
print(y) print(y)
print("...the line continues...") print("...die Zeile geht weiter...")
print("still...") print("immernoch...")
println(y) println(y)
println("New line") println("Neue Zeile")
println("New line") println("Neue Zeile")
``` ```
Beide Funkionen können als Argument eine Liste von *strings* und Variablen bekommen. Man kann Variablen auch in *strings* einbetten, indem man dem Variablennamen ein Dollarzeichen voranstellt *(string interpolation)*.
Both functions can accept a list of string literals and variables as arguments. Variables can also be embedded in strings by prefixing the variable name with a dollar sign *(string interpolation)*.
```{julia} ```{julia}
x = 23 x = 23
y = 3x + 5 y = 3x + 5
zz = "Done!" zz = "Fertig!"
println("x= ", x, " ... and y= ", y, "...", zz) # 1. variant println("x= ", x, " ...und y= ", y, "...", zz) # 1. Variante
println("x= $x ... and y= $y...$zz") # variant with string interpolation println("x= $x ...und y= $y...$zz") # Variante mit string interpolation
``` ```
:::{.callout-note .titlenormal collapse=true icon=false } :::{.callout-note .titlenormal collapse=true icon=false }
## If you want to print a dollar sign... ## Wenn man ein Dollarzeichen drucken will...
you must escape it with a *backslash*. To print a *backslash* itself, you must double it. muss man einen *backslash* voranstellen. Wenn man einen *backslash* drucken will, muss man ihn verdoppeln.
```{julia} ```{julia}
println("One dollar: 1\$ and three backslashes: \\\\\\ ") println("Ein Dollar: 1\$ und drei backslashs: \\\\\\ ")
``` ```
::: :::
## Functions ## Funktionen
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 a `return` statement. 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} ```{julia}
function hypotenuse(a, b) # a bit cumbersome function hypotenuse(a, b) # heute besonders umständlich
c2 = a^2 + b^2 c2 = a^2 + b^2
c = sqrt(c2) c = sqrt(c2)
return c return c
end end
``` ```
After definition, the function can be used (called). The variables `a,b,c,c2` used in the definition are local and 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} ```{julia}
#| error: true #| error: true
x = 3 x = 3
@@ -219,71 +206,72 @@ println("z = $z")
println("c = $c") println("c = $c")
``` ```
Very simple functions can also be defined as one-liners: Sehr einfache Funktionen können auch als Einzeiler definiert werden.
```{julia} ```{julia}
hypotenuse(a, b) = sqrt(a^2+b^2) hypotenuse(a, b) = sqrt(a^2+b^2)
``` ```
## Tests ## Tests
Tests return a Boolean value (`true` or `false`). Tests liefern einen Wahrheitswert zurück.
```{julia} ```{julia}
x = 3^2 x = 3^2
x < 2^3 x < 2^3
``` ```
In addition to the usual arithmetic comparisons `==, !=, <, <=, >, >=` Neben den üblichen arithmetischen Vergleichen `==, !=, <, <= ,> ,>=`
there are many other tests. 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. 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} ```{julia}
test1 = "Car" in ["Bicycle", "Car", "Train"] test1 = "Auto" in ["Fahrrad", "Auto", "Bahn"]
test2 = x == 100 || !(x <= 30 && x > 8) test2 = x == 100 || !(x <= 30 && x > 8)
test3 = startswith("lampshade", "Lamp") test3 = startswith("Lampenschirm", "Lamp")
println("$test1 $test2 $test3") println("$test1 $test2 $test3")
``` ```
## Verzweigungen
Verzweigungen (bedingte Anweisungen) haben die Form
## Conditional Statements
A simple `if` statement has the form
```default ```default
if <test> if <Test>
<statement1> <Anweisung1>
<statement2> <Anweisung2>
... ...
end end
``` ```
There can be one or more `elseif` blocks and an optional final `else` block.
Ein `else`-Zweig und `elseif`-Zweige sind möglich.
```{julia} ```{julia}
x = sqrt(100) x = sqrt(100)
if x > 20 if x > 20
println("Strange!") println("Seltsam!")
else else
println("OK") println("OK")
y = x + 3 y = x + 3
end end
``` ```
Indentation enhances readability but is optional. Line breaks separate statements, as do semicolons. The code above is equivalent to the following single 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} ```{julia}
# Please don't program like this! You will regret it! # Bitte nicht so programmieren! Sie werden es bereuen!
x=sqrt(100); if x > 20 println("Strange!") else println("OK"); y = x + 3 end x=sqrt(100); if x > 20 println("Seltsam!") else println("OK"); y = x + 3 end
``` ```
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 repeating the execution of statements have the form zum wiederholten Abarbeiten von Anweisungen haben die Form
```default ```default
for <counter> = start:end for <Zähler> = Start:Ende
<statement1> <Anweisung1>
<statement2> <Anweisung2>
... ...
end end
``` ```
Example: Beispiel:
```{julia} ```{julia}
sum = 0 sum = 0
@@ -293,10 +281,9 @@ end
sum sum
``` ```
## Arrays ## Arrays
One-dimensional arrays (vectors) are a simple container type. They can be created with square brackets 1-dimensionale Arrays (Vektoren) sind eine einfache Form von Containern. Man kann sie mit echigen Klammern anlegen
and accessed by index, with indexing starting at 1. und auf die Elemente per Index zugreifen. Die Indizierung beginnt mit 1.
```{julia} ```{julia}
v = [12, 33.2, 17, 19, 22] v = [12, 33.2, 17, 19, 22]
@@ -311,18 +298,17 @@ v[1] = v[4] + 10
v v
``` ```
Empty vectors can be created and extended with `push!()`. Man kann leere Vektoren anlegen und sie verlängern.
```{julia} ```{julia}
v = [] # empty vector v = [] # leerer Vektor
push!(v, 42) push!(v, 42)
push!(v, 13) push!(v, 13)
v v
``` ```
:::{.callout-note icon="false" .titlenormal collapse="true" font-variant-ligatures="no-contextual" } :::{.callout-note icon="false" .titlenormal collapse="true" font-variant-ligatures="no-contextual" }
## Appendix: 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} ```{julia}
using REPL using REPL

View File

@@ -1,34 +1,8 @@
--- ---
engine: julia engine: julia
julia:
exeflags: ["--color=yes"]
--- ---
```{julia} # Maschinenzahlen
#| error: false
#| echo: false
#| output: false
using InteractiveUtils
#struct M a::Int end; x = M(22); @show x
#should not print "Main.Notebook.M(22)" but only "M(22)"
function Base.show(io::IO, x::T) where T
if parentmodule(T) == @__MODULE__
# Print "TypeName(fields...)" without module prefix
print(io, nameof(T), "(")
fields = fieldnames(T)
for (i, f) in enumerate(fields)
print(io, getfield(x, f))
i < length(fields) && print(io, ", ")
end
print(io, ")")
else
invoke(Base.show, Tuple{IO, Any}, io, x)
end
end
```
# Machine Numbers
```{julia} ```{julia}
#| error: false #| error: false
@@ -44,24 +18,24 @@ for x ∈ ( 3, 3.3e4, Int16(20), Float32(3.3e4), UInt16(9) )
end end
``` ```
## Integers ## Ganze Zahlen *(integers)*
Integers are stored as fixed-length bit patterns. Therefore, the value range is finite. Ganze Zahlen werden grundsätzlich als Bitmuster fester Länge gespeichert. Damit ist der Wertebereich endlich.
**Within this value range** addition, subtraction, multiplication, and integer division with remainder **Innerhalb dieses Wertebereichs** sind Addition, Subtraktion, Multiplikation und die Ganzzahldivision mit Rest
are exact operations without rounding errors. exakte Operationen ohne Rundungsfehler.
Integer numbers come in two types: `Signed` 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* ### *Unsigned integers*
```{julia} ```{julia}
subtypes(Unsigned) subtypes(Unsigned)
``` ```
`UInts` are binary numbers with a bit width of 8, 16, 32, 64, or 128 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 0 \le x < 2^n
$$ $$
They are used rarely in *scientific computing*. In low-level hardware programming, they are used, e.g., for handling binary data and memory addresses. By default, Julia displays them 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} ```{julia}
x = 0x0033efef x = 0x0033efef
@@ -76,51 +50,51 @@ z = UInt(32)
```{julia} ```{julia}
subtypes(Signed) subtypes(Signed)
``` ```
*Integers* have the value range *Integers* haben den Wertebereich
$$ $$
-2^{n-1} \le x < 2^{n-1} -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} ```{julia}
x = 42 x = 42
typeof(x) 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 -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 -2.147.483.648 \le x \le 2.147.483.647
$$ $$
By the way, the maximum value $2^{31}-1$ is a Mersenne prime: Der Maximalwert $2^{31}-1$ is zufällig gerade eine Mersenne-Primzahl:
```{julia} ```{julia}
using Primes using Primes
isprime(2^31-1) 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 as follows: Das sieht so aus:
::: {.content-visible when-format="html"} ::: {.content-visible when-format="html"}
![A representation of the fictional data type `Int4`](../images/Int4.png){width=50%} ![Eine Darstellung des fiktiven Datentyps `Int4`](../images/Int4.png){width=50%}
::: :::
::: {.content-visible when-format="typst"} ::: {.content-visible when-format="pdf"}
![A representation of the fictional data type `Int4`](../images/Int4.png){width=50%} ![Eine Darstellung des fiktiven Datentyps `Int4`](../images/Int4.png){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} :::{.callout-important}
All integer arithmetic is __arithmetic modulo $2^n$__ Die gesamte Ganzzahlarithmetik ist eine __Arithmetik modulo $2^n$__
```{julia} ```{julia}
x = 2^62 - 10 + 2^62 x = 2^62 - 10 + 2^62
@@ -128,11 +102,11 @@ x = 2^62 - 10 + 2^62
```{julia} ```{julia}
x + 20 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} ```{julia}
@@ -145,7 +119,7 @@ for i in (1, 2, 7, -7, 2^50, -1, Int16(7), Int8(7))
end end
``` ```
Julia has functions that provide type information (*introspection*): Julia hat Funktionen, die über die Datentypen informieren (*introspection*):
```{julia} ```{julia}
@@ -160,36 +134,36 @@ typemin(UInt64), typemax(UInt64), BigInt(typemax(UInt64))
typemin(Int8), typemax(Int8) typemin(Int8), typemax(Int8)
``` ```
## Integer Arithmetic ## Arithmetik ganzer Zahlen
#### Addition, Multiplication #### Addition, Multiplikation
The operations `+`,`-`,`*` have the usual exact arithmetic **modulo $2^{64}$**. 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`. - Potenzen `a^n` werden für natürliche Exponenten `n` ebenfalls modulo $2^{64}$ exakt berechnet.
- For negative exponents, the result is a `Float`. - Für negative Exponenten ist das Ergebnis eine Gleitkommazahl.
- `0^0` is [naturally](https://en.wikipedia.org/wiki/Zero_to_the_power_of_zero#cite_note-T4n3B-4) equal to 1. - `0^0` ist [selbstverständlich](https://en.wikipedia.org/wiki/Zero_to_the_power_of_zero#cite_note-T4n3B-4) gleich 1.
```{julia} ```{julia}
(-2)^63, 2^64, 3^(-3), 0^0 (-2)^63, 2^64, 3^(-3), 0^0
``` ```
- For natural exponents, [*exponentiation by squaring*](https://en.wikipedia.org/wiki/Exponentiation_by_squaring) 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 x^{23} = \left( \left( (x^2)^2 \cdot x \right)^2 \cdot x \right)^2 \cdot x
$$ $$
#### Division #### Division
- Division `/` produces a floating-point number. - Division `/` erzeugt eine Gleitkommazahl.
```{julia} ```{julia}
x = 40/5 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. - 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.
- For `div(a,b)` there is the operator form `a ÷ b` (input: `\div<TAB>`), and for `rem(a,b)` the operator form `a % b`. - Für `div(a,b)` gibt es die Operatorform `a ÷ b` (Eingabe: `\div<TAB>`) und für `rem(a,b)` die Operatorform `a % b`.
- By default, division uses "rounding toward zero", so the corresponding remainder has the same sign as the dividend `a`: - Standardmäßig wird bei der Division „zur Null hin gerundet“, wodurch der dazugehörige Rest dasselbe Vorzeichen wie der Dividend `a` trägt:
```{julia} ```{julia}
@show divrem( 27, 4) @show divrem( 27, 4)
@@ -198,9 +172,9 @@ x = 40/5
@show ( 27 ÷ -4, 27 % -4); @show ( 27 ÷ -4, 27 % -4);
``` ```
- A rounding rule other than `RoundToZero` can be specified as the third optional argument for these functions. - Eine von `RoundToZero` abweichende Rundungsregel kann bei den Funktionen als optionales 3. Argument angegeben werden.
- `?RoundingMode` shows the possible rounding modes. - `?RoundingMode` zeigt die möglichen Rundungsregeln an.
- 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)`: - 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} ```{julia}
@show divrem(-27, 4, RoundDown) @show divrem(-27, 4, RoundDown)
@@ -208,47 +182,47 @@ x = 40/5
@show (fld( 27, -4), mod( 27, -4)); @show (fld( 27, -4), mod( 27, -4));
``` ```
For all rounding modes, the following holds: Für alle Rundungsregeln gilt:
``` ```
div(a, b, RoundingMode) * b + rem(a, b, RoundingMode) = a div(a, b, RoundingMode) * b + rem(a, b, RoundingMode) = a
``` ```
#### The `BigInt` Type #### Der Datentyp `BigInt`
The `BigInt` type supports arbitrary-precision integers with dynamically allocated memory. 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} ```{julia}
z = 10 z = 10
@show typeof(z) @show typeof(z)
z = 10_000_000_000_000_000 # 10 quadrillion z = 10_000_000_000_000_000 # 10 Billiarden
@show typeof(z) @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) @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); @show typeof(z);
``` ```
In most cases, you must explicitly specify 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} ```{julia}
@show 3^300 BigInt(3)^300; @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` versus `BigInt`. Wir vergleichen den Zeit- und Speicherbedarf bei der Aufsummation von 10 Millionen Ganzzahlen als `Int64` und als `BigInt`.
```{julia} ```{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) vec_int = rand(-10^7:10^7, 10^7)
# The same numbers as BigInts # Dieselben Zahlen als BigInts
vec_bigint = BigInt.(vec_int) vec_bigint = BigInt.(vec_int)
``` ```
The `@time` macro provides a rough estimate of the required time and memory: Einen ersten Eindruck vom Zeit- und Speicherbedarf gibt das `@time`-Macro:
```{julia} ```{julia}
@time x = sum(vec_int) @time x = sum(vec_int)
@@ -259,7 +233,7 @@ The `@time` macro provides a rough estimate of the required time and memory:
@show x typeof(x); @show x typeof(x);
``` ```
Due to Julia's just-in-time compilation, timing a single function call 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} :::{.ansitight}
```{julia} ```{julia}
@@ -273,11 +247,13 @@ using BenchmarkTools
@benchmark sum($vec_bigint) @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"} :::{.content-hidden unless-format="xxx"}
The following function computes the sum of all numbers from 1 to n using arithmetic of type T. Die folgende Funktion soll die Summe aller Zahlen von 1 bis n mit der Arithmetik des Datentyps T berechnen.
Due to *type promotion rules*, it is sufficient to initialize the accumulator with a value of type T (for `T ≥ Int64`). 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} ```{julia}
function mysum(n, T) function mysum(n, T)
s = T(0) s = T(0)
@@ -288,7 +264,7 @@ function mysum(n, T)
end 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} ```{julia}
@time x = mysum(10_000_000, Int64) @time x = mysum(10_000_000, Int64)
@@ -300,7 +276,7 @@ An initial impression of the time and memory requirements is provided by the `@t
@show x typeof(x); @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} :::{.ansitight}
```{julia} ```{julia}
@@ -316,83 +292,85 @@ using BenchmarkTools
``` ```
The computation of $\sum_{n=1}^{10000000} n$ takes on my PC an average of 2 milliseconds 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
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 der Numerischen Mathematik spricht man auch gerne von **Maschinenzahlen**.
In numerical mathematics, the term **machine numbers** is also commonly used. ### Grundidee
- Eine „feste Anzahl von Vor- und Nachkommastellen“ ist für viele Probleme ungeeignet.
### Basic Idea - Eine Trennung zwischen „gültigen Ziffern“ und Größenordnung (Mantisse und Exponent) wie in der wissenschaftlichen Notation ist wesentlich flexibler.
- 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.
$$ 345.2467 \times 10^3\qquad 34.52467\times 10^4\qquad \underline{3.452467\times 10^5}\qquad 0.3452467\times 10^6\qquad 0.03452467\times 10^7$$ $$ 345.2467 \times 10^3\qquad 34.52467\times 10^4\qquad \underline{3.452467\times 10^5}\qquad 0.3452467\times 10^6\qquad 0.03452467\times 10^7$$
- 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}, 1 > m \ge (0.1)_b = b^{-1},
$$ $$
where $b$ denotes the base of the number system. wobei $b$ die gewählte Basis des Zahlensystems bezeichnet.
- We choose the form that corresponds to the actual implementation on the computer and specify: - Wir wählen im Folgenden die Form, die der tatsächlichen Implementation auf dem Computer entspricht und legen fest:
The representation with exactly one nonzero digit before the decimal point is the __normalized representation__. Thus, Die Darstellung mit genau einer Ziffer ungleich Null vor dem Komma ist die __Normalisierte Darstellung__. Damit gilt
$$ $$
(10)_b = b> m \ge 1. (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$$ $$m = 1 + M$$
holds. gilt.
:::{.callout-note } :::{.callout-note }
## Machine Numbers ## Maschinenzahlen
The set of machine numbers $𝕄(b, p, e_{min}, e_{max})$ is characterized by the base $b$, 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$) 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 - `Float32` als $𝕄(2, 24, -126, 127 )$ und
- `Float64` as $𝕄(2, 53, -1022, 1023 ).$ - `Float64` als $𝕄(2, 53, -1022, 1023 ).$
::: :::
### Structure of `Float64` according to the [IEEE 754 standard](https://en.wikipedia.org/wiki/IEEE_754) ### Aufbau von `Float64` nach [Standard IEEE 754](https://de.wikipedia.org/wiki/IEEE_754)
::: {.content-visible when-format="html"} ::: {.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) ](../images/1024px-IEEE_754_Double_Floating_Point_Format.png)
::: :::
::: {.content-visible when-format="typst"} ::: {.content-visible when-format="pdf"}
![Structure of a `Float64` \mysmall{(Source: \href{https://commons.wikimedia.org/wiki/File:IEEE_754_Double_Floating_Point_Format.svg}{Codekaizen}, \href{https://creativecommons.org/licenses/by-sa/4.0}{CC BY-SA 4.0}, via Wikimedia Commons)} ![Aufbau einer `Float64` \mysmall{(Quelle: \href{https://commons.wikimedia.org/wiki/File:IEEE_754_Double_Floating_Point_Format.svg}{Codekaizen}, \href{https://creativecommons.org/licenses/by-sa/4.0}{CC BY-SA 4.0}, via Wikimedia Commons)}
](../images/1024px-IEEE_754_Double_Floating_Point_Format.png){width="70%"} ](../images/1024px-IEEE_754_Double_Floating_Point_Format.png){width="70%"}
::: :::
- 1 sign bit $S$ - 1 Vorzeichenbit $S$
- 11 bits for the exponent, thus $0\le E \le 2047$ - 11 Bits für den Exponenten, also $0\le E \le 2047$
- The values $E=0$ and $E=(11111111111)_2=2047$ are reserved for encoding special values such as - 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)_ and subnormal numbers. $\pm0, \pm\infty$, NaN _(Not a Number)_ und denormalisierte Zahlen.
- 52 bits for the (shortened) mantissa $M,\quad 0\le M<1$, corresponding to approximately 16 decimal digits - 52 Bits für die (gekürzte) Mantisse $M,\quad 0\le M<1$, das entspricht etwa 16 Dezimalstellen
- Thus, the number represented is: - Damit wird folgende Zahl dargestellt:
$$ x=(-1)^S \cdot(1+M)\cdot 2^{E-1023}$$ $$ x=(-1)^S \cdot(1+M)\cdot 2^{E-1023}$$
An example: Ein Beispiel:
```{julia} ```{julia}
x = 27.56640625 x = 27.56640625
bitstring(x) bitstring(x)
``` ```
This can be displayed more clearly: Das geht auch schöner:
```{julia} ```{julia}
function printbitsf64(x::Float64) function printbitsf64(x::Float64)
@@ -405,7 +383,7 @@ end
printbitsf64(x) 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} \begin{aligned}
S &= 0\\ S &= 0\\
@@ -416,15 +394,15 @@ x &=(-1)^S \cdot(1+M)\cdot 2^{E-1023}
$$ $$
... and thus reconstruct the number: ... und damit die Zahl rekonstruieren:
```{julia} ```{julia}
x = (1 + 1/2 + 1/8 + 1/16 + 1/32 + 1/256 + 1/4096) * 2^4 x = (1 + 1/2 + 1/8 + 1/16 + 1/32 + 1/256 + 1/4096) * 2^4
``` ```
- The set of machine numbers 𝕄 forms a finite, discrete subset of . There exists a smallest and a largest machine number; all other elements x∈𝕄 have both a predecessor and successor in 𝕄. - 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 𝕄.
- What is the successor of x in 𝕄? To do this, we set the smallest mantissa bit from 0 to 1. - Was ist der Nachfolger von x in 𝕄? Dazu setzen wir das kleinste Mantissenbit von 0 auf 1.
- Converting a string of zeros and ones into the corresponding machine number: - Die Umwandlung eines Strings aus Nullen und Einsen in die entsprechende Maschinenzahl ist z.B. so möglich:
```{julia} ```{julia}
@@ -432,13 +410,13 @@ ux = parse(UInt64, "010000000011101110010001000000000000000000000000000000000000
reinterpret(Float64, ux) reinterpret(Float64, ux)
``` ```
However, Julia can do this more simply: Das kann man in Julia allerdings auch einfacher haben:
```{julia} ```{julia}
y = nextfloat(x) y = nextfloat(x)
``` ```
The predecessor of x is: Der Vorgänger von x ist:
```{julia} ```{julia}
z = prevfloat(x) z = prevfloat(x)
@@ -448,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} ```{julia}
@show nextfloat(1.) - 1 2^-52 eps(Float64); @show nextfloat(1.) - 1 2^-52 eps(Float64);
``` ```
- Machine epsilon measures the relative distance between machine numbers and quantifies the statement: "64-bit floating-point numbers have a precision of approximately 16 decimal digits." - Das Maschinenepsilon ist ein Maß für den relativen Abstand zwischen den Maschinenzahlen und quantifiziert die Aussage: 64-Bit-Gleitkommazahlen haben eine Genauigkeit von etwa 16 Dezimalstellen.“
- Machine epsilon should not be confused with the smallest positive floating-point number: - Das Maschinenepsilon ist etwas völlig anderes als die kleinste positive Gleitkommazahl:
```{julia} ```{julia}
floatmin(Float64) 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} \epsilon' = \frac{\epsilon}{2}\approx 1.1\times 10^{-16}
$$ $$
This is the maximum relative error that can occur when rounding a real number to the nearest machine number. ist der maximale relative Fehler, der beim Runden einer reellen Zahl auf die nächste Maschinenzahl entstehen kann.
- 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 $1+\epsilon' = 1$ still holds in machine arithmetic.* - 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$.*
This allows to compute machine epsilon using the floating point arithmetic: Auf diese Weise kann man das Maschinenepsilon auch berechnen:
:::{.ansitight} :::{.ansitight}
@@ -484,7 +464,7 @@ end
Eps Eps
``` ```
or as a bit pattern: oder als Bitmuster:
```{julia} ```{julia}
Eps=1 Eps=1
@@ -498,19 +478,19 @@ Eps
::: :::
:::{.callout-note} :::{.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. - Im Intervall $[1,2)$ liegen $2^{52}$ äquidistante Maschinenzahlen.
- 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})$. - 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})$.
- 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})$. - 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})$.
- This forms the set $𝕄_+$ of positive machine numbers, and we have - Dies bildet die Menge $𝕄_+$ der positiven Maschinenzahlen und es ist
$$ $$
𝕄 = -𝕄_+ \cup \{0\} \cup 𝕄_+ 𝕄 = -𝕄_+ \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} ```{julia}
@show floatmax(Float64) @show floatmax(Float64)
@@ -522,35 +502,37 @@ printbitsf64(floatmin(Float64))
## Rounding to Machine Numbers
- The map rd: $\rightarrow$ 𝕄 should round to the nearest representable number.
- Standard rounding mode is _round to nearest, ties to even_: ## Runden auf Maschinenzahlen
when a value falls exactly midway between two machine numbers *(tie)*, the one with 0 as its last mantissa bit is selected.
- Justification: this way, we round up in 50% of the cases and down in 50% of the cases, thus avoiding a "statistical drift" in longer calculations. - Die Abbildung rd: $\rightarrow$ 𝕄 soll zur nächstgelegenen darstellbaren Zahl runden.
- It holds: - 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 \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 is generally not representable as 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} :::{.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) a \oplus b = \text{rd}(a + b)
$$ $$
The same must hold for the implementation of standard functions such as Analoges muss für die Implemetierung der Standardfunktionen wie
`sqrt()`, `log()`, `sin()`, ... -- they also return the machine number closest to the exact result. 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} ```{julia}
1 + 10^-16 + 10^-16 1 + 10^-16 + 10^-16
@@ -560,7 +542,7 @@ Arithmetic is *not associative*:
1 + (10^-16 + 10^-16) 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} \begin{aligned}
1 \oplus 10^{-16} \oplus 10^{-16} &= 1 \oplus 10^{-16} \oplus 10^{-16} &=
@@ -571,7 +553,7 @@ $$
\end{aligned} \end{aligned}
$$ $$
In the second case, one obtains: Im zweiten Fall erhält man:
$$ $$
\begin{aligned} \begin{aligned}
1 \oplus \left(10^{-16} \oplus 10^{-16}\right) &= 1 \oplus \left(10^{-16} \oplus 10^{-16}\right) &=
@@ -582,21 +564,22 @@ $$
$$ $$
One should also remember that even "simple" decimal fractions cannot always 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} \begin{aligned}
(0.1)_{10} &= (0.000110011001100110011001100...)_2 = (0.000\overline{1100})_2 \\ (0.1)_{10} &= (0.000110011001100110011001100...)_2 = (0.000\overline{1100})_2 \\
(0.3)_{10} &= (0.0100110011001100110011001100..)_2 = (0.0\overline{1001})_2 (0.3)_{10} &= (0.0100110011001100110011001100..)_2 = (0.0\overline{1001})_2
\end{aligned} \end{aligned}
$$ $$
```{julia} ```{julia}
printbitsf64(0.1) printbitsf64(0.1)
printbitsf64(0.3) printbitsf64(0.3)
``` ```
Consequence: Folge:
```{julia} ```{julia}
0.1 + 0.1 == 0.2 0.1 + 0.1 == 0.2
@@ -610,7 +593,7 @@ Consequence:
0.2 + 0.1 0.2 + 0.1
``` ```
When outputting a machine number, the binary fraction must be converted to a decimal fraction. Julia can 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} ```{julia}
using Printf using Printf
@printf("%.30f", 0.1) @printf("%.30f", 0.1)
@@ -619,12 +602,12 @@ using Printf
```{julia} ```{julia}
@printf("%.30f", 0.3) @printf("%.30f", 0.3)
``` ```
The binary fraction mantissa of a machine number can have a long or even infinitely periodic decimal expansion. But Die Binärbruch-Mantisse einer Maschinenzahl kann eine lange oder sogar unendlich-periodische Dezimalbruchentwicklung haben. Dadurch
one should not be misled into thinking that this is "higher precision"! sollte man sich nicht eine „höheren Genauigkeit“ suggerieren lassen!
:::{.callout-important} :::{.callout-important}
Key message: When testing `Float`s for equality, one should almost always define a realistic tolerance `epsilon` appropriate to the problem and Moral: wenn man `Float`s auf Gleichheit testen will, sollte man fast immer eine dem Problem angemessene realistische Genauigkeit `epsilon` festlegen und
test: darauf testen:
```julia ```julia
epsilon = 1.e-10 epsilon = 1.e-10
@@ -635,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}$ Die Lücke zwischen Null und der kleinsten normalisierten Maschinenzahl $2^{-1022} \approx 2.22\times 10^{-308}$
is filled with subnormal machine numbers. ist mit denormalisierten Maschinenzahlen besiedelt.
Let's look at 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. - 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.
- Then the normalized representation (nonzero leading digit) - Dann ist die normalisierte Darstellung (Vorkommastelle ungleich 0)
of e.g. 1234.0 is 1.234e3 and of 0.00789 is 7.890e-3. von z.B. 1234.0 gleich 1.234e3 und von 0.00789 gleich 7.890e-3.
- It is essential that machine numbers remain normalized at each computation step. Only then is the full mantissa length utilized, maximizing accuracy. - 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.
- The smallest positive normalized number in our model is `x = 1.000e-5`. Already `x/2` would have to be rounded to 0. - Die kleinste positive normalisierte Zahl in unserem Modell ist `x = 1.000e-5`. Schon `x/2` müsste auf 0 gerundet werden.
- But for many applications, it is advantageous to allow also subnormal numbers and represent `x/2` as `0.500e-5` or `x/20` as `0.050e-5`. - 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.
- This *gradual underflow* is of course associated with a loss of significant digits and thus accuracy. - 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} ```{julia}
#| echo: false #| echo: false
@@ -663,7 +647,7 @@ flush(stdout)
```{julia} ```{julia}
using Printf 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 while x != 0
x /= 2 x /= 2
@@ -673,9 +657,9 @@ end
``` ```
::: :::
## Special Values ## Spezielle Werte
Floating-point arithmetic defines certain special values, e.g., Die Gleitkommaarithmetik kennt einige spezielle Werte, z.B.
```{julia} ```{julia}
nextfloat(floatmax(Float64)) nextfloat(floatmax(Float64))
``` ```
@@ -687,22 +671,23 @@ for x ∈ (NaN, Inf, -Inf, -0.0)
end end
``` ```
- An exponent overflow leads to the result `Inf` or `-Inf`. - Ein Exponentenüberlauf *(overflow)* führt zum Ergebnis `Inf` oder `-Inf`.
```{julia} ```{julia}
2/0, -3/0, floatmax(Float64) * 1.01, exp(1300) 2/0, -3/0, floatmax(Float64) * 1.01, exp(1300)
``` ```
- One can continue calculating with these values: - Damit kann weitergerechnet werden:
```{julia} ```{julia}
-Inf + 20, Inf/30, 23/-Inf, sqrt(Inf), Inf * 0, Inf - Inf -Inf + 20, Inf/30, 23/-Inf, sqrt(Inf), Inf * 0, Inf - Inf
``` ```
- `NaN` *(Not a Number)* represents the result of an undefined operation. 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} ```{julia}
0/0, Inf - Inf, 2.3NaN, sqrt(NaN) 0/0, Inf - Inf, 2.3NaN, sqrt(NaN)
``` ```
- Since `NaN` represents an undefined value, it is not equal to anything, not even to itself. This is sensible, because if two variables `x` and `y` are computed as `NaN`, one should not conclude that they are equal.
- 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} ```{julia}
x = 0/0 x = 0/0
@@ -710,18 +695,18 @@ y = Inf - Inf
@show x==y NaN==NaN isfinite(NaN) isinf(NaN) isnan(x) isnan(y); @show x==y NaN==NaN isfinite(NaN) isinf(NaN) isnan(x) isnan(y);
``` ```
- There is a "minus zero". It signals a numerical underflow of a small *negative* quantity. - Es gibt eine „minus Null“. Sie signalisiert einen Exponentenunterlauf *(underflow)* einer betragsmäßig zu klein gewordenen *negativen* Größe.
```{julia} ```{julia}
@show 23/-Inf -2/exp(1200) -0.0==0.0; @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,...`, `sqrt, exp, log, log2, log10, sin, cos,..., asin, acos,..., sinh,..., gcd, lcm, factorial,...,abs, max, min,...`,
including e.g. the [rounding functions](https://en.wikipedia.org/wiki/Floor_and_ceiling_functions) darunter z.B. die [Rundungsfunktionen](https://de.wikipedia.org/wiki/Abrundungsfunktion_und_Aufrundungsfunktion)
- `floor(T,x)` = $\lfloor x \rfloor$ - `floor(T,x)` = $\lfloor x \rfloor$
- `ceil(T,x)` = $\lceil x \rceil$ - `ceil(T,x)` = $\lceil x \rceil$
@@ -734,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) ceil(3.4), ceil(Int64, 3.5), ceil(Int64, -3.5)
``` ```
Also worth noting is `atan(y, x)`, the two-argument arctangent (known as `atan2` in many programming languages, see [atan2](https://en.wikipedia.org/wiki/Atan2)). 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.
This solves the problem of converting from Cartesian to polar coordinates without awkward case distinctions. 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} ```{julia}
atan(3, -2), atan(-3, 2), atan(-3/2) atan(3, -2), atan(-3, 2), atan(-3/2)
``` ```
## Conversion Between Strings and Numbers ## Umwandlung Strings $\Longleftrightarrow$ Zahlen
Use the functions `parse()` and `string()` for such conversions: Die Umwandlung ist mit den Funktionen `parse()` und `string()` möglich.
```{julia} ```{julia}
parse(Int64, "1101", base=2) parse(Int64, "1101", base=2)
@@ -764,7 +749,7 @@ string(1/7)
string(77, base=16) 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} ```{julia}
@@ -783,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) - 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)

View File

@@ -2,72 +2,63 @@
engine: julia engine: julia
--- ---
# Example: The Parametric Data Type `PComplex` # Ein Fallbeispiel: Der parametrisierte Datentyp PComplex
```{julia} ```{julia}
#| error: false #| error: false
#| echo: false #| echo: false
#| output: false #| output: false
using InteractiveUtils using InteractiveUtils
import QuartoNotebookWorker
#struct M a::Int end; x = M(22); @show x Base.stdout = QuartoNotebookWorker.with_context(stdout)
#should not print "Main.Notebook.M(22)" but only "M(22)" myactive_module() = Main.Notebook
function Base.show(io::IO, x::T) where T Base.active_module() = myactive_module()
if parentmodule(T) == @__MODULE__ # https://github.com/JuliaLang/julia/blob/master/base/show.jl#L516-L520
# Print "TypeName(fields...)" without module prefix # https://github.com/JuliaLang/julia/blob/master/base/show.jl#L3073-L3077
print(io, nameof(T), "(")
fields = fieldnames(T)
for (i, f) in enumerate(fields)
print(io, getfield(x, f))
i < length(fields) && print(io, ", ")
end
print(io, ")")
else
invoke(Base.show, Tuple{IO, Any}, io, x)
end
end
``` ```
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'. - Der Typ soll sich in die Typhierarchie einfügen als Subtyp von '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.) - $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} ```{julia}
struct PComplex{T <: AbstractFloat} <: Number struct PComplex1{T <: AbstractFloat} <: Number
r :: T r :: T
ϕ :: T ϕ :: T
end end
#const PComplex = Main.Notebook.PComplex #| hide_line z1 = PComplex1(-32.0, 33.0)
#Base.show(io::IO, ::Type{PComplex}) = print(io, "PComplex") #| hide_line z2 = PComplex1{Float32}(12, 13)
z1 = PComplex(-32.0, 33.0)
z2 = PComplex{Float32}(12, 13)
@show z1 z2; @show z1 z2;
``` ```
:::{.callout-warning collapse="true" .titlenormal}
##
Es ist nicht möglich, in einer Julia-Session eine einmal definierte `struct` später umzudefinieren. Daher verwende ich verschiedene Namen. Eine andere Möglichkeit ist z.B. die Verwendung von [`ProtoStructs.jl`](https://juliahub.com/ui/Packages/General/ProtoStructs).
:::
Julia automatically provides *default constructors*: Julia stellt automatisch *default constructors* zur Verfügung:
- The constructor `PComplex` infers type `T` from the arguments, and - den Konstruktor `PComplex1`, bei dem der Typ `T` von den übergebenen Argumenten abgeleitet wird und
- Constructors like `PComplex{Float64}` accept explicit type specifications. Arguments are converted to the requested type. - 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. Wir wollen nun, dass der Konstruktor noch mehr tut.
In the polar representation, we want $0\le r$ and $0\le \phi<2\pi$ to hold. 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. - Ein _inner constructor_ ist eine Funktion innerhalb der `struct`-Definition.
- In an _inner constructor_, one can use the special function `new`, which acts like the _default constructor_. - In einem _inner constructor_ kann man die spezielle Funktion `new` verwenden, die wie der _default constructor_ wirkt.
```{julia} ```{julia}
@@ -82,17 +73,18 @@ struct PComplex{T <: AbstractFloat} <: Number
end end
if r==0 ϕ=0 end # normalize r=0 case to phi=0 if r==0 ϕ=0 end # normalize r=0 case to phi=0
ϕ = mod(ϕ, 2π) # map phi into interval [0,2pi) ϕ = mod(ϕ, 2π) # map phi into interval [0,2pi)
new(r, ϕ) # new() is special function, new(r, ϕ) # new() ist special function,
end # available only inside inner constructors end # available only inside inner constructors
end end
``` ```
```{julia} ```{julia}
#| echo: false #| echo: false
#| output: false #| output: false
#= #=
in 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.)) zz = @which Base.show(stdout, PComplex{Float64}(2.,3.))
if zz.module != Base if zz.module != Base
@@ -102,9 +94,9 @@ end
```{julia} ```{julia}
z1 = PComplex{Float64}(-3.3, 7π+1) z1 = PComplex{Float64}(-3.3, 7π+1)
``` ```
However, explicitly specifying an *inner constructor* has a consequence: 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, which infers the type from the arguments, is also needed: Den Konstruktor, der ohne explizite Typangabe in geschweiften Klammern auskommt und den Typ der Argumente übernimmt, wollen wir gerne auch haben:
```{julia} ```{julia}
PComplex(r::T, ϕ::T) where {T<:AbstractFloat} = PComplex{T}(r,ϕ) PComplex(r::T, ϕ::T) where {T<:AbstractFloat} = PComplex{T}(r,ϕ)
@@ -113,53 +105,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:
:::{.content-visible unless-format="typst"}
$$ $$
z= r\enclose{phasorangle}{\phi} = 3.4\;\enclose{phasorangle}{45^\circ} z= r\enclose{phasorangle}{\phi} = 3.4\;\enclose{phasorangle}{45^\circ}
$$ $$
::: wobei man in der Regel den Winkel in Grad notiert.
:::{.content-hidden unless-format="typst"}
```{=typst}
$ z = r angle.acute phi = 3.4 angle.acute 45 degree $
```
:::
where the angle is usually noted in degrees.
:::{.callout-note .titlenormal collapse="true"} :::{.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 a Julia operator. We use `⋖` as an alternative, entered 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} ```{julia}
⋖(r::Real, ϕ::Real) = PComplex(r, π*ϕ/180) ⋖(r::Real, ϕ::Real) = PComplex(r, π*ϕ/180)
z3 = 2. ⋖ 90. z3 = 2. ⋖ 90.
``` ```
(The type annotation `Real` instead of `AbstractFloat` anticipates further constructors. Currently, the operator `⋖` works only with `Float64`.) (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} ```{julia}
using Printf using Printf
function Base.show(io::IO, z::PComplex) function Base.show(io::IO, z::PComplex)
# print phase in degrees, rounded to one decimal place # wir drucken die Phase in Grad, auf Zehntelgrad gerundet,
p = z.ϕ * 180/π p = z.ϕ * 180/π
sp = @sprintf "%.1f" p sp = @sprintf "%.1f" p
print(io, z.r, "⋖", sp, '°') print(io, z.r, "⋖", sp, '°')
@@ -169,22 +151,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`, additional functionality is required: arithmetic operations, comparison operators, and conversions must all 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 focus on multiplication and square root operations. Wir beschränken uns auf Multiplikation und Quadratwurzeln.
:::{.callout-note collapse="false"} :::{.callout-note collapse="true"}
## Modules ## Module
- Adding methods to existing functions requires using their fully qualified names. - Um die `methods` der existierenden Funktionen und Operationen zu ergänzen, muss man diese mit ihrem 'vollen Namen' ansprechen.
- All objects belong to a namespace or `module`. - Alle Objekte gehören zu einem Namensraum oder `module`.
- Most basic functions belong to `Base`, which is loaded automatically. - Die meisten Basisfunktionen gehören zum Modul `Base`, welches standardmäßig immer ohne explizites `using ...` geladen wird.
- Without user-defined modules, definitions reside in `Main`. - Solange man keine eigenen Module definiert, sind die eigenen Definitionen im Modul `Main`.
- The macro `@which` applied to a name shows its defining module. - Das Macro `@which`, angewendet auf einen Namen, zeigt an, in welchem Modul der Name definiert wurde.
```{julia} ```{julia}
f(x) = 3x^3 f(x) = 3x^3
@@ -194,13 +176,13 @@ f(x) = 3x^3
```{julia} ```{julia}
wp = @which + wp = @which +
ws = @which(sqrt) ws = @which(sqrt)
println("Module for addition: $wp, Module for sqrt: $ws") println("Modul für Addition: $wp, Modul für sqrt: $ws")
``` ```
::: :::
```{julia} ```{julia}
sqrt_polar(z::PComplex) = PComplex(sqrt(z.r), z.ϕ / 2) qwurzel(z::PComplex) = PComplex(sqrt(z.r), z.ϕ / 2)
``` ```
```{julia} ```{julia}
@@ -208,7 +190,7 @@ sqrt_polar(z::PComplex) = PComplex(sqrt(z.r), z.ϕ / 2)
#| output: false #| output: false
#= #=
to make length(methods(sqrt)) work damit das length(methods(sqrt)) klappt
=# =#
if hasmethod(sqrt, (PComplex,)) if hasmethod(sqrt, (PComplex,))
zz = @which Base.sqrt(PComplex{Float64}(1.,1.)) zz = @which Base.sqrt(PComplex{Float64}(1.,1.))
@@ -216,14 +198,14 @@ if hasmethod(sqrt, (PComplex,))
end end
``` ```
The function `sqrt()` already has some methods: Die Funktion `sqrt()` hat schon einige Methoden:
```{julia} ```{julia}
length(methods(sqrt)) length(methods(sqrt))
``` ```
Adding one more method: Jetzt wird es eine Methode mehr:
```{julia} ```{julia}
Base.sqrt(z::PComplex) = sqrt_polar(z) Base.sqrt(z::PComplex) = qwurzel(z)
length(methods(sqrt)) length(methods(sqrt))
``` ```
@@ -232,26 +214,26 @@ length(methods(sqrt))
sqrt(z2) sqrt(z2)
``` ```
For multiplication: und nun zur Multiplikation:
```{julia} ```{julia}
Base.:*(x::PComplex, y::PComplex) = PComplex(x.r * y.r, x.ϕ + y.ϕ) Base.:*(x::PComplex, y::PComplex) = PComplex(x.r * y.r, x.ϕ + y.ϕ)
@show z1 * z2; @show z1 * z2;
``` ```
(Since `:` is not a valid identifier character, it must be qualified with `Base.`) (Da das Operatorsymbol kein normaler Name ist, muss der Doppelpunkt bei der Zusammensetzung mit `Base.` sein.)
However, multiplication with other numeric types is not yet supported. Many corresponding methods could be defined, but Julia provides another mechanism for *numeric types* that simplifies this: 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
Julia supports freely mixing various numeric types: In Julia kann man bekanntlich die verschiedensten numerischen Typen nebeneinander verwenden.
```{julia} ```{julia}
1//3 + 5 + 5.2 + 0xff 1//3 + 5 + 5.2 + 0xff
``` ```
Among the numerous methods defined for `+` and `*`, we find a 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 ```julia
+(x::Number, y::Number) = +(promote(x,y)...) +(x::Number, y::Number) = +(promote(x,y)...)
@@ -260,15 +242,15 @@ Among the numerous methods defined for `+` and `*`, we find a catch-all definiti
(The three dots form the splat operator, which decomposes the tuple returned by `promote()` 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} ```{julia}
promote(12, 34.555, 77/99, 0xff) promote(12, 34.555, 77/99, 0xff)
@@ -279,15 +261,15 @@ z = promote(BigInt(33), 27)
@show z typeof(z); @show z typeof(z);
``` ```
The function `promote()` uses two helpers, the functions Die Funktion `promote()` verwendet dazu zwei Helfer, die Funktionen
`promote_type(T1, T2)` and `convert(T, x)` `promote_type(T1, T2)` und `convert(T, x)`
As usual in Julia, we can extend this mechanism with our own 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 the conversion should take place. Arguments are types, not values. Sie ermittelt, zu welchem Typ umgewandelt werden soll. Argumente sind Typen, nicht Werte.
```{julia} ```{julia}
@show promote_type(Rational{Int64}, ComplexF64, Float32); @show promote_type(Rational{Int64}, ComplexF64, Float32);
@@ -295,10 +277,10 @@ It determines to which type the conversion should take place. Arguments are type
### The Function `convert(T,x)` ### Die Funktion `convert(T,x)`
The methods of Die Methoden von
`convert(T, x)` convert `x` into an object of type `T`. Such a conversion should be lossless. `convert(T, x)` wandeln `x` in ein Objekt vom Typ `T` um. Dabei sollte eine solche Umwandlung verlustfrei möglich sein.
```{julia} ```{julia}
z = convert(Float64, 3) z = convert(Float64, 3)
@@ -312,7 +294,7 @@ z = convert(Int64, 23.00)
z = convert(Int64, 2.3) z = convert(Int64, 2.3)
``` ```
The special role of `convert()` is that it is called implicitly 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?): > [The following language constructs call convert](https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#When-is-convert-called?):
> >
@@ -322,24 +304,24 @@ The special role of `convert()` is that it is called implicitly at various point
- Assigning to a variable with a declared type (e.g. local x::T) converts to that type. - Assigning to a variable with a declared type (e.g. local x::T) converts to that type.
- A function with a declared return type converts its return value to that type. - A function with a declared return type converts its return value to that type.
-- and of course in `promote()` -- und natürlich in `promote()`
For user-defined types, `convert()` can be extended with custom methods. Für selbstdefinierte Datentypen kann man convert() um weitere Methoden ergänzen.
Within the `Number` hierarchy, a generic method handles conversions: Für Datentypen innerhalb der Number-Hierarchie gibt es wieder eine 'catch-all-Definition'
```julia ```julia
convert(::Type{T}, x::Number) where {T<:Number} = T(x) convert(::Type{T}, x::Number) where {T<:Number} = T(x)
``` ```
Therefore: If a type `T<:Number` has a constructor `T(x)` accepting a numeric argument, this constructor is automatically used for conversions. (More specific methods for `convert()` can also be defined and will take 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} ```{julia}
## (a) Arbitrary real types for r and ϕ (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}(r::T1, ϕ::T2) where {T<:AbstractFloat, T1<:Real, T2<: Real} =
PComplex{T}(convert(T, r), convert(T, ϕ)) PComplex{T}(convert(T, r), convert(T, ϕ))
@@ -347,8 +329,8 @@ PComplex{T}(r::T1, ϕ::T2) where {T<:AbstractFloat, T1<:Real, T2<: Real} =
PComplex(r::T1, ϕ::T2) where {T1<:Real, T2<: Real} = PComplex(r::T1, ϕ::T2) where {T1<:Real, T2<: Real} =
PComplex{promote_type(Float64, T1, T2)}(r, ϕ) PComplex{promote_type(Float64, T1, T2)}(r, ϕ)
## (b) For conversion from reals: constructor with ## (b) Zur Umwandlung von Reals: Konstruktor mit
## only one argument r ## nur einem Argument r
PComplex{T}(r::S) where {T<:AbstractFloat, S<:Real} = PComplex{T}(r::S) where {T<:AbstractFloat, S<:Real} =
PComplex{T}(convert(T, r), convert(T, 0)) PComplex{T}(convert(T, r), convert(T, 0))
@@ -356,7 +338,7 @@ PComplex{T}(r::S) where {T<:AbstractFloat, S<:Real} =
PComplex(r::S) where {S<:Real} = PComplex(r::S) where {S<:Real} =
PComplex{promote_type(Float64, S)}(r, 0.0) PComplex{promote_type(Float64, S)}(r, 0.0)
## (c) Conversion Complex -> PComplex ## (c) Umwandlung Complex -> PComplex
PComplex{T}(z::Complex{S}) where {T<:AbstractFloat, S<:Real} = PComplex{T}(z::Complex{S}) where {T<:AbstractFloat, S<:Real} =
PComplex{T}(abs(z), angle(z)) PComplex{T}(abs(z), angle(z))
@@ -367,7 +349,8 @@ PComplex(z::Complex{S}) where {S<:Real} =
``` ```
Testing the new constructors:
Ein Test der neuen Konstruktoren:
```{julia} ```{julia}
@@ -376,9 +359,9 @@ Testing the new constructors:
``` ```
*Promotion rules* are needed to determine the result type of `promote(x::T1, y::T2)`. This mechanism extends `promote_type()` with the necessary 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} ```{julia}
@@ -388,16 +371,15 @@ Base.promote_rule(::Type{PComplex{T}}, ::Type{S}) where {T<:AbstractFloat,S<:Rea
Base.promote_rule(::Type{PComplex{T}}, ::Type{Complex{S}}) where Base.promote_rule(::Type{PComplex{T}}, ::Type{Complex{S}}) where
{T<:AbstractFloat,S<:Real} = PComplex{promote_type(T,S)} {T<:AbstractFloat,S<:Real} = PComplex{promote_type(T,S)}
``` ```
1. **Rule:** 1. Regel:
When a `PComplex{T}` and an `S<:Real` are combined, both convert to `PComplex{U}`, where `U` is the promoted type of `S` and `T`. : 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** 2. Regel
When a `PComplex{T}` and a `Complex{S}` are combined, both convert to `PComplex{U}`, where `U` is the promoted type of `S` and `T`. : 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.
Damit klappt nun die Multiplikation mit beliebigen numerischen Typen.
We can now multiply with arbitrary numeric types:
```{julia} ```{julia}
z3, 3z3 z3, 3z3
@@ -409,10 +391,9 @@ z3, 3z3
:::{.callout-caution icon="false" collapse="true" .titlenormal} :::{.callout-caution icon="false" collapse="true" .titlenormal}
## Summary: our type `PComplex` ## Zusammenfassung: unser Typ `PComplex`
```julia ```julia
struct PComplex{T <: AbstractFloat} <: Number struct PComplex{T <: AbstractFloat} <: Number
@@ -426,7 +407,7 @@ struct PComplex{T <: AbstractFloat} <: Number
end end
if r==0 ϕ=0 end # normalize r=0 case to phi=0 if r==0 ϕ=0 end # normalize r=0 case to phi=0
ϕ = mod(ϕ, 2π) # map phi into interval [0,2pi) ϕ = mod(ϕ, 2π) # map phi into interval [0,2pi)
new(r, ϕ) # new() is special function, new(r, ϕ) # new() ist special function,
end # available only inside inner constructors end # available only inside inner constructors
end end
@@ -462,7 +443,7 @@ PComplex(z::Complex{S}) where {S<:Real} =
using Printf using Printf
function Base.show(io::IO, z::PComplex) function Base.show(io::IO, z::PComplex)
# print phase in degrees, rounded to one decimal place # wir drucken die Phase in Grad, auf Zehntelgrad gerundet,
p = z.ϕ * 180/π p = z.ϕ * 180/π
sp = @sprintf "%.1f" p sp = @sprintf "%.1f" p
print(io, z.r, "⋖", sp, '°') print(io, z.r, "⋖", sp, '°')
@@ -484,7 +465,7 @@ Base.promote_rule(::Type{PComplex{T}}, ::Type{Complex{S}}) where
:::{.content-hidden unless-format="xxx"} :::{.content-hidden unless-format="xxx"}
`PComplex(1, 0)` is not yet supported. Other real types for `r` and `ϕ` should also be supported. For simplicity, all types are converted to `Float64`. Analogous handling applies for single real or complex arguments. 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 ```julia
PComplex(r::Real, ϕ::Real) = PComplex(Float64(r), Float64(ϕ)) PComplex(r::Real, ϕ::Real) = PComplex(Float64(r), Float64(ϕ))

View File

@@ -1,7 +1,5 @@
--- ---
engine: julia engine: julia
julia:
exeflags: ["--color=yes"]
--- ---
```{julia} ```{julia}
@@ -11,68 +9,67 @@ julia:
using InteractiveUtils 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 `!`. - Namen können Buchstaben, Ziffern, den Unterstrich `_` und das Ausrufezeichen `!` enthalten.
- The first character must be a letter or an underscore. - Das erste Zeichen muss ein Buchstabe oder ein Unterstrich sein.
- Case is significant: `Nmax` and `NMAX` are different variables. - Groß- und Kleinbuchstaben werden unterschieden: `Nmax` und `NMAX` sind verschiedene Variablen.
- The character set used is [Unicode](https://home.unicode.org/), which covers over 150 scripts and numerous symbols. - Als Zeichensatz wird [Unicode](https://home.unicode.org/) verwendet. Damit stehen über 150 Schriften und zahlreiche Symbole zur Verfügung.
- There is a short [list of reserved keywords](https://docs.julialang.org/en/v1/base/base/#Keywords): `if, then, function, true, false,...` - 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} :::{.callout-tip}
## Example ## Beispiel
Permissible: `i, x, Ω, x2, TheUnknownNumber, new_Value, 🎷, Counter_2, лічильник, yes!!!!,...` zulässig: `i, x, Ω, x2, DieUnbekannteZahl, neuer_Wert, 🎷, Zähler, лічильник, einself!!!!,...`
Impermissible: `Karen'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 } :::{.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()`. Neben den *reserved keywords* der Kernsprache sind zahlreiche weitere Funktionen und Objekte vordefiniert, wie z.B. die mathematischen Funktionen `sqrt(), log(), sin()`.
These definitions are found in the `Base` module, which Julia loads automatically on startup. Diese Definitionen finden sich in dem Modul `Base`, welches Julia beim Start automatisch lädt.
Names from `Base` can be redefined as long as they have not yet been used: Namen aus `Base` können umdefiniert werden, solange sie noch nicht verwendet wurden:
```{julia} ```{julia}
#| error: true #| error: true
log = 3 log = 3
1 + log 1 + log
``` ```
Now, of course, `log()` no longer works: Jetzt ist natürlich der Logarithmus kaputt:
```{julia} ```{julia}
#| error: true #| error: true
x = log(10) 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
- Usually, each line contains one statement. - Im Normalfall enthält eine Zeile eine Anweisung.
- If a statement is recognizable as incomplete at the end of a line through - Wenn eine Anweisung am Zeilenende als unvollständig erkennbar ist durch
- open parentheses - offene Klammern
- operators, - Operationszeichen,
then the next line is regarded as a continuation. dann wird die nächste Zeile als Fortsetzung aufgefasst.
- Multiple statements per line can be separated by semicolons. - Mehrere Anweisungen pro Zeile können durch Semikolon getrennt werden.
- In interactive mode (REPL or notebook), a semicolon after the last statement suppresses the output of the result of that statement. - Im interaktiven Betrieb (REPL oder Notebook) unterdrückt ein Semikolon nach der letzten Anweisung die Ausgabe des Ergebnisses dieser Anweisung.
:::{.callout-tip} :::{.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} ```{julia}
println("Hallo 🌍!") println("Hallo 🌍!")
x = sum([i^2 for i=1:10]) x = sum([i^2 for i=1:10])
``` ```
Das Semikolon unterdrückt das:
The semicolon suppresses this:
```{julia} ```{julia}
println("Hallo 🌍!") println("Hallo 🌍!")
x = sum([i^2 for i=1:10]); x = sum([i^2 for i=1:10]);
@@ -84,14 +81,14 @@ x = sum([i^2 for i=1:10]);
:::{.callout-warning } :::{.callout-warning }
For multi-line statements, a continued line should end with an open operator or parenthesis. Bei mehrzeiligen Anweisungen muss die fortzusetzende Zeile mit einer offenen Operation oder Klammer enden:
```{julia} ```{julia}
x = sin(π/2) + x = sin(π/2) +
3 * cos(0) 3 * cos(0)
``` ```
Therefore, the following fails, but—unfortunately—**without an error message**! Also geht das Folgende schief, aber leider **ohne eine Fehlermeldung**!
```{julia} ```{julia}
#| error: true #| error: true
#| warning: true #| warning: true
@@ -99,9 +96,9 @@ x = sin(π/2)
+ 3 * cos(0) + 3 * cos(0)
println(x) 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} ```{julia}
x = ( sin(π/2) x = ( sin(π/2)
+ 3 * cos(0) ) + 3 * cos(0) )
@@ -110,41 +107,43 @@ println(x)
::: :::
## Comments ## Kommentare
Julia knows two types of comments in program text: Julia kennt 2 Arten von Kommentaren im Programmtext:
```{julia} ```{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} ```{julia}
#= #=
Single and multi-line comments can be enclosed in `#= ... =#`. Nested comments are possible. Ein- und mehrzeilige Kommentare können zwischen #= ... =# eingeschlossen werden.
`#=` Dabei sind verschachtelte Kommentare möglich.
i.e., unlike in C/C++/Java, the comment does not end with the first comment-end character, but the `#=...=#` pairs act like parentheses. #=
`=#` d.h., anders als in C/C++/Java endet der Kommentar nicht mit dem ersten
The automatic 'syntax highlighter' doesn't support this yet, as the alternating Kommentar-Endezeichen, sondern die #=...=# - Paare wirken wie Klammern.
gray shading of this comment shows. =#
Der automatische 'syntax highlighter' weiss das leider noch nicht, wie die wechselnde
Graufärbung dieses Kommentars zeigt.
=# =#
x #= this is a really rare name for a variable! =# = 3 x #= das ist ein seltener Variablenname! =# = 3
``` ```
## Data Types Part I ## Datentypen Teil I
- Julia is a [strongly typed](https://en.wikipedia.org/wiki/Type_safety#Strong_and_weak_typing) language. All objects have a type. Functions and operations expect arguments of the correct type. - Julia ist eine [stark typisierte](https://de.wikipedia.org/wiki/Starke_Typisierung) Sprache. Alle Objekte haben einen Typ. Funktionen/Operationen erwarten Argumente mit dem richtigen Typ.
- Julia is a [dynamically typed](https://en.wikipedia.org/wiki/Dynamic_programming_language) language. Variables have no type. They are names that can be bound to objects via assignment `x = ...`. - 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.
- When speaking of the "type of a variable", one means the type of the object currently assigned to the variable. - Wenn man vom „Typ einer Variablen“ spricht, meint man den Typ des Objektes, das der Variablen gerade zugewiesen ist.
- Functions and operators can implement different *methods* for different argument types. - Funktionen/Operatoren können verschiedene *methods* für verschiedene Argumenttypen implementieren.
- Depending on the concrete argument types, it is decided at call time which method is selected ([*dynamic dispatch*](https://en.wikipedia.org/wiki/Dynamic_dispatch)). - 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 Int64, Float64, String, Char, Bool
@@ -162,7 +161,7 @@ x, typeof(x), sizeof(x)
``` ```
```{julia} ```{julia}
x = "Hello!" x = "Hallo!"
x, typeof(x), sizeof(x) x, typeof(x), sizeof(x)
``` ```
@@ -177,58 +176,58 @@ x = 3 > π
x, typeof(x), sizeof(x) x, typeof(x), sizeof(x)
``` ```
- `sizeof()` returns the size of an object or type in bytes (1 byte = 8 bits) - `sizeof()` liefert die Größe eines Objekts oder Typs in Bytes (1 Byte = 8 Bit)
- 64-bit integers and 64-bit floating-point numbers correspond to the instruction set of modern processors and are therefore the standard numeric types. - 64bit Ganzzahlen und 64bit Gleitkommazahlen entsprechen dem Befehlssatz moderner Prozessoren und sind daher die numerischen Standardtypen.
- Character literals like `'A'` and single-character strings like `"A"` are different objects. - 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. - Ein `if`-Block *kann* **beliebig viele** `elseif`-Zweige und als letztes maximal **einen** `else`-Zweig enthalten.
- The block has a value: the value of the last executed statement. - Der Block hat einen Wert, den Wert der letzten ausgeführten Anweisung.
```{julia} ```{julia}
x = 33 x = 33
y = 44 y = 44
z = 34 z = 34
if x < y && z != x # elseif or else branches are optional if x < y && z != x # elseif- und else-Blöcke sind optional
println("yes") println("yes")
x += 10 x += 10
elseif x < z # any number of elseif branches elseif x < z # beliebig viele elseif-Blöcke
println(" x is smaller than z") println(" x is smaller than z")
elseif x == z+1 elseif x == z+1
println(" x is successor of z") println(" x is successor of z")
else # at most one else block else # maximal ein else-Block
println("All wrong") println("Alles falsch")
end # value of the entire block is the value of the end # Wert des gesamten Blocks ist der Wert der
# last evaluated statement # letzten ausgeführten Auswertung
``` ```
Short blocks can be written on one line: Kurze Blöcke kann man in eine Zeile schreiben:
```{julia} ```{julia}
if x > 10 println("x is larger than 10") end if x > 10 println("x is larger than 10") end
``` ```
The value of an `if` block can be assigned: Der Wert eines `if`-Blocks kann natürlich zugewiesen werden:
```{julia} ```{julia}
y = 33 y = 33
z = if y > 10 z = if y > 10
println("y is larger than 10") println("y is larger than 10")
y += 1 y += 1
end end
z z
``` ```
### Conditional Operator (ternary operator) `test ? exp1 : exp2` ### Auswahloperator (ternary operator) `test ? exp1 : exp2`
```{julia} ```{julia}
x = 20 x = 20
y = 15 y = 15
z = x < y ? x+1 : y+1 z = x < y ? x+1 : y+1
``` ```
is equivalent to ist äquivalent zu
```{julia} ```{julia}
z = if x < y z = if x < y
@@ -238,9 +237,9 @@ z = if x < y
end end
``` ```
## Comparisons, Tests, Logical Operations ## Vergleiche, Tests, Logische Operationen
### Arithmetic Comparisons ### Arithmetische Vergleiche
- `==` - `==`
- `!=`, `≠` - `!=`, `≠`
@@ -249,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} ```{julia}
"Aachen" < "Leipzig", 10 ≤ 10.01, [3,4,5] < [3,6,2] "Aachen" < "Leipzig", 10 ≤ 10.01, [3,4,5] < [3,6,2]
``` ```
Well, almost anything: Nun ja, fast alles:
```{julia} ```{julia}
3 < "four" 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)`. - Operatoren sind auch nur Funktionen: `x < y` wird zum Funktionsaufruf `isless(x, y)`.
- Functions (and thus operators) can implement different *methods* for different argument types. - Funktionen (und damit Operatoren) können verschiedene *methods* für verschiedene Argumenttypen implementieren.
- 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)). - 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} ```{julia}
methods(<) methods(<)
``` ```
Finally: comparisons can be chained. Zuletzt noch: Vergleiche können gekettet werden.
```{julia} ```{julia}
10 < x ≤ 100 # this is equivalent to 10 < x ≤ 100 # das ist äquivalent zu
# 10 < x && x ≤ 100 # 10 < x && x ≤ 100
``` ```
### Tests ### Tests
Some functions of type `f(c::Char) -> Bool` Einge Funktionen vom Typ `f(c::Char) -> Bool`
```{julia} ```{julia}
isnumeric('a'), isnumeric('7'), isletter('a') 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} ```{julia}
contains("Lampenschirm", "pensch"), startswith("Lampenschirm", "Lamb"), endswith("Lampenschirm", "rm") contains("Lampenschirm", "pensch"), startswith("Lampenschirm", "Lamb"), endswith("Lampenschirm", "rm")
``` ```
- The function `in(item, collection) -> Bool` tests whether `item` is in `collection`. - Die Funktion `in(item, collection) -> Bool` testet, ob `item` in `collection` ist.
- It also has the alias ` ∈(item, collection)` and - Sie hat auch das Alias ` ∈(item, collection)` und
- both `in` and `∈` can also be written as infix operators. - sowohl `in` als auch `∈` können auch als Infix-Operatoren geschrieben werden.
```{julia} ```{julia}
x = 3 x = 3
@@ -308,24 +307,23 @@ x in [1, 2, 3, 4, 5]
x ∈ [1, 2, 33, 4, 5] x ∈ [1, 2, 33, 4, 5]
``` ```
### Logical Operations: `&&`, `||`, `!` ### Logische Operationen: `&&`, `||`, `!`
```{julia} ```{julia}
3 < 4 && !(2 > 8) && !contains("aaa", "b") 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` wird `b` nur ausgewertet, wenn `a == true`
- In `a || b`, `b` is only evaluated if `a == false` - 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`. (ii) Damit kann `if !test statement end` als `test || statement` geschrieben werden.
As an example^[from the [Julia documentation](https://docs.julialang.org/en/v1/manual/control-flow/#Short-Circuit-Evaluation)] here is an implementation of the factorial function:
Als Beispiel^[aus der [Julia-Dokumentation](https://docs.julialang.org/en/v1/manual/control-flow/#Short-Circuit-Evaluation)] hier eine Implementierung der Fakultätsfunktion *(factorial)*:
```{julia} ```{julia}
function fact(n::Int) function fact(n::Int)
n >= 0 || error("n must be non-negative") n >= 0 || error("n must be non-negative")
@@ -338,23 +336,23 @@ fact(5)
Of course, all these tests can also be assigned to variables of type `Bool` and Natürlich kann man alle diese Tests auch Variablen vom Typ `Bool` zuordnen und
these variables can be used as tests in `if` and `while` blocks: diese Variablen können als Tests in `if`- und `while`-Blöcken verwendet werden:
```{julia} ```{julia}
x = 3 < 4 x = 3 < 4
y = 5 ∈ [1, 2, 5, 7] y = 5 ∈ [1, 2, 5, 7]
z = x && y z = x && y
if z # 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("All correct!") println("Stimmt alles!")
end end
``` ```
- In Julia, all tests in a logical expression must be of type `Bool`. - In Julia müssen alle Tests in einem logischen Ausdruck vom Typ `Bool` sein.
- There is no implicit conversion such as *"0 is false and 1 (or anything != 0) is true"* - Es gibt keine implizite Konvertierung à la *"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`. - Wenn `x` ein numerischer Typ ist, dann muss daher das C-Idiom `if(x)` als `if x != 0` geschrieben werden.
- There is an exception to support the _short circuit evaluation_: - Es gibt eine Ausnahme zur Unterstützung der _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`: - 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} ```{julia}
@@ -367,9 +365,9 @@ z = 3 < 4 && 10 < 50 && sqrt(3^3)
z, typeof(z) z, typeof(z)
``` ```
## Loops ## Schleifen *(loops)*
### The `while` loop ### Die `while` ("solange")-Schleife
Syntax: Syntax:
@@ -378,19 +376,19 @@ while *condition*
*loop body* *loop body*
end 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} ```{julia}
i = 1 # typically the test of the i = 1 # typischerweise braucht der Test der
# while loop needs preparation ... # while-Schleife eine Vorbereitung ...
while i < 10 while i < 10
println(i) println(i)
i += 2 # ... and an update i += 2 # ... und ein update
end 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} ```{julia}
i = 0 i = 0
@@ -398,20 +396,20 @@ while i<10
i += 1 i += 1
if i == 3 if i == 3
continue # start next iteration immediately, continue # beginne sofort nächsten Durchlauf,
end # skip rest of loop body end # überspringe Rest des Schleifenkörpers
println("i = $i") println("i = $i")
if i ≥ 5 if i ≥ 5
break # break loop break # breche Schleife ab
end end
end end
println("Done!") println("Fertig!")
``` ```
With `break` one can also exit infinite loops: Mit `break` kann man auch Endlosschleifen verlassen:
```{julia} ```{julia}
i = 1 i = 1
@@ -423,7 +421,7 @@ while true
end end
``` ```
### `for` Loops ### `for`-Schleifen
Syntax: Syntax:
@@ -433,24 +431,24 @@ for *var* in *iterable container*
end 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} ```{julia}
for i ∈ ["Mother", "Father", "Daughter"] for i ∈ ["Mutter", "Vater", "Tochter"]
println(i) println(i)
end end
``` ```
A numerical loop counter is often needed. For this purpose, we have the `range` construct. The simplest forms are Oft benötigt man einen numerischen Schleifenzähler. Dafür gibt es das *range*-Konstrukt. Die einfachsten Formen sind
`Start:End` and `Start:Step:End`. `Start:Ende` und `Start:Schrittweite:Ende`.
```{julia} ```{julia}
end_value = 5 endwert = 5
for i ∈ 1:end_value for i ∈ 1:endwert
println(i^2) println(i^2)
end end
``` ```
@@ -471,8 +469,9 @@ for k = 14 : -2.5 : 1 print(" $k") end
#### Nested Loops #### Geschachtelte Schleifen _(nested loops)_
A `break` ends the innermost loop.
Ein `break` beendet die innerste Schleife.
```{julia} ```{julia}
for i = 1:3 for i = 1:3
@@ -485,22 +484,22 @@ for i = 1:3
end 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} ```{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) ) println( (i,j) )
if j == 2 if j == 2
break # break ends the entire loop here break # break bricht hier die Gesamtschleife ab
end end
end end
``` ```
:::{.callout-important .titlenormalxx} :::{.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} ```{julia}
@@ -513,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:
```{.julia} ```
i = 1 i = 1
while i<5 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 i += 1
end end
``` ```
@@ -525,96 +524,100 @@ end
## Unicode ## Unicode
Julia uses Unicode as its character set. This allows identifiers in non-Latin scripts (e.g., Cyrillic, Korean, Sanskrit, runes, Julia verwendet Unicode als Zeichensatz. Damit können für Variablen, Funktionen etc auch Bezeichner aus nicht-lateinischen Schriften (zB Kyrillisch, Koreanisch, Sanskrit, Runen,
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. 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. - über 3000 Unicode-Zeichen können in Julia in einer LaTeX-ähnlichen Weise mit der Tab-Vervollständigung eingegeben werden.
- `\alpha<TAB>` becomes `α`, - `\alpha<TAB>` wird zu `α`,
- `\euler<TAB>` becomes `` (Euler's number `exp(1)`, [special script e, `U+0212F`](https://www.htmlsymbol.com/unicode-code/212f.html)) - `\euler<TAB>` wird zu `` (Eulersche Zahl `exp(1)`, [spezielles Schreibschrift-e, `U+0212F`](https://www.htmlsymbol.com/unicode-code/212f.html))
- `\le<TAB>` becomes `≤`, - `\le<TAB>` wird zu `≤`,
- `\in<TAB>` becomes `∈`, - `\in<TAB>` wird zu `∈`,
- `\:rainbow:<TAB>` becomes `🌈` - `\:rainbow:<TAB>` wird zu `🌈`
[Here is the list.](https://docs.julialang.org/en/v1/manual/unicode-input/) [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 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} ```{julia}
e = 7 e = 7
3e 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} ```{julia}
3e+2 3e+2
``` ```
A space creates clarity: Ein Leerzeichen schafft Eindeutigkeit:
```{julia} ```{julia}
3e + 2 3e + 2
``` ```
This works: Das funktioniert:
```{julia} ```{julia}
x = 4 x = 4
3x + 3 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} ```{julia}
3y + 0x 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} ```{julia}
Important = 21 Wichtig = 21
Important! = 42 # identifiers can also contain ! Wichtig! = 42 # Bezeichner können auch ein ! enthalten
(Important, Important!) (Wichtig, Wichtig!)
``` ```
```{julia} ```{julia}
Important!=88 Wichtig!=88
``` ```
Julia interprets this as the *comparison* `Important != 88`. Julia interpretiert das als Vergleich `Wichtig != 88`.
Leerzeichen helfen:
Again, spaces around operators help:
```{julia} ```{julia}
Important! = 88 Wichtig! = 88
Important! 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} ```{julia}
1.+2. 1.+2.
``` ```
Again, spaces create clarity! Wieder gilt: Leerzeichen schaffen Klarheit!
```{julia} ```{julia}
1. + 2. 1. + 2.
``` ```

View File

@@ -8,42 +8,29 @@ engine: julia
#| echo: false #| echo: false
#| output: false #| output: false
using InteractiveUtils using InteractiveUtils
import QuartoNotebookWorker
#struct M a::Int end; x = M(22); @show x Base.stdout = QuartoNotebookWorker.with_context(stdout)
#should not print "Main.Notebook.M(22)" but only "M(22)" myactive_module() = Main.Notebook
function Base.show(io::IO, x::T) where T Base.active_module() = myactive_module()
if parentmodule(T) == @__MODULE__
# Print "TypeName(fields...)" without module prefix
print(io, nameof(T), "(")
fields = fieldnames(T)
for (i, f) in enumerate(fields)
print(io, getfield(x, f))
i < length(fields) && print(io, ", ")
end
print(io, ")")
else
invoke(Base.show, Tuple{IO, Any}, io, x)
end
end
``` ```
# 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 designed to simplify users' work. 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, for a deeper understanding we will now examine the underlying type system. 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. `subtypes()` displays all child nodes, while `supertype()` shows the parent. 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} ```{julia}
subtypes(Int64) subtypes(Int64)
``` ```
The result is an empty list of types. `Int64` is a so-called **concrete type** with no subtypes. Das Ergebnis ist eine leere Liste von Typen. `Int64` ist ein sogenannter **konkreter Typ** und hat keine Untertypen.
Let's now traverse this branch upward to the root (in computer science, trees are typically inverted). Wir klettern jetzt mal die Typhierarchie auf diesem Ast nach oben bis zur Wurzel (Informatiker-Bäume stehen bekanntlich immer auf dem Kopf).
```{julia} ```{julia}
supertype(Int64) supertype(Int64)
``` ```
@@ -59,69 +46,72 @@ supertype(Real)
```{julia} ```{julia}
supertype(Number) 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} ```{julia}
supertypes(Int64) supertypes(Int64)
``` ```
We can now examine the nodes: Nun kann man sich die Knoten angucken:
{{< embed ../notebooks/nb-types.ipynb#nb3 >}} {{< embed ../notebooks/nb-types.ipynb#nb3 >}}
A simple recursive function can display the entire subtree: Mit einer kleinen rekursiven Funktion kann man schnell einen ganzen (Unter-)Baum ausdrucken:
{{< embed ../notebooks/nb-types.ipynb#nb1 >}} {{< embed ../notebooks/nb-types.ipynb#nb1 >}}
::::{.content-hidden unless-format="xxx"} ::::{.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 >}} {{< embed ../notebooks/nb-types.ipynb#nb2 >}}
:::: :::
Below is the same hierarchy 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"} ::: {.content-visible when-format="html"}
![](../images/TypeTree2.png){width=80%} ![](../images/TypeTree2.png){width=80%}
::: :::
::: {.content-visible when-format="typst"} ::: {.content-visible when-format="pdf"}
![The hierarchy of numeric types](../images/TypeTree2.png){width=60%} ![Die Hierarchie der numerischen Typen](../images/TypeTree2.png){width=60%}
::: :::
Beyond numeric types, Julia includes many others. 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} ```{julia}
length(subtypes(Any)) length(subtypes(Any))
``` ```
This number increases with (almost) every package loaded via `using ...`. 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. ## Abstrakte und Konkrete Typen
- Concrete types have no more subtypes, they are always the "leaves" of the tree.
- Concrete types specify a concrete data structure. - 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} :::{.xxx}
::: :::
- Abstract types cannot be instantiated; that is, no objects can have an abstract type directly. - Abstrakte Typen können nicht instanziiert werden, d.h., es gibt keine Objekte mit diesem Typ.
- They define a set of concrete types and common methods for these types. - Sie definieren eine Menge von konkreten Typen und gemeinsame Methoden für diese Typen.
- They can therefore be used in the definition of function types, argument types, element types of composite types, etc. - Sie können daher in der Definition von Funktionstypen, Argumenttypen, Elementtypen von zusammengesetzten Typen u.ä. verwendet werden.
To **declare** *and* **test** the relationships in the type hierarchy, Julia provides a special operator:
Zum **Deklarieren** *und* **Testen** der "Abstammung" innerhalb der Typhierarchie gibt es einen eigenen Operator:
```{julia} ```{julia}
Int64 <: Number 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 reads as the question `is x 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} ```{julia}
x = 17.2 x = 17.2
@@ -130,7 +120,7 @@ x = 17.2
``` ```
Since abstract types do not define data structures, they are simple to define. 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} ```{julia}
abstract type MySuperType end abstract type MySuperType end
@@ -138,7 +128,7 @@ abstract type MySuperType end
supertype(MySuperType) supertype(MySuperType)
``` ```
or from another abstract type: oder von einem anderen abstrakten Typ:
```{julia} ```{julia}
abstract type MySpecialNumber <: Integer end abstract type MySpecialNumber <: Integer end
@@ -146,24 +136,24 @@ abstract type MySpecialNumber <: Integer end
supertypes(MySpecialNumber) supertypes(MySpecialNumber)
``` ```
By this definition, the abstract type is attached at a specific 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`
Though appearing in the numeric type tree, these types warrant brief explanation: Da sie im Baum der numerischen Typen zu sehen sind, seien sie kurz erklärt:
`Bool` is numeric in the sense that `true=1, false=0`: `Bool` ist numerisch im Sinne von `true=1, false=0`:
```{julia} ```{julia}
true + true + true, false - true, sqrt(true), true/4 true + true + true, false - true, sqrt(true), true/4
``` ```
`Irrational` is the type of certain predefined constants, such as `π` and ``. `Irrational` ist der Typ einiger vordefinierter Konstanten wie `π` und ``.
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".* 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
When the tree structure is insufficient, abstract types can be defined 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} ```{julia}
IntOrString = Union{Int64,String} IntOrString = Union{Int64,String}
@@ -171,17 +161,17 @@ IntOrString = Union{Int64,String}
:::{.callout-note .titlenormal} :::{.callout-note .titlenormal}
## Example ## Beispiel
The command `methods(<)` reveals over 70 methods for the comparison operator, including methods with union type arguments, such as: 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 ```julia
<(x::Union{Float16, Float32, Float64}, y::BigFloat) <(x::Union{Float16, Float32, Float64}, y::BigFloat)
``` ```
a method comparing fixed-width machine numbers with arbitrary precision numbers. eine Methode für den Vergleich einer Maschinenzahl fester Länge mit einer Maschinenzahl beliebiger Länge.
::: :::
## Composite Types: `struct` ## Zusammengesetzte (_composite_) Typen: `struct`
A `struct` defines a concrete type as a collection of named fields. Eine `struct` ist eine Zusammenstellung von mehreren benannten Feldern und definiert einen konkreten Typ.
```{julia} ```{julia}
abstract type Point end abstract type Point end
@@ -198,7 +188,7 @@ mutable struct Point3D <: Point
end end
``` ```
As seen with expressions like `x = Int8(33)`, type names can serve as constructors: Wie wir schon bei Ausdrücken der Form `x = Int8(33)` gesehen haben, kann man Typnamen direkt als Konstruktoren einsetzen:
```{julia} ```{julia}
p1 = Point2D(1.4, 3.5) p1 = Point2D(1.4, 3.5)
@@ -210,20 +200,20 @@ p1 isa Point3D, p1 isa Point2D, p1 isa Point
``` ```
The fields of a `struct` are accessed by name using the `.` operator. Die Felder einer `struct` können über ihren Namen mit dem `.`-Operator adressiert werden.
```{julia} ```{julia}
p1.y p1.y
``` ```
Because 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} ```{julia}
p1.x = 3333.4 p1.x = 3333.4
p1 p1
``` ```
The `dump()` function displays structure information for types and objects. Informationen über den Aufbau eines Typs oder eines Objekts von diesem Typ liefert `dump()`.
```{julia} ```{julia}
dump(Point3D) dump(Point3D)
@@ -234,27 +224,28 @@ dump(Point3D)
dump(p1) dump(p1)
``` ```
## Functions and *Multiple Dispatch* ## Funktionen und *Multiple dispatch*
:::{.callout-note .titlenormal} :::{.callout-note .titlenormal}
## Objects, Functions, and Methods ## Objekte, Funktionen, Methoden
In classical object-oriented languages (C++, Java, Python), methods are bound to objects. In klassischen objektorientierten Sprachen wie C++/Java haben Objekte üblicherweise mit ihnen assoziierte Funktionen, die Methoden des Objekts.
Julia takes a different approach: methods belong to functions, not to objects. In Julia gehören Methoden zu einer Funktion und nicht zu einem Objekt.
Constructors (functions sharing a type's name that create instances of that type) are the only exception. (Eine Ausnahme sind die Konstruktoren, also Funktionen, die genauso heißen wie ein Typ und ein Objekt dieses Typs erzeugen.)
When we define a new type, we can define functions specific to that type but we can also add additional methods to existing functions. Sobald man einen neuen Typ definiert hat, kann man sowohl neue als auch bestehende Funktionen um neue Methoden für diesen Typ ergänzen.
- 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.
- A single functions can have multiple methods for different argument types.
- At call time, Julia selects the most specific method matching the concrete argument types *(multiple dispatch)*.
- Core functions in Julia often have numerous predefined methods and third-party packages or user code can extend them adding additional methods.
::: :::
We define a distance function with two methods: Den Abstand zwischen zwei Punkten implementieren wir als Funktion mit zwei Methoden:
```{julia} ```{julia}
function distance(p1::Point2D, p2::Point2D) function distance(p1::Point2D, p2::Point2D)
@@ -265,95 +256,97 @@ function distance(p1::Point3D, p2::Point3D)
sqrt((p1.x-p2.x)^2 + (p1.y-p2.y)^2 + (p1.z-p2.z)^2) sqrt((p1.x-p2.x)^2 + (p1.y-p2.y)^2 + (p1.z-p2.z)^2)
end end
``` ```
```{julia} ```{julia}
distance(p1, Point2D(2200, -300)) distance(p1, Point2D(2200, -300))
``` ```
As mentioned earlier, `methods()` shows the method table of a function: Wie schon erwähnt, zeigt `methods()` die Methodentabelle einer Funktion an:
```{julia} ```{julia}
methods(distance) methods(distance)
``` ```
The `@which` macro, applied to a function call with concrete arguments, shows which method is selected for these arguments: Das Macro `@which`, angewendet auf einen vollen Funktionsaufruf mmit konkreter Argumentliste, zeigt an, welche Methode zu diesen konkreten Argumenten ausgewählt wird:
```{julia} ```{julia}
@which sqrt(3.3) @which sqrt(3.3)
``` ```
```{julia} ```{julia}
z = "Hello" * '!' z = "Hallo" * '!'
println(z) println(z)
@which "Hello" * '!' @which "Hallo" * '!'
``` ```
Methods can also have abstract types as arguments: Methoden können auch abstrakte Typen als Argument haben:
```{julia} ```{julia}
""" """
Calculate the angle ϕ (in degrees) of the polar coordinates (2D) or Berechnet den Winkel ϕ (in Grad) der Polarkoordinaten (2D) bzw.
spherical coordinates (3D) of a point Kugelkoordinaten (3D) eines Punktes
""" """
function phi_angle(p::Point) function phi_winkel(p::Point)
atand(p.y, p.x) atand(p.y, p.x)
end end
phi_angle(p1) phi_winkel(p1)
``` ```
:::{.callout-tip collapse="true"} :::{.callout-tip collapse="true"}
Text enclosed in *triple quotes* immediately before the function definition Ein in *triple quotes* eingeschlossene Text unmittelbat vor der Funktionsdefinition
is automatically integrated into Julia's help database: wird automatisch in die Hilfe-Datenbank von Julia integriert:
```{julia} ```{julia}
?phi_angle ?phi_winkel
``` ```
::: :::
With *multiple dispatch*, the method is applied that is the most specific among all matching ones. Here is a function with several methods Beim *multiple dispatch* wird die Methode angewendet, die unter allen passenden die spezifischste ist. Hier eine Funktion mit mehreren Methoden
(all but the last written in short [*assignment form*](https://docs.julialang.org/en/v1/manual/functions/#man-functions)): (alle bis auf die letzte in der kurzen [*assignment form*](https://docs.julialang.org/en/v1/manual/functions/#man-functions) geschrieben):
```{julia} ```{julia}
f(x::String, y::Number) = "Args: String + Number" f(x::String, y::Number) = "Args: String + Zahl"
f(x::String, y::Int64) = "Args: String + Int64" f(x::String, y::Int64) = "Args: String + Int64"
f(x::Number, y::Int64) = "Args: Number + Int64" f(x::Number, y::Int64) = "Args: Zahl + Int64"
f(x::Int64, y:: Number) = "Args: Int64 + Number" f(x::Int64, y:: Number) = "Args: Int64 + Zahl"
f(x::Number) = "Arg: a Number" f(x::Number) = "Arg: eine Zahl"
function f(x::Number, y::Number, z::String) function f(x::Number, y::Number, z::String)
return "Arg: 2 × Number + String" return "Arg: 2 x Zahl + String"
end end
``` ```
The first two methods match; the second is chosen as it is more specific (`Int64 <: Number`): Hier passen die ersten beiden Methoden. Gewählt wird die zweite, da sie spezifischer ist, `Int64 <: Number`.
```{julia} ```{julia}
f("Hello", 42) f("Hallo", 42)
``` ```
Ambiguities may arise if methods are defined poorly: Es kann sein, dass diese Vorschrift zu keinem eindeutigen Ergebnis führt, wenn man seine Methoden schlecht gewählt hat.
```{julia} ```{julia}
f(42, 42) 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} ```{julia}
@show Rational(23, 17) 4//16 + 1//3; @show Rational(23, 17) 4//16 + 1//3;
``` ```
- The imaginary unit $\sqrt{-1}$ is denoted `im` - Die imaginäre Einheit $\sqrt{-1}$ heißt `im`
```{julia} ```{julia}
@show Complex(0.4) 23 + 0.5im/(1-2im); @show Complex(0.4) 23 + 0.5im/(1-2im);
``` ```
Like `Point2D`, both `Rational` and `Complex` consist of two fields: numerator and denominator or real and imaginary parts. `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} ```{julia}
x = 2//7 x = 2//7
@@ -374,14 +367,14 @@ y = 1.0 + 2.0im
typeof(y) typeof(y)
``` ```
The concrete types `Rational{Int64}`, `Rational{BigInt}`,..., `Complex{Int64}`, `Complex{Float64}}`,... are subtypes of `Rational` and `Complex`, respectively. Die konkreten Typen `Rational{Int64}`, `Rational{BigInt}`,..., `Complex{Int64}`, `Complex{Float64}}`, ... sind Subtypen von `Rational` bzw. `Complex`.
```{julia} ```{julia}
Rational{BigInt} <: Rational 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} ```{julia}
struct MyComplex{T<:Real} <: Number struct MyComplex{T<:Real} <: Number
@@ -395,19 +388,19 @@ struct MyRational{T<:Integer} <: Real
end end
``` ```
The first definition says: Die erste Definition besagt:
- `MyComplex` has two fields `re` and `im`, both of the same type `T`. - `MyComplex` hat zwei Felder `re` und `im`, beide vom gleichen Typ `T`.
- This type `T` must be a subtype of `Real`. - Dieser Typ `T` muss ein Untertyp von `Real` sein.
- `MyComplex` and all its variants like `MyComplex{Float64}` are subtypes of `Number`. - `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`. - `MyRational` hat zwei Felder `num` und `den`, beide vom gleichen Typ `T`.
- This type `T` must be a subtype of `Integer`. - Dieser Typ `T` muss ein Untertyp von `Integer` sein.
- `MyRational` and its variants are subtypes of `Real`. - `MyRational` und seine Varianten sind Untertypen von `Real`.
Since $\subset$ (or `Rational <: Real` in Julia notation), 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} ```{julia}
z = 3//4 + 5im z = 3//4 + 5im
@@ -416,24 +409,23 @@ dump(z)
Diese Strukturen sind ohne das `mutable`-Attribut definiert, also *immutable*:
These structures are declared without the `mutable` attribute, making them *immutable*:
```{julia} ```{julia}
x = 2.2 + 3.3im x = 2.2 + 3.3im
println("The real part is: $(x.re)") println("Der Realteil ist: $(x.re)")
x.re = 4.4 x.re = 4.4
``` ```
This is standard practice. The object `9` (of type `Int64`) is also immutable. Das ist so üblich. Wir betrachten das Objekt `9` vom Typ `Int64` ja auch als unveränderlich.
The following, of course, still works: Das Folgende geht natürlich trotzdem:
```{julia} ```{julia}
x += 2.2 x += 2.2
``` ```
Here, a new object of type `Complex{Float64}` is created and `x` then references this new object. Hier wird ein neues Objekt vom Typ `Complex{Float64}` erzeugt und `x` zur Referenz auf dieses neue Objekt gemacht.
The type system's flexibility invites experimentation. 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} ```{julia}
struct MyParms{T <: Union{Float64, Tuple{Int64, Int64}}} struct MyParms{T <: Union{Float64, Tuple{Int64, Int64}}}
@@ -449,13 +441,13 @@ p2 = MyParms( (2, 4) )
## Types as Objects ## Typen als Objekte
(1) Types are also objects. Each type is an instance of one of three "meta-types": (1) Typen sind ebenfalls Objekte. Sie sind Objekte einer der drei "Meta-Typen"
- `Union` (union types) - `Union` (Union-Typen)
- `UnionAll` (parametric types) - `UnionAll` (parametrisierte Typen)
- `DataType` (all concrete and other abstract types) - `DataType` (alle konkreten und sonstige abstrakte Typen)
```{julia} ```{julia}
@show 23779 isa Int64 Int64 isa DataType; @show 23779 isa Int64 Int64 isa DataType;
@@ -471,7 +463,7 @@ p2 = MyParms( (2, 4) )
``` ```
These three 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} ```{julia}
subtypes(Type) subtypes(Type)
@@ -479,7 +471,7 @@ subtypes(Type)
----------------- -----------------
(2) Types can be assigned to a variable: (2) Damit können Typen auch einfach Variablen zugewiesen werden:
```{julia} ```{julia}
x3 = Float64 x3 = Float64
@@ -488,13 +480,15 @@ x3 = Float64
:::{.callout-note collapse="true"} :::{.callout-note collapse="true"}
This demonstrates that [Julia's style guidelines](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 conventions, not language-enforced rules. 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.
They should still be followed for readability. Man sollte sie trotzdem einhalten, um den Code lesbar zu halten.
::: :::
Declaring such assignments with `const` creates a *type alias*.
Wenn man solche Zuweisungen mit `const` für dauerhaft erklärt, entsteht ein
*type alias*.
```{julia} ```{julia}
@@ -506,7 +500,7 @@ typeof(z)
-------- --------
(3) Types can be function arguments. (3) Typen können Argumente von Funktionen sein.
```{julia} ```{julia}
@@ -522,100 +516,99 @@ z = myf(43, UInt16, Real)
@show z typeof(z); @show z typeof(z);
``` ```
To define this function with type signatures, we can write Wenn man diese Funktion mit Typsignaturen definieren möchte, kann man natürlich
```julia ```julia
function myf(x, S::Type, T::Type) ... end function myf(x, S::Type, T::Type) ... end
``` ```
However, the (equivalent) special syntax schreiben. Üblicher ist hier die (dazu äquivalente) spezielle Syntax
```julia ```julia
function myf(x, ::Type{S}, ::Type{T}) where {S,T} ... end function myf(x, ::Type{S}, ::Type{T}) where {S,T} ... end
``` ```
is more common. Here we 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 can we 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 ```julia
function myf(x, ::Type{Int64}, ::Type{Int64}) ... end 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 functions with types as arguments. We have already seen `<:(T1, T2)`, `supertype(T)`, `supertypes(T)`, `subtypes(T)`. Other useful operations include `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 used as parameters in 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, such types exist. They are concrete, and objects can be instantiated. Ja, die gibt es; und es sind konkrete Typen, man kann also Objekte von diesem Typ erzeugen.
```{julia} ```{julia}
z5 = Complex{Integer}(2, 0x33) z5 = Complex{Integer}(2, 0x33)
dump(z5) dump(z5)
``` ```
This is a heterogeneous composite type. 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.
Note that Nun gilt zwar
```{julia} ```{julia}
Int64 <: Integer Int64 <: Integer
``` ```
but it does not hold that aber es gilt nicht, dass
```{julia} ```{julia}
Complex{Int64} <: Complex{Integer} 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 theoretical computer science terminology](https://en.wikipedia.org/wiki/Type_variance), **invariant**. 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**.
(If `S<:T` implied `ParamType{S} <: ParamType{T}`, this would be **covariance**.) (Wenn aus `S<:T` folgen würde, dass auch `ParamType{S} <: ParamType{T}` gilt, würde man von **Kovarianz** sprechen.)
## Generic Functions ## Generische Funktionen
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} ```{julia}
function fmm(x, y) function fsinnfrei1(x, y)
return x * x * y return x * x * y
end end
``` ```
This function works with any types supporting the required operations. Diese Funktion funktioniert sofort mit allen Typen, für die die verwendeten Operationen definiert sind.
```{julia} ```{julia}
fmm( Complex(2,3), 10), fmm("Hello", '!') fsinnfrei1( Complex(2,3), 10), fsinnfrei1("Hallo", '!')
``` ```
Man kann natürlich Typ-Annotationen benutzen, um die Verwendbarkeit einzuschränken oder um unterschiedliche Methoden für unterschiedliche Typen zu implementieren:
Type annotations can restrict applicability or implement different methods for different types:
```{julia} ```{julia}
function fmm2(x::Number, y::AbstractFloat) function fsinnfrei2(x::Number, y::AbstractFloat)
return x * x * y return x * x * y
end end
function fmm2(x::String, y::String) function fsinnfrei2(x::String, y::String)
println("Sorry, I don't take strings!") println("Sorry, I don't take strings!")
end end
@show fmm2(18, 2.0) fmm2(18, 2); @show fsinnfrei2(18, 2.0) fsinnfrei2(18, 2);
``` ```
:::{.callout-important} :::{.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 *advantages* 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 seamless integration across packages and support high-level 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} ```{julia}
#| echo: false #| echo: false
@@ -645,7 +638,7 @@ A simple example: The `Measurements.jl` package defines a new data type `Measure
=# =#
using Measurements using Measurements
zz = @which Base.show(stdout, MIME"text/latex"(), 3±2) zz= @which Base.show(stdout, MIME"text/latex"(), 3±2)
Base.delete_method(zz) Base.delete_method(zz)
``` ```
@@ -655,22 +648,22 @@ using Measurements
x = 33.56±0.3 x = 33.56±0.3
y = 2.3±0.02 y = 2.3±0.02
fmm(x, y) 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., an implementation of [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} ```{julia}
#| eval: false #| eval: false
function isprime(x::Complex{Integer}) ... end 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} ```{julia}
#| eval: false #| eval: false
@@ -679,11 +672,11 @@ function isprime(x::Complex{T}) where {T<:Integer}
end 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} ```{julia}
#| eval: false #| eval: false
function kgV(x::Complex{T}, y::Complex{S}) where {T<:Integer, S<:Integer} function kgV(x::Complex{T}, y::Complex{S}) where {T<:Integer, S<:Integer}
@@ -691,11 +684,10 @@ function kgV(x::Complex{T}, y::Complex{S}) where {T<:Integer, S<:Integer}
end end
``` ```
> The arguments x and y can have different types, each a subtype 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 Wenn es nur eine `where`-Klausel wie im vorletzten Beispiel gibt, kann man die geschweiften Klammern weglassen und
write
```{julia} ```{julia}
#| eval: false #| eval: false
@@ -703,7 +695,7 @@ function isprime(x::Complex{T}) where T<:Integer
... ...
end end
``` ```
This can still be shortened to schreiben. Das lässt sich noch weiter kürzen zu
```{julia} ```{julia}
#| eval: false #| eval: false
function isprime(x::Complex{<:Integer}) function isprime(x::Complex{<:Integer})
@@ -711,7 +703,7 @@ function isprime(x::Complex{<:Integer})
end 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} ```{julia}
C1 = Complex{T} where {T<:Integer} C1 = Complex{T} where {T<:Integer}
@@ -721,24 +713,24 @@ C3 = Complex{<:Integer}
C1 == C2 == C3 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.
Finally, note that `where T` is shorthand for `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} ```{julia}
function fgl(x::T, y::T) where T 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 end
``` ```
This method requires that both arguments have exactly the same type; otherwise, any type is accepted. Diese Methode erfordert, dass die Argumente genau den gleichen, aber ansonsten beliebigen Typ haben.
```{julia} ```{julia}
fgl(33, 44) fgl(33, 44)
``` ```
```{julia} ```{julia}
fgl(33, 44.0) fgl(33, 44.0)
``` ```

118
index.qmd
View File

@@ -1,20 +1,12 @@
--- ---
engine: julia engine: julia
julia:
exeflags: ["--color=yes"]
--- ---
# Was ist Julia? {.unnumbered}
# What is Julia? {.unnumbered}
```{=typst} Julia ist eine noch recht junge für *scientific computing* konzipierte moderne Programmiersprache.
#set math.equation(numbering: none)
// Some things need to be here to counter the Typst style
```
Julia is a relatively new, modern programming language designed for *scientific computing*. Ein kleines Codebeispiel:
A code example:
```{julia} ```{julia}
#| error: false #| error: false
@@ -41,28 +33,25 @@ end
f f
``` ```
## History {.unnumbered} ## Geschichte {.unnumbered}
- 2009: Development started at MIT's *Computer Science and Artificial - 2009 Beginn der Entwicklung am *Computer Science and Artificial
Intelligence Laboratory* Intelligence Laboratory* des MIT
- 2012: First release (v0.1) - 2012 erste Release v0.1
- 2018: Version 1.0 released - 2018 Version v1.0
- February 2026: Version 1.12.5 - aktuell: v1.11.4 vom 10. März 2025
Zum ersten Release 2012 haben die Schöpfer von Julia ihre Ziele und Motivation in dem Blogbeitrag [Why we created Julia](https://julialang.org/blog/2012/02/why-we-created-julia/)
interessant zusammengefasst.
Für ein Bild von *Stefan Karpinski, Viral Shah, Jeff
In their 2012 inaugural blog post [Why we created Julia](https://julialang.org/blog/2012/02/why-we-created-julia), Bezanson* und *Alan Edelman* bitte hier klicken: <https://news.mit.edu/2018/julia-language-co-creators-win-james-wilkinson-prize-numerical-software-1226>.
the developers provide an insightful and humorous overview of their objectives and motivations for creating Julia.
A photo of *Stefan Karpinski, Viral Shah, Jeff
Bezanson*, and *Alan Edelman* can be found
here: <https://news.mit.edu/2018/julia-language-co-creators-win-james-wilkinson-prize-numerical-software-1226>.
:::{.content-hidden unless-format="xxx"} :::{.content-hidden unless-format="xxx"}
Short summary: Kurzfassung:
> We want a language that is > We want a language that is
> >
@@ -78,26 +67,26 @@ Short summary:
Formal syntax Formale Syntax
: :
- Algorithmic thinking - Algorithmisches Denken
- Intuition for the efficiency and complexity of algorithms - Gefühl für die Effizienz und Komplezität von Algorithmen
- Special features of computer arithmetic, particularly floating-point numbers - Besonderheiten der Computerarithmetik, insbes. Gleitkommazahlen
- The "ecosystem" of the language - „Ökosystem“ der Sprache:
- The art of debugging. - die Kunst des Debugging.
::: :::
## Why Julia? {.unnumbered} ## Warum Julia? {.unnumbered}
:::{.callout-tip .titlenormal icon=false} :::{.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 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. Julia is dynamically typed, provides multiple dispatch, and is designed for parallelism and distributed computation.
@@ -106,45 +95,40 @@ Julia has a built-in package manager."
::: :::
***open source*** *open source*
: - offene Entwicklung auf [GitHub](https://github.com/JuliaLang/julia)
- Implementierungen für alle gängigen Betriebssysteme
- open development on [GitHub](https://github.com/JuliaLang/julia) *high-performance programming language for technical computing*
- implementations for all common operating systems : - 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
***high-performance programming language for technical computing*** *a JIT compiler*
: - 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
- many functions for *scientific computing* built-in *a built-in package manager*
- (intentional) similarity to Python, R and Matlab : - riesiges *ecosystem* an einfach installierbaren Paketen, z.B.
- complex calculations in a few lines - [Mathematische Optimierung](https://jump.dev/)
- simple interface to other languages like C or Python - [Machine Learning](https://fluxml.ai/)
- [Data Visualization](https://docs.makie.org/stable/)
***JIT compilation*** - [Differentialgleichungen](https://docs.sciml.ai/DiffEqDocs/stable/)
- [Mathematische Modellierung](https://sciml.ai/)
- supports interactive workflow via the `read-eval-print loop (REPL)`
- just-in-time (JIT) compilation
- resulting in runtimes comparable to static languages like C/C++, Fortran, or Rust
***a built-in package manager***
- huge *ecosystem* of easily installable packages, e.g.
- [Mathematical Optimization](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/)
## Selected Links {.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 overview" - [Cheat Sheet](https://cheatsheet.juliadocs.org/) - "a quick & dirty overview"
- [Introducing Julia](https://en.wikibooks.org/wiki/Introducing_Julia) -- a WikiBook - [Introducing Julia](https://en.wikibooks.org/wiki/Introducing_Julia)-- ein WikiBook
- [The Julia Express](http://bogumilkaminski.pl/files/julia_express.pdf) -- Julia in 16 pages - [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) -- introduction to programming using Julia as first language - [Think Julia](https://benlauwens.github.io/ThinkJulia.jl/latest/book.html) - Einführung in die Programmierung mit Julia als Sprache
- The [Julia Forum](https://discourse.julialang.org/) - Das [Julia Forum](https://discourse.julialang.org/)
- For the eyes: [Examples for the Julia graphics package `Makie`](https://beautiful.makie.org/) - Was fürs Auge: [Beispiele zum Julia-Grafikpaket `Makie`](https://beautiful.makie.org/)

View File

@@ -1,23 +0,0 @@
#let Skylighting(fill: none, number: false, start: 1, sourcelines) = {
let blocks = []
let lnum = start - 1
let bgcolor = rgb("#f1f3f5")
for ln in sourcelines {
if number {
lnum = lnum + 1
blocks = blocks + box(width: if start + sourcelines.len() > 999 { 30pt } else { 24pt }, text(fill: rgb("#aaaaaa"), [ #lnum ]))
}
blocks = blocks + ln + EndLine()
}
block(fill: bgcolor, width:100%, inset:(x:5pt, y:8pt), stroke:( left: 2pt + green), below:0pt, blocks)
}
#set math.mat(delim: "[")
// now in index.qmd
//#set math.equation(numbering: none)
// not enough
//#let equation-numbering = it => {
// numbering(none, it)
//}

View File

@@ -5,11 +5,11 @@
"npm": "@ai-sdk/openai-compatible", "npm": "@ai-sdk/openai-compatible",
"name": "llama-server (local)", "name": "llama-server (local)",
"options": { "options": {
"baseURL": "http://127.0.0.1:12434/v1" "baseURL": "http://127.0.0.1:8077/v1"
}, },
"models": { "models": {
"Qwen3.5-122B-A10B-coding": { "Qwen3-coder-next-100": {
"name": "Qwen3.5-122B-A10B-coding", "name": "Qwen3-coder-next-100",
"tool_call": true, "tool_call": true,
"reasoning": true, "reasoning": true,
"limit": { "limit": {