Einleitung

Motivation

Wenn man es mit komplexen Modellen, vielen Daten, oder nur numerisch lösbaren Problemen zu tun hat, verwendet man in der Mathematik sehr gerne den Computer (deutsch: Rechner, to compute = berechnen) in Verbindung mit einer passenden Software. Aber auch zum Visualisieren und zum Überprüfungen von Handrechnungen ist der Computer sehr hilfreich.

Warum Python für wissenschaftliches Rechnen? Python ist eine freie, offene, plattformunabhängige, üblicherweise interpretierte, höhere Programmiersprache. Python Code ist gut lesbar und einfach zu lernen. Es gibt sehr viele Pakete und Einsatzgebiete für Python, siehe PyPI - the Python Package Index.

Für den Bereich des wissenschaftlichen Rechnens sind insbesondere folgende Python-Pakete nützlich:

  • NumPy: NumPy bietet Unterstützung für große, mehrdimensionale Arrays (Vektoren, Matrizen, …) sowie eine große Sammlung von high-level mathematischen Funktionen, um mit diesen Arrays zu arbeiten.
  • Matplotlib: eine Grafikbibliothek, die jener von Matlab sehr ähnlich ist
  • SciPy: SciPy enthält Module für Optimierung, lineare Algebra, Integration, Interpolation, spezielle Funktionen, Signal- und Bildverarbeitung, Solver für gewöhnliche Differentialgleichungen und andere in Wissenschaft und Technik übliche Aufgaben.

Python erfreut sich einer großen und wachsenden Beliebtheit und besitzt daher eine umfangreiche und breitgefächert Community. So ziemlich jedes Problem mit Lösung/en findet man z. B. unter stackoverflow. Der Name bezieht sich übrigens auf die englische Komikergruppe Monty Python.

Zu den Alternativen im Bereich wissenschaftliches Rechnen zählen

  • Julia: frei, offen und plattformunabhängig
  • R: frei, offen und plattformunabhängig
  • Matlab: kommerziell
  • Mathematica: kommerziell

Im Folgenden finden Sie:

  • Informationen zur Installation von Python auf Ihrem Computer,
  • Informationen zum Online-Jupyter-Hub der FHV,
  • kurze Einführungen in JupyterLab und in jene Python-Kenntnissen, die wir in dieser Lehrveranstaltung verwenden.

FHV-Jupyter-Hub

Unter jupyter.labs.fhv.at können Sie sich mit Ihrem FHV-Account einloggen und Python in Jupyter Notebooks verwenden. Verwenden Sie zum Einloggen Ihre FHV-Emailadresse ohne den Domänenteil @students.fhv.at als Benutzernamen. Von zu Hause müssen Sie zuerst eine VPN-Verbindung zur FHV aufbauen, siehe FHV-Inside/VPN.

Lokale Installation

Python und Python-Pakete können auf unterschiedliche Weisen lokal installiert werden. Wir beschreiben hier die von vielen empfohlene Installation der Python Distribution Anaconda:

Anaconda

Um die umfangreiche Anaconda Distribution zu installieren, folgen Sie der Dokumentation entsprechend Ihrem Betriebssystem. 1 Anaconda ist ein Manager für Umgebungen (engl. environments). Neben Python können auch weitere Sprachen damit installiert werden, was aber für diesen Kurs nicht notwendig ist.

Environments

Variante 1: Anaconda Navigator

  1. Nach der Installation von Anaconda findet man im Startmenü Anaconda 3 oder Anaconda Navigator. Nach dem Starten des Programms Anaconda Navigator befindet sich auf der linken Seite der Punkt Environments. Beim Klicken auf diesen Punkt öffnet sich eine neue Ansicht. In dieser Ansicht unten in der Mitte auf Import klicken.
  2. Anschließend den Pfad der heruntergeladenen Datei LinAlg2023.txt (für Windows) bzw. LinAlg2023.yaml (für alle anderen Betriebssysteme) angeben und mit Import den Import starten.
  3. Nach erfolgreicher Installation erscheint LinAlg2023 in der Liste der Umgebungen. Bei Klicken auf Home (Menü links), kann die Umgebung aus dem rechten Dropdown-Menü (oben in der Mitte) ausgewählt werden. Anschließend kann so Jupyter Lab in der richtigen Umgebung gestartet werden.

Variante 2: Anaconda Prompt

Neben der Benutzung des Anaconda-Navigators, kann die Installation eines Environments auch mittels der Kommandozeile in einem Anaconda Prompt oder Miniconda Prompt erfolgen. Hier ein Beispiel: Um eine Environment namens LinAlg zu erstellen, die Python in Version 3.11 und eine Reihe zusätzlicher Pakete enthält, geben Sie folgenden Befehl im Prompt ein:

conda create -n LinAlg python=3.11 ipython jupyterlab numpy matplotlib scipy

Aktivieren Sie das Environment mit conda activate LinAlg, und starten Sie JupyterLab mit jupyter lab. Deaktivieren Sie das Environment nach getaner Arbeit mit conda deactivate. Mehr Infos zu Environments und conda finden Sie z. B. im Conda Cheatsheet. Folgende Pakete werden für die Lehrveranstaltung benötigt:

  • python (version 3.9.18)
  • jupyter (version 1.0.0)
  • matplotlib (version 3.8.2)
  • numpy (version 1.26.0)
  • scipy (version 1.11.3)

Die angegebenen Versionsnummern sind die Versionen aus dem vorgefertigten Environment LinAlg2023.txt bzw. LinAlg2023.yaml. Diese sind nicht verpflichtend, aber es können damit Kompatibilitätsprobleme vermieden werden.

JupyterLab

Es gibt, grob gesagt, zwei Typen von Entwicklungsumgebungen:

Wenn Sie sich unter jupyter.labs.fhv.at einloggen, verwenden Sie bereits JupyterLab. Auf Ihrem Computer starten Sie JupyterLab via dem Anaconda Navigator oder einfacher über eine Kommandozeile mit dem Befehl jupyter lab.

Das meiste der browserbasierten Oberfläche ist selbsterklärend. Wenn Sie ein (neues) Jupyter Notebook (Dateiendung .ipynb) starten, wird ein Kernel gestartet. Der Kernel führt Ihre Python Befehle aus und beinhaltet alle verwendeten Objekte (Variablen, Funktionen, Pakete etc.).

Achtung

Verwenden Sie generell für Ordner- und und Dateinamen keine Umlaute, keine Sonderzeichen und keine Leerzeichen!

Ein Jupyter-Notebook besteht aus einer Liste von Zellen (engl. cells). Zellen können im Command Mode oder im Edit Mode bearbeitet werden. Die wichtigsten zwei Zelltypen sind Code und Markdown.

Code Zellen:

  • Wir schreiben unseren Python Code in die Code-Zellen eines Jupyter-Notebooks. Zum Ausführen des Codes einer Code-Zelle drücken Sie Strg+Return oder Shift+Return. Bei der ersten Variante bleibt der Fokus auf der Code-Zelle, bei der zweiten springt man in die nächste Zelle.
  • Der Rückgabewert des letzten Befehls einer Code Input-Zelle wird in einer folgenden Code Output-Zelle ausgegeben. Sie können die Ausgabe mit einem Strichpunkt am Ende des letzten Befehls unterdrücken.
  • Kommentare in Code-Zellen beginnen mit dem Rautezeichen #.
  • Funktionen haben runde Klammern. Hilfe z. B. zur Funktion print erhalten Sie durch help(print) oder print? oder SHIFT-TAB drücken, wenn der Cursor nach der ersten runden Klammer von print() steht.
  • Eine Liste der von Ihnen definierten Variablen erhalten Sie mit dem magic command %whos. Löschen einzelner Variablen, hier z. B. der Variable x, erfolgt mit dem Befehl del(x). Löschen aller selber definierten Variablen erfolgt mit dem Befehl %reset -s.
  • Tipp: Verwenden Sie die Tabulator-Vervollständigung beim Coden!
  • Tipp: Mit der Tastenkombination Strg+I öffnet sich der sehr hilfreiche Contextual Help Tab.
  • Tipp: Öffnen Sie eine Console für Ihr Notebook, um außerhalb des Notebooks interaktiv Befehle im Namespace des Notebook-Kernels auszuführen.

Markdown Zellen: Markdown ist eine vereinfachte Auszeichnungssprache, die bereits in der Ausgangsform ohne weitere Konvertierung leicht lesbar ist. Sie können in Markdown sehr leicht folgenden strukturierten Text erstellen:

  • Überschirften: Rautesymbol(e) vor der Überschrift
  • Listen: mit Minus-, Plus- oder Sternzeichen
  • Links: mit Syntax [Name](URL)
  • Bilder: mit Syntax ![Name](Pfad-zu-Bilddatei)
  • Mathematische Formeln wie z. B. \(K = \frac{mv^2}{2}\) via dem LaTeX-Code $K = \frac{mv^2}{2}$
  • Tipp: Cheatsheet
Keyboard Shortcuts

Die Keyboard Shortcuts (Tastenkürzel) sind in den Menüs neben den Auswahlen angegeben. Hier eine persönliche Auswahl:

Shortcut Effekt
Ctrl+s save notebook
Ctrl+Shift+q close and shutdown notebook
Ctrl+f Find
Enter enter edit mode
Escape enter command mode
Ctrl+Enter run cell
Shift+Enter run cell and got to cell below
Shift+m merge selected cells
in edit mode: Ctrl+Shift+- split cell
in command mode: m set cell type to markdown
in command mode: y set cell type to code
in command mode: d d delete cell
in command mode: z undo deleting of cell
in command mode: a insert cell above
in command mode: b insert cell below
in command mode: x/c/v cut/copy/paste cells
in command mode: UP/DOWN arrow selected previous/next cell
in command mode: i+i interrupt kernel
in command mode: 0+0 restart kernel
in command mode: Shift+l toggle all line numbers

Bevor Sie JupyterLab beenden, vergessen Sie nicht, Ihre Jupyter-Notebooks zu speichern, zu schließen sowie die zugehörigen Kernel herunterzufahren. Zum Beenden von JupyterLab wählen Sie im Menü File/Shut Down.

Navigationsbefehle im Dateisystem: Für die Arbeit in einem System-Terminal, dem Anaconda Command Prompt oder in einer Codezelle sind oft folgende Navigationsbefehle nützlich:

  • pwd: print working/current directory
  • ls oder dir: list files in current directory
  • cd DIR: change into absolute or relative directory DIR
  • cd ..: change to parent directory

Tipps: Schauen Sie mal in die Gallery of interesting Jupyter Notebooks und in das Jupyter-Tutorial rein.

Tutorial

Dieses Tutorial zeigt einführend, wie Python zum wissenschaftlichen Rechnen verwendet werden kann. Ausführlichere Einführungen finden Sie z. B. in:

Wer Python von Grund auf und umfassender lernen möchte, kann z. B. diese Bücher und Links verwenden:

Python als Taschenrechner

In der Python-Shell können Sie intuitiv Rechnungen eintippen. Hier ein paar Beispiele:

Code
(42 + 137)/0.815
219.6319018404908

Achtung: Das Dezimaltrennzeichen ist im Englischen ein Punkt, und Potenzieren wird mit ** implementiert!

Code
1.23**45
11110.40818513195

Um die elementaren mathematischen Funktionen zu verwenden, müssen Sie zuerst, und nur einmal, das NumPy-Paket importieren. Wir verwenden das Kürzel np, um die Funktionen von NumPy anzusprechen.

Code
import numpy as np

np.sqrt(np.pi/2)
1.2533141373155001

Kommentare beginnen mit einem #.

Code
# This is a comment.
np.log(1)  # This also.
0.0

Formatierte Ausgabe

Für eine formatierte Ausgabe verwenden wir die Funktion print und sogenannte f-Strings:

Code
name  = "Klaus"
like_math = True
age = 50
value = 12.3456789

print(f"Hallo! My name is {name}.")
print(f"I {like_math = }")
print(f"I am {age} years old. These are about {age*365} days.")
print(f"A value: {value:.2f}")  # float with two decimal places
Hallo! My name is Klaus.
I like_math = True
I am 50 years old. These are about 18250 days.
A value: 12.35

Listen und Vektoren

In der Mathematik ist ein Vektor des \(\mathbb{R}^n\) eine geordnete Liste von \(n\) reellen Zahlen. In Python werden allgemeine Listen (nicht nur von Zahlen) mit eckigen Klammern erzeugt:

Code
a = [-3, 5.7, 8]
b = [2.1, 0, -8]
c = ["Karl", "Klaus", "Erna", "Maria"]

Allerdings ist z. B. die Addition von Python-Listen mit Zahleneinträgen nicht wie die Addition von Vektoren in der Mathematik, nämlich elementweise, definiert:

Code
a + b
[-3, 5.7, 8, 2.1, 0, -8]

Um den gewünschten Effekt von Addition und Skalarmultiplikation für Vektoren zu erreichen, machen wir solche Python-Listen zu 1-dimensionalen NumPy-Arrays:

Code
v = np.array([-3, 5.7, 8])
w = np.array([2.1, 0, -8])

print(v + w)
print(3*w)
[-0.9  5.7  0. ]
[  6.3   0.  -24. ]

Es gibt einige hilfreiche NumPy-Funktionen, um oft gebrauchte Typen von NumPy-Arrays zu erzeugen, z. B.:

Code
# 11 evenly spaced numbers over the interval [0, 50]:
x = np.linspace(0, 50, 11)
print(x)
[ 0.  5. 10. 15. 20. 25. 30. 35. 40. 45. 50.]
Code
# evenly spaced numbers over the interval [0, 20] with step size 2:
x = np.arange(0, 20, 2)  # Note, that 20 is not included!
print(x)
[ 0  2  4  6  8 10 12 14 16 18]

NumPy-Arrays

Ein Vektor wird als eindimensionales NumPy-Array implementiert, eine Matrix als zweidimensionales NumPy-Array.

Code
v = np.array([-3, 5.7, 8])

print(f"{v}")
print(np.ndim(v)) # number of dimensions
print(len(v))     # length, i. e. number of items, not the geometric length!
print(v.size)     # also number of items
[-3.   5.7  8. ]
1
3
3
Code
# A matrix is filled row-wise with lists:
M = np.array([[-3, 5.7, 8],
              [2.1, 0, -8]])
print(f"{M}")
print(np.ndim(M)) # number of dimensions of the array
print(M.shape)    # shape of the array
print(M.size)     # number of elements in the array
[[-3.   5.7  8. ]
 [ 2.1  0.  -8. ]]
2
(2, 3)
6

Indexing und slicing of vectors and lists:

Code
x = np.array([1, 2.1, -5])

# accessing vector (=1-dim-array) items works the same as with lists:
print(x[0])     # Python starts indexing with 0.
print(x[1:3])   # items from index 1 included until index 3 excluded
print(x[:2])    # items up to index 2 with index 2 excluded
print(x[1:])    # items starting from index 1 with index 1 included
print(x[-1])    # last item
print(x[-2])    # second last item
print(x[-2:])   # from the second last item to the end
print(x[-2:-1]) # should be clear now :-)
1.0
[ 2.1 -5. ]
[1.  2.1]
[ 2.1 -5. ]
-5.0
2.1
[ 2.1 -5. ]
[2.1]

Indexing and slicing of matrices:

Code
M = np.array([[-3, 5.7, 8],
              [2.1, 0, -8]])
print(f"{M}")

# accessing matrix items works similar: 
print("first row, second column:")
print(M[0, 1])
print("first row:")
print(M[0, :])
print("second column:")
print(M[:, 1])
print("second and third column:")
print(M[:, 1:3])
print("first two columns:")
print(M[:, :2])
[[-3.   5.7  8. ]
 [ 2.1  0.  -8. ]]
first row, second column:
5.7
first row:
[-3.   5.7  8. ]
second column:
[5.7 0. ]
second and third column:
[[ 5.7  8. ]
 [ 0.  -8. ]]
first two columns:
[[-3.   5.7]
 [ 2.1  0. ]]

Beachten Sie, dass beim Slicing das Rückgabe-Array die angepasste Dimension hat, die sich von der Dimension des Ausgangs-Arrays unterscheiden kann. Hier ein Beispiel, wie man das Slicing so anpasst, dass das Rückgabe-Array die gleiche Dimension wie das Ausgangs-Array hat:

Code
M = np.array([[-3, 5.7, 8],
              [2.1, 0, -8]])
print(f"{M}")
print("first column as 1-dim array:")
print(M[:, 0])
print("first column as 2-dim array:")
print(M[:, [0]])
[[-3.   5.7  8. ]
 [ 2.1  0.  -8. ]]
first column as 1-dim array:
[-3.   2.1]
first column as 2-dim array:
[[-3. ]
 [ 2.1]]

Transponieren einer Matrix:

Code
print(f"{M}")
print(f"{M.T}")
[[-3.   5.7  8. ]
 [ 2.1  0.  -8. ]]
[[-3.   2.1]
 [ 5.7  0. ]
 [ 8.  -8. ]]

Mutability

Listen und NumPy-Arrays sind veränderbar (engl. mutable), d. h. sie können nach ihrer Erzeugung verändert werden.

Code
a = np.array([1, 2, 3])
print(f"{a = }")
b = a     # Caution: b references the same object as a
b[1] = 4  # Changing b changes a!
print(f"{a = }")
a = array([1, 2, 3])
a = array([1, 4, 3])
Code
# If you do not want this, you have to make a copy:
a = np.array([1, 2, 3])
print(f"{a = }")
b = a.copy() # b is a copy of a
b[1] = 4     # changing b does not change a
print(f"{a = }")
a = array([1, 2, 3])
a = array([1, 2, 3])

Vektor- und Matrizenrechnung

Code
v = np.array([-1, 5, 0])  # 1-dim array
w = np.array([ 2, 2, 1])  # 1-dim array

print("inner product:")
print(f"{v@w = } or {np.dot(v, w) = }")
print("cross product:")
print(f"{np.cross(v, w) = }")

print("Caution: These are element-wise operations:")
print(f"{v*w = }")
print(f"{v/w = }")
print(f"{v**2 = }")
inner product:
v@w = 8 or np.dot(v, w) = 8
cross product:
np.cross(v, w) = array([  5,   1, -12])
Caution: These are element-wise operations:
v*w = array([-2, 10,  0])
v/w = array([-0.5,  2.5,  0. ])
v**2 = array([ 1, 25,  0])

Die Matrixmultiplikation wird wie das innere Produkt mit dem @ Operator durchgeführt:

Code
M = np.array([[-3, 5.7, 8],
              [2.1, 0, -8]])
N = np.array([[1, 2],
              [3, 4],
              [5, 6]])
print("M@N = ")
print(f"{M@N}")

print("M@v = ")
print(f"{M@v}")
M@N = 
[[ 54.1  64.8]
 [-37.9 -43.8]]
M@v = 
[31.5 -2.1]

Berechnung von Rängen, Determinanten, Eigenwerten, Eigenvektoren:

Code
M = np.array([[-3, 2, 8],
              [ 2, 0, 1],
              [ 8, 1, 3]])
rank = np.linalg.matrix_rank(M)
print(f"{rank = }")
det = np.linalg.det(M)
print(f"{det = :.2f}")
eigenvalues, eigenvectors = np.linalg.eig(M)
print("1-dim array of eigenvalues:")
print(f"{eigenvalues}")
print("2-dim array of eigenvectors in columns:")
print(f"{eigenvectors}")

print("Some check by computing M*v_1 - lambda_1*v_1")
print("which should be a numerically zero vector:")
result = M@eigenvectors[:, 0] - eigenvalues[0]*eigenvectors[:, 0]
print(f"{result = }")
rank = 3
det = 23.00
1-dim array of eigenvalues:
[ 8.97566072 -8.68045912 -0.2952016 ]
2-dim array of eigenvectors in columns:
[[ 0.56706349  0.82346126  0.01872296]
 [ 0.21494363 -0.12599762 -0.96846468]
 [ 0.7951341  -0.55320535  0.2484464 ]]
Some check by computing M*v_1 - lambda_1*v_1
which should be a numerically zero vector:
result = array([ 0.00000000e+00, -1.11022302e-15, -1.77635684e-15])

Lineare Gleichungssysteme

Wir lösen das quadratische lineare Gleichungssystem \(Ax = b\) und überprüfen zuerst, ob es eine eindeutige Lösung gibt:

Code
A = np.array([[1, 2],
              [3, 4]])
b = np.array([5, 6])

(m, n) = A.shape
print(f"rank(A) = {np.linalg.matrix_rank(A)}")
if np.linalg.matrix_rank(A) == n:
    x = np.linalg.solve(A, b)  # Matrix A must be square and of full-rank!
    print(f"unique solution: {x = }")
else:
    print("no unique solution!")
rank(A) = 2
unique solution: x = array([-4. ,  4.5])

Kern (engl. null space, kernel) und Bild (engl. column space, range, image) einer Matrix:

Code
import scipy as sp

A = np.array([[1, 2, -1],
              [2, 4,  3]])

print("matrix A:")
print(f"{A}")
print(f"{np.linalg.matrix_rank(A) = }.")

print("orthonormal basis for the null space (kernel) of A:")
N = sp.linalg.null_space(A)
print(f"{N}")

print("orthonormal basis for the column space (range, image) of A:")
C = sp.linalg.orth(A)
print(f"{C}")

# the orthonormal bases are given as column vectors.
matrix A:
[[ 1  2 -1]
 [ 2  4  3]]
np.linalg.matrix_rank(A) = 2.
orthonormal basis for the null space (kernel) of A:
[[ 8.94427191e-01]
 [-4.47213595e-01]
 [-3.33066907e-16]]
orthonormal basis for the column space (range, image) of A:
[[-0.27000134 -0.96285995]
 [-0.96285995  0.27000134]]

Plot einer Funktion

Code
# define the function f:
def f(x):
    return x**2

# 50 grid points distributed between -2 and 2 with equal spacing:
x = np.linspace(-2, 2, num=50)

# plot the function at the grid points:
import matplotlib.pyplot as plt

plt.figure(figsize=(4, 3))
plt.plot(x, f(x), linestyle='-', color='red', marker='.')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.grid(True)
plt.show()

Regression

Code
n = 13                                  # number of data points
t = np.linspace(1, 10, num = n)         # time points measurements
noise = 0.2*np.random.normal(size = n)  # noise in measurement values 
y = 2 + 0.5*t + noise                   # measurement values: line + noise 

plt.figure(figsize=(5, 3))
plt.plot(t, y, 'o')
plt.xlabel('t')
plt.ylabel('y')
plt.grid(True)

Code
col_of_ones = np.ones(n)
A = np.stack((col_of_ones, t), axis = 1)
b = y.reshape(13, 1)

print(f"{A = }")
print(f"{b = }")
A = array([[ 1.  ,  1.  ],
       [ 1.  ,  1.75],
       [ 1.  ,  2.5 ],
       [ 1.  ,  3.25],
       [ 1.  ,  4.  ],
       [ 1.  ,  4.75],
       [ 1.  ,  5.5 ],
       [ 1.  ,  6.25],
       [ 1.  ,  7.  ],
       [ 1.  ,  7.75],
       [ 1.  ,  8.5 ],
       [ 1.  ,  9.25],
       [ 1.  , 10.  ]])
b = array([[2.53084062],
       [2.8218618 ],
       [3.34747429],
       [3.40429675],
       [4.3548805 ],
       [4.31680299],
       [4.44275831],
       [4.87325517],
       [5.13941056],
       [5.75393039],
       [6.73257333],
       [6.613111  ],
       [7.00708772]])
Code
# via Formel:
x_hat_1 = np.linalg.inv(A.T @ A) @ A.T @ b
print(x_hat_1)

# via Normalgleichungen:
x_hat_2 = np.linalg.solve(A.T @ A, A.T @ b)
print(x_hat_2)

# via lstsq:
x_hat_3 = np.linalg.lstsq(A, b, rcond=None)[0]
print(x_hat_3)
[[1.95710635]
 [0.50204057]]
[[1.95710635]
 [0.50204057]]
[[1.95710635]
 [0.50204057]]
Code
# Fit A*x_hat:
y_hat = A@x_hat_1

plt.figure(figsize=(5, 3))
plt.plot(t, y, 'o', label='data')
plt.plot(t, y_hat, '.-', label='fit')
plt.xlabel('t')
plt.ylabel('y')
plt.legend(loc='best')
plt.grid(True)

For-Schleife

Zinseszinsrechnung:

Code
B_0 = 1000.0  # initial balance in EUR
q = 1.05      # interest rate factor
n = 5         # number of years

# range: start 1 is included, stop n + 1 is excluded!
for i in np.arange(1, n + 1, 1):
    B_i = B_0*q**i
    print(f"Balance after {i} years = {B_i:.2f} EUR.")
Balance after 1 years = 1050.00 EUR.
Balance after 2 years = 1102.50 EUR.
Balance after 3 years = 1157.63 EUR.
Balance after 4 years = 1215.51 EUR.
Balance after 5 years = 1276.28 EUR.

While-Schleife

Wir berechnen die Fakultät einer natürlichen Zahl \(n > 0\):

Code
n = 10
f = 1  # initial value for factorial n!
k = n  # initial decreasing number k
while k > 0:
    print(f"{k = }")
    f = f*k
    k = k - 1

print(f"{n}! = {f}")
k = 10
k = 9
k = 8
k = 7
k = 6
k = 5
k = 4
k = 3
k = 2
k = 1
10! = 3628800

If-Elif-Else Abfrage

Wir bestimmen das Vorzeichen von ein paar Zahlen:

Code
numbers = np.arange(-3, 4, 1)
for n in numbers:
    if n > 0:
        print(f"{n} hat das Vorzeichen +.")
    elif n == 0:
        print(f"{n} hat kein Vorzeichen.")
    else:
        print(f"{n} hat das Vorzeichen -.")
-3 hat das Vorzeichen -.
-2 hat das Vorzeichen -.
-1 hat das Vorzeichen -.
0 hat kein Vorzeichen.
1 hat das Vorzeichen +.
2 hat das Vorzeichen +.
3 hat das Vorzeichen +.

Beachte: Eine If-Elif-Else Abfrage muss nicht zwingend elif oder else Teile haben.

Fußnoten

  1. Sparsamer ist die minimale Version Miniconda, die jedoch nur Terminal-basiert ist.↩︎