some small improvements in English

This commit is contained in:
2026-02-22 19:18:21 +01:00
parent 3b9c141c44
commit 552438aebe
8 changed files with 83 additions and 99 deletions

View File

@@ -41,7 +41,7 @@ If `T` is a numeric type, the elements are converted to this type.
v = [3//7, 4, 2im]
```
Information about an array is provided by the functions:
The following functions provide information about an array:
- `length(A)` --- number of elements
- `eltype(A)` --- type of elements

View File

@@ -12,7 +12,7 @@ using InteractiveUtils
# First Small Programs
## What Should One Be Able to Do for Programming?
## What Skills Are Needed for Programming?
- **Thinking in algorithms:**
@@ -30,7 +30,7 @@ using InteractiveUtils
These cannot all be mastered at once. Be patient with yourself and 'play' with the language.
The following should serve as a small inspiration.
The following examples should serve as inspiration.
## Project Euler
@@ -51,7 +51,7 @@ Aufg. 92
:::
::: {.callout-note icon=false .titlenormal}
## Project Euler Problem No 1
## Project Euler Problem No. 1
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
@@ -65,7 +65,7 @@ Find the sum of all the multiples of 3 or 5 below 1000.
2. Implementation:
How does Julia provide the remainder of integer division? Functions like this are typically called `rem()` (for *remainder*) or `mod()`. [Look it up in the documentation](https://docs.julialang.org/en/v1/base/math/#Base.rem) or try `?rem` and `?mod` in the Julia REPL shows that there are both. The difference lies in the treatment of negative integers. For natural numbers `n,m`, `mod(n,m)` and `rem(n,m)` give the same result, and the latter also has the infix form `n % m`.
How does Julia provide the remainder of integer division? Functions like this are typically called `rem()` (for *remainder*) or `mod()`. You can look it up in the documentation or try `?rem` and `?mod` in the Julia REPL. Both functions exist; the difference lies in the treatment of negative integers. For natural numbers `n,m`, `mod(n,m)` and `rem(n,m)` give the same result, and the latter also has the infix form `n % m`.
How does one test a sequence of values and sum them up? There is a standard pattern: `for` loop and accumulator variable:
@@ -103,7 +103,7 @@ sum([i for i in 1:999 if i%3==0||i%5==0])
::: {.callout-note icon=false .titlenormal}
## Project Euler Problem No 92
## Project Euler Problem No. 92
A number chain is created by continuously adding the square of the digits in a number to form a new number until it has been seen before.
For example,
@@ -195,7 +195,7 @@ end
println("$c numbers below ten million arrive at 89.")
```
Numbers for which the iterative square digit sum calculation ends at 1 are called [happy numbers](https://en.wikipedia.org/wiki/Happy_number), and we have just calculated the number of sad numbers less than 10,000,000.
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.
Here is the complete program again:

View File

@@ -16,15 +16,13 @@ using InteractiveUtils
flush(stdout)
```
# Example of Floating-Point Arithmetic Stability
# A Case Study in Floating-Point Arithmetic Stability
## Calculation of $\pi$ According to Archimedes
## Calculation of $\pi$ according to Archimedes
A lower bound for $2\pi$, the circumference of the unit circle, is obtained by the
sum of the side lengths of a regular $n$-gon inscribed in the unit circle.
The figure on the left shows how one can iteratively double the number of vertices starting from a square with side length $s_4=\sqrt{2}$.
A lower bound for $2\pi$—the circumference of the unit circle—is obtained by summing
the side lengths of a regular $n$-gon inscribed in the unit circle.
The figure on the left shows how one can iteratively double the number of vertices starting from a square with side length $$s_4=\sqrt{2}$$.
:::{.narrow}
@@ -35,7 +33,6 @@ The figure on the left shows how one can iteratively double the number of vertic
:::
The second figure shows the geometry of the vertex doubling.
With
@@ -50,35 +47,30 @@ $$
s_{2n} = \sqrt{2-\sqrt{4-s_n^2}} \qquad\text{with initial value}\qquad
s_4=\sqrt{2}
$$
for the length $s_n$ **of one** side of the inscribed regular
for the length $s_n$ of one side of the inscribed regular
$n$-gon.
The sequence $(n\cdot s_n)$
converges monotonically from below to the
limit $2\pi$:
The sequence $(n\cdot s_n)$ converges monotonically from below to the limit $2\pi$:
$$
n\, s_n \rightarrow 2\pi % \qquad\text{and} \qquad {n c_n}\downarrow 2\pi
$$
The relative error of the approximation of 2π by an $n$-gon is:
The relative error of approximating $2\pi$ by an $n$-gon is:
$$
\epsilon_n = \left| \frac{n\, s_n-2 \pi}{2\pi} \right|
$$
## Two Iteration Formulas^[by: Christoph Überhuber, "Computer-Numerik" Vol. 1, Springer 1995, Chap. 2.3]
The equation
## Two Iteration Formulas^[by Christoph Überhuber, "Computer-Numerik" Vol. 1, Springer 1995, Chap. 2.3]. The equation
$$
s_{2n} = \sqrt{2-\sqrt{4-s_n^2}}\qquad \qquad \text{(Iteration A)}
$$
is mathematically equivalent to
is mathematically equivalent to:
$$
s_{2n} = \frac{s_n}{\sqrt{2+\sqrt{4-s_n^2}}} \qquad \qquad \text{(Iteration B)}
$$
(Please verify!)
However, Iteration A is ill-conditioned and numerically unstable, as the following code demonstrates. The output shows the respective approximation for π.
However, Iteration A is ill-conditioned and numerically unstable, as the following code demonstrates. The output shows the respective approximation for $\pi$.
```{julia}
using Printf
@@ -86,19 +78,19 @@ using Printf
iterationA(s) = sqrt(2 - sqrt(4 - s^2))
iterationB(s) = s / sqrt(2 + sqrt(4 - s^2))
s_B = s_A = sqrt(2) # initial value
s_B = s_A = sqrt(2) # initial value
ϵ(x) = abs(x - 2π)/2π # rel. error
ϵ(x) = abs(x - 2π)/2π # relative error
ϵ_A = Float64[] # vectors for the plot
ϵ_A = Float64[] # vectors for the plot
ϵ_B = Float64[]
is = Float64[]
is = Float64[]
@printf """ approx. value of π
n-gon Iteration A Iteration B
@printf """Approx. value of π
$n$-gon Iteration A Iteration B
"""
for i in 3:35
for $i$ in $3:35$
push!(is, i)
s_A = iterationA(s_A)
s_B = iterationB(s_B)
@@ -106,47 +98,42 @@ for i in 3:35
doublePi_B = 2^i * s_B
push!(ϵ_A, ϵ(doublePi_A))
push!(ϵ_B, ϵ(doublePi_B))
@printf "%14i %20.15f %20.15f\n" 2^i doublePi_A/2 doublePi_B/2
@printf "%14i %20.15f %20.15f\n" 2^i doublePi_A/2 doublePi_B/2
end
```
While Iteration B stabilizes at a value correct within machine precision, Iteration A quickly becomes unstable. A plot of the relative errors $\epsilon_i$ confirms this:
While Iteration B stabilizes at a value correct within machine precision, Iteration A becomes unstable. A plot of the relative errors $\epsilon_i$ confirms this:
```{julia}
using PlotlyJS
layout = Layout(xaxis_title="Iteration steps", yaxis_title="rel. error",
layout = Layout(xaxis_title="Iteration steps", yaxis_title="Relative error",
yaxis_type="log", yaxis_exponentformat="power",
xaxis_tick0=2, xaxis_dtick=2)
plot([scatter(x=is, y=ϵ_A, mode="markers+lines", name="Iteration A", yscale=:log10),
plot([scatter(x=is, y=ϵ_A, mode="markers+lines", name="Iteration A", yscale=:log10),
scatter(x=is, y=ϵ_B, mode="markers+lines", name="Iteration B", yscale=:log10)],
layout)
```
```
## Stability and Cancellation
At $i=26$, Iteration B reaches a relative error on the order of machine epsilon:
```{julia}
ϵ_B[22:28]
```
Further iterations do not improve the result. It stabilizes at a relative error of approximately 2.5 machine epsilons:
Further iterations do not improve the result; it stabilizes at a relative error of approximately 2.5 machine epsilons.
```{julia}
ϵ_B[end]/eps(Float64)
```
Iteration A is unstable; already at $i=16$, the relative error begins to grow again.
Iteration A is unstable. Already at $i=16$ the relative error begins to grow again.
The cause is a typical cancellation effect. The side lengths $s_n$ become very small very quickly. Thus
$a_n=\sqrt{4-s_n^2}$ is only slightly smaller than 2, and when computing $s_{2n}=\sqrt{2-a_n}$ a typical cancellation effect occurs.
The cause is a typical cancellation effect. The side lengths $s_n$ become very small, very quickly. Thus
$a_n=\sqrt{4-s_n^2}$ is only slightly smaller than 2, and when computing $s_{2n}=\sqrt{2-a_n}$, a typical cancellation effect occurs.
```{julia}
setprecision(80) # precision for BigFloat
@@ -155,24 +142,22 @@ s = sqrt(BigFloat(2))
@printf " a = √(4-s^2) as BigFloat and as Float64\n\n"
for i = 3:44
for $$i=$ 3:44$
s = iterationA(s)
x = sqrt(4-s^2)
if i > 20
@printf "%i %30.26f %20.16f \n" i x Float64(x)
end
end
```
One sees the decrease in the number of significant digits. One also sees that using `BigFloat` with a mantissa length of 80 bits here only slightly delays the onset of the cancellation effect.
One sees the decrease in the number of significant digits. One also sees that using `BigFloat` with a mantissa length of 80 bits only slightly delays the onset of the cancellation effect.
**Countermeasures against unstable algorithms usually require better, stable algorithms, not more precise machine numbers!**
**Countermeasures against unstable algorithms typically require better, stable algorithms, not more precise machine numbers.**
:::{.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,
Clearly, the computation of $2-a_n$ already shows a decrease in the number of significant digits (cancellation) relatively early
before the computation of $a_n=\sqrt{4-s_n^2}$ itself leads to an unusable result due to cancellation.
:::
:::

View File

@@ -43,7 +43,7 @@ julia>
### Jupyterhub & Jupyter
- [Jupyterhub](https://de.wikipedia.org/wiki/Project_Jupyter) is a multi-user server for Jupyter.
- [JupyterHub](https://de.wikipedia.org/wiki/Project_Jupyter) is a multi-user server for Jupyter notebooks.
- Jupyter is a web-based interactive programming environment that
- was originally written for and in Python, but now supports many programming languages
- In Jupyter, one works with so-called *notebooks*. These are structured text files (JSON), recognizable by the file extension `*.ipynb`.
@@ -65,7 +65,7 @@ This can be used to:
- open existing *notebooks*,
- create new *notebooks*,
- upload files, e.g. *notebooks*, from the local computer,
- upload files, e.g., notebooks, from a local computer,
- end the session with `Logout` (please don't forget!).
### Jupyter notebooks
@@ -120,7 +120,7 @@ The cell currently being worked on can be in `command mode` or `edit mode`.
:::
When a cell is "working", its cell number becomes a `*` and
When a cell is working, its cell number becomes a `*` and
the `kernel busy` indicator (solid black dot at the top right next to the
Julia version) appears. If this takes too long (an *infinite loop*
is quickly programmed), then
@@ -130,7 +130,7 @@ is quickly programmed), then
::: {.callout-important }
After a `kernel restart`, all cells containing required definitions,
After a `kernel restart`, all cells containing the required definitions,
`using` statements, etc. must be executed again.

View File

@@ -11,7 +11,7 @@ using InteractiveUtils
# First Contact
This chapter helps you get started. It omits many details and the code examples are often rather suboptimal.
This chapter helps you get started. It omits many details, and the code examples are often rather suboptimal.
## Julia as a Calculator
@@ -41,7 +41,7 @@ end
# IJulia.set_verbose(true)
```
Compute $\qquad 12^{1/3} + \frac{3\sqrt{2}}{\sin(0.5)-\cos(\frac{\pi}{4})\log(3)}+ e^5$
Compute: $\qquad 12^{1/3} + \frac{3\sqrt{2}}{\sin(0.5)-\cos(\frac{\pi}{4})\log(3)}+ e^5$
```{julia}
12^(1/3) + 3sqrt(2) / (sin(.5) - cos(pi/4)*log(3)) + exp(5)
@@ -50,14 +50,14 @@ Compute $\qquad 12^{1/3} + \frac{3\sqrt{2}}{\sin(0.5)-\cos(\frac{\pi}{4})\log(3)
Note that:
- Powers are written as `a^b`.
- The constant `pi` is predefined.
- The constant `π` is predefined.
- `log()` is the natural logarithm.
- The multiplication sign `a*b` can be omitted after a number if followed by a variable, function, or parenthesis.
- The multiplication sign `a*b` can be omitted after a number if it is followed by a variable, function, or parenthesis.
## The most important keys: `Tab` and `?` {#sec-tab}
When programming, repeatedly press the Tab key as soon as 2...3 letters of a word have been typed. Potential completions are then displayed or completed if the completion is unique. This saves time and is extremely helpful:
When programming, repeatedly press the Tab key as soon as 23 letters of a word have been typed. Potential completions are then displayed or completed if the completion is unique. This saves time and is extremely helpful.
```{julia}
lo = "lo" #| hide_line
@@ -69,7 +69,7 @@ pri = "pri" #| hide_line
pri ▷ Tab
```
The built-in Julia help `?name` for all functions and constructs is very comprehensive. Here is a rather short example:
The built-in Julia help `?name` for all functions and constructs is very comprehensive. Here is a rather brief example:
```{julia}
?for
@@ -105,17 +105,17 @@ julia> for i in [1, 4, 0]
## Variables and Assignments
Variables are created through assignment with the assignment operator `=` . Afterward, they can be used in further statements.
Variables are created through assignment with the assignment operator `=`. Afterwards, they can be used in further statements.
```{julia}
x = 1 + sqrt(5)
y = x / 2
```
In interactive mode, Julia displays the result of the last operation.
In interactive mode, Julia displays the result of the last statement.
:::{.callout-note .titlenormal}
Assignments are not mathematical equations. The semantics of the assignment operator (equals sign) is:
Assignments are not mathematical equations. The semantics of the assignment operator (the equals sign) is:
- Compute the right side and
- Assign the result to the left side.
@@ -142,11 +142,11 @@ for x ∈ (42, 12.0, 3.3e4, "Hello!", true)
println("x = ", x, " ..... Type: ", typeof(x))
end
```
The standard floating-point number has a length of 64 bits, which corresponds to a `double` in C/C++/Java.
The standard floating-point number has a size of 64 bits, which corresponds to a `double` in C/C++/Java.
Julia is a [dynamically typed](https://en.wikipedia.org/wiki/Dynamic_typing) language.
Variables have no type. They are typeless references (pointers) to objects.
When one speaks of the "type of a variable", one means the type of the object currently assigned to the variable.
Variables have no type; they are typeless references (pointers) to objects.
When people speak of the "type of a variable", they mean the type of the object currently assigned to the variable.
```{julia}
x = sqrt(2)
@@ -189,7 +189,7 @@ println("One dollar: 1\$ and three backslashes: \\\\\\ ")
:::
## Functions
Function definitions begin with the keyword `function` and end with the keyword `end`. Typically, they have one or more arguments and return a computed object with the `return` statement on calling.
Function definitions begin with the keyword `function` and end with the keyword `end`. Typically, they have one or more arguments and return a computed result via the `return` statement.
```{julia}
function hypotenuse(a, b) # particularly cumbersome today
c2 = a^2 + b^2
@@ -252,7 +252,7 @@ else
end
```
Indentation improves readability but is optional. Line breaks separate statements. This can also be done with semicolons. The above code block is identical to the following line for Julia:
Indentation improves readability but is optional. Line breaks separate statements, and this can also be done with semicolons. The above code block is identical to the following line in Julia:
```{julia}
# Please don't program like this! You will regret it!
x=sqrt(100); if x > 20 println("Strange!") else println("OK"); y = x + 3 end
@@ -263,7 +263,7 @@ It is strongly recommended to format your own code from the beginning with clear
## Simple `for` loops
for repeated execution of statements have the form
`for` loops for repeated execution of statements have the form
```default
for <counter> = start:end
<statement1>
@@ -299,7 +299,7 @@ v[1] = v[4] + 10
v
```
Empty vectors can be created and extended.
Empty vectors can be created and extended with `push!()`.
```{julia}
v = [] # empty vector
push!(v, 42)
@@ -310,7 +310,7 @@ v
:::{.callout-note icon="false" .titlenormal collapse="true" font-variant-ligatures="no-contextual" }
## Postscript: how the effect of the Tab key was simulated on this page...
## Postscript: how the effect of the Tab key was simulated on this page
```{julia}
using REPL

View File

@@ -93,7 +93,7 @@ end
```{julia}
z1 = PComplex{Float64}(-3.3, 7π+1)
```
For the explicit specification of an *inner constructor*, we have to pay a price: The *default constructors* provided by Julia are missing.
For explicitly specifying an *inner constructor*, we pay a price: Julia's *default constructors* are no longer available.
The constructor without explicit type specification in curly braces, which takes over the type of the arguments, is also desired:

View File

@@ -16,21 +16,21 @@ using InteractiveUtils
- Names may contain letters, digits, underscores `_`, and exclamation marks `!`.
- The first character must be a letter or an underscore.
- Case is significant: `Nmax` and `NMAX` are different variables.
- The character set used is [Unicode](https://home.unicode.org/). This provides access to over 150 scripts and numerous symbols.
- The character set used is [Unicode](https://home.unicode.org/), which provides access to over 150 scripts and numerous symbols.
- There is a short [list of reserved keywords](https://docs.julialang.org/en/v1/base/base/#Keywords): `if, then, function, true, false,...`
:::{.callout-tip}
## Example
permissible: `i, x, Ω, x2, DieUnbekannteZahl, neuer_Wert, 🎷, Zähler, лічильник, einself!!!!,...`
Permissible: `i, x, Ω, x2, DieUnbekannteZahl, neuer_Wert, 🎷, Zähler, лічильник, einself!!!!,...`
impermissible: `Uwe's_Funktion, 3achsen, A#B, $this_is_not_Perl, true,...`
Impermissible: `Uwe's_Funktion, 3achsen, A#B, $this_is_not_Perl, true,...`
:::
----
:::{.callout-note }
## Note
## Note:
In addition to the *reserved keywords* of the core language, numerous additional functions and objects are predefined, such as the mathematical functions `sqrt(), log(), sin()`.
These definitions are found in the module `Base`, which Julia loads automatically at startup.
@@ -41,7 +41,7 @@ Names from `Base` can be redefined as long as they have not yet been used:
log = 3
1 + log
```
Now of course the logarithm is broken:
Now, of course, the logarithm is broken:
```{julia}
#| error: true
x = log(10)
@@ -62,13 +62,14 @@ x = log(10)
:::{.callout-tip}
## Example
## Example:
In interactive mode, the value of the last statement is also displayed without explicit `print()`:
```{julia}
println("Hallo 🌍!")
x = sum([i^2 for i=1:10])
```
The semicolon suppresses this:
```{julia}
println("Hallo 🌍!")
@@ -81,14 +82,14 @@ x = sum([i^2 for i=1:10]);
:::{.callout-warning }
For multi-line statements, the line to be continued must end with an open operation or parenthesis:
For multi-line statements, the line to be continued must end with an open operator or parenthesis.
```{julia}
x = sin(π/2) +
3 * cos(0)
```
Therefore, the following goes wrong, but unfortunately **without an error message**!
Therefore, the following goes wrong, butunfortunately**without an error message**!
```{julia}
#| error: true
#| warning: true
@@ -98,7 +99,7 @@ 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.
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:** If you want to split longer expressions across multiple lines, you should always open a parenthesis. Then it doesn't matter where the line break occurs.
```{julia}
x = ( sin(π/2)
+ 3 * cos(0) )
@@ -119,12 +120,10 @@ x = 2 # everything from '#' to the end of the line is a comment and is ignore
```{julia}
#=
Single and multi-line comments can be enclosed between #= ... =#.
Nested comments are possible.
#=
i.e., unlike in C/C++/Java, the comment does not end with the first
comment-end character, but the #=...=# pairs act like parentheses.
=#
Single and multi-line comments can be enclosed between `#= ... =#`. Nested comments are possible.
`#=`
i.e., unlike in C/C++/Java, the comment does not end with the first comment-end character, but the `#=...=#` pairs act like parentheses.
`=#`
The automatic 'syntax highlighter' does not yet know this, as the alternating
gray shading of this comment shows.
=#
@@ -136,10 +135,10 @@ x #= das ist ein seltener Variablenname! =# = 3
## Data Types Part I
- Julia is a [strongly typed](https://de.wikipedia.org/wiki/Starke_Typisierung) language. All objects have a type. Functions/operations expect arguments of the correct type.
- Julia is a [strongly typed](https://de.wikipedia.org/wiki/Starke_Typisierung) language. All objects have a type. Functions and operations expect arguments of the correct type.
- Julia is a [dynamically typed](https://de.wikipedia.org/wiki/Dynamische_Typisierung) language. Variables have no type. They are names that can be bound to objects via assignment `x = ...`.
- When speaking of the "type of a variable", one means the type of the object currently assigned to the variable.
- Functions/operators can implement different *methods* for different argument types.
- Functions and operators can implement different *methods* for different argument types.
- Depending on the concrete argument types, it is decided at function usage which method is used ([*dynamic dispatch*](https://en.wikipedia.org/wiki/Dynamic_dispatch)).
@@ -184,8 +183,8 @@ x, typeof(x), sizeof(x)
### `if` Blocks
- An `if` block *can* contain **any number** of `elseif` branches and at the end at most **one** `else` branch.
- The block has a value, the value of the last executed statement.
- An `if` block can contain any number of `elseif` branches and, at the end, at most one `else` branch.
- The block has a value: the value of the last executed statement.
```{julia}
x = 33
@@ -205,7 +204,7 @@ end # value of the entire block is the value
# last evaluated statement
```
Short blocks can be written in one line:
Short blocks can be written on one line:
```{julia}
if x > 10 println("x is larger than 10") end
```
@@ -248,7 +247,7 @@ z = if x < y
- `<`
- `<=`, `≤`
As usual, the equality test `==` is to be distinguished from the assignment operator `=`. Almost anything can be compared:
As usual, the equality test `==` must be distinguished from the assignment operator `=`. Almost anything can be compared.
```{julia}
"Aachen" < "Leipzig", 10 ≤ 10.01, [3,4,5] < [3,6,2]

View File

@@ -21,7 +21,7 @@ One can write extensive programs in Julia without using a single type declaratio
However, we will now take a look under the hood.
## The Type Hierarchy with the Example of Numeric Types
## The Type Hierarchy: A Case Study with Numeric Types
The type system has the structure of a tree whose root is the type `Any`. The functions `subtypes()` and `supertype()` can be used to explore the tree. They show all children or the parent of a node.