algorithmische grundlagen einführung in das programmieren ... · 4.6 das small-world-problem und...
Post on 27-Jun-2020
2 Views
Preview:
TRANSCRIPT
Algorithmische Grundlagen
–
Einfuhrung in das Programmieren
mit Python
(Teil 1)
Sommersemester 2019
Martin Mundhenk
Uni Jena, Institut fur Informatik
4. Juli 2019
Vorlesung Algorithmische Grundlagen
(Sommer 2019)
Die Vorlesung/Ubung orientiert sich am Buch
Introduction to Programming in Python – An Interdisciplinary Approach
von Robert Sedgewick, Kevin Wayne und Robert Dondero
(Addison Wesley, 2015)
Auch die Webseite zum Buch
http://introcs.cs.princeton.edu/python/home/
ist fur diese Vorlesung nutzlich.
Organisatorisches zum Erwerb von Leistungspunktenhttp://www.complexity.uni-jena.de/Python1
§ Vorlesung montags, 16-18 Uhr, oder mittwochs, 12-14 Uhr, Raum 3325, Ernst-Abbe-Platz 2.§ Ubung donnerstags, 8-10 Uhr, Raum 3410 (Linux-Pool 2), EAP2.
Zur Teilnahme brauchen Sie eine Nutzerkennung beim KSZ!(KSZ: Kompetenz- und Servicezentrum der Fakultat fur Mathematik und Informatik,
Ernst-Abbe-Platz 2, 4.Stock (ehemals: Fakultatsrechenzentrum))
§ Es gibt ein wochentliches Ubungsblatt (ca. 12).Abgabe ist montags 16 Uhr (an pythonkurs@uni-jena.de).
§ Zur Zulassung zur Modulprufung mussen jeweils mindestens 50% der Punkte derUbungsblatter aus der ersten und der zweiten Semesterhalfte erreicht sein.
§ Die Abschlussprufung ist mundlich und dauert ca. 30 Minuten.Sie besteht aus der Vorstellung eines Programmierprojekts. Alle Dateien dazu mussen bisspatestens 30 Stunden vor Beginn der Prufung per Email bei mir angekommen sein(pythonkurs@uni-jena.de).Prufungstermine sind ab August und werden noch bekannt gegeben.
Inhaltsverzeichnis (vorlaufig)
1. Elemente des Programmierens1.2 Grundlegende Daten-Typen1.3 Verzweigungen und Schleifen1.4 Arrays1.5 Ein- und Ausgabe1.6 Dictionaries und Abschluss-Beispiel Page Rank
2. Funktionen und Module2.1 Definition von Funktionen2.2 Module und Klienten2.3 Rekursion
3. Objekt-orientierte Programmierung (erste Schritte)3.1 Benutzung von Daten-Typen
4. Algorithmen4.1 Rechenzeit4.6 Das Small-World-Problem und die Suche nach Wegen in Netzwerken
Die Nummerierung der Kapitel 1, 2 und 4 entspricht (fast) der Nummerierung im Buch von Sedgewick et al.
0.0.4
1 Elemente des Programmierens
Ein Programm zu schreiben ist nicht schwieriger,
als einen Aufsatz zu schreiben.
Wir schauen uns die Grundbausteine von Programmen der Programmiersprache Python an und
starten mit dem Programmieren.
1. Elemente des Programmierens
1.2 Grundlegende Daten-Typen
1.3 Verzweigungen und Schleifen
1.4 Arrays
1.5 Ein- und Ausgabe
1.6 Dictionaries und Abschluss-Beispiel Page Rank
Vorlesung 01
1. Elemente des Programmierens
1.2 Grundlegende Daten-TypenDas erste Programm
Datentyp int – ganze Zahlen
Datentyp str – Zeichenfolgen
Datentyp bool – Wahrheitswerte
Datentyp float – Dezimalbruche
Anhang
1.3 Verzweigungen und Schleifen
1.4 Arrays
1.5 Ein- und Ausgabe
1.6 Dictionaries und Abschluss-Beispiel Page Rank
1.2.1
1.2 Grundlegende Datentypen
Programme dienen der Verarbeitung von Daten.
Die elementaren Arten von Daten fur die Programmiersprache Python sind
§ Zahlen,
§ Texte und
§ Wahrheitswerte.
Zu ihrer Verarbeitung sind verschiedene Grund-Operationen verfugbar
(und sie werden intern unterschiedlich behandelt).
1.2.2
1 Berechne Volumen und Oberflache eines Quaders
Breite Tiefe
Hoh
e
Volumen = Breite ¨ Hohe ¨ Tiefe (es werden ganze Zahlen benutzt)
Oberflache = 2 ¨ Breite ¨ Hohe + 2 ¨ Breite ¨ Tiefe + 2 ¨ Hohe ¨ Tiefe= 2 ¨ ( Breite ¨ Hohe + Breite ¨ Tiefe + Hohe ¨ Tiefe )
Erstes Programm-Beispiel 1.2.3
1 Berechne Volumen und Oberflache eines Quaders
Breite Tiefe
Hoh
e
Volumen = Breite ¨ Hohe ¨ Tiefe (es werden ganze Zahlen benutzt)
Oberflache = 2 ¨ Breite ¨ Hohe + 2 ¨ Breite ¨ Tiefe + 2 ¨ Hohe ¨ Tiefe= 2 ¨ ( Breite ¨ Hohe + Breite ¨ Tiefe + Hohe ¨ Tiefe )
Erstes Programm-Beispiel 1.2.3
1 Berechne Volumen und Oberflache eines Quaders
Breite Tiefe
Hoh
e
Volumen = Breite ¨ Hohe ¨ Tiefe (es werden ganze Zahlen benutzt)
Oberflache =
2 ¨ Breite ¨ Hohe + 2 ¨ Breite ¨ Tiefe + 2 ¨ Hohe ¨ Tiefe= 2 ¨ ( Breite ¨ Hohe + Breite ¨ Tiefe + Hohe ¨ Tiefe )
Erstes Programm-Beispiel 1.2.3
1 Berechne Volumen und Oberflache eines Quaders
Breite TiefeBreite
Hoh
e
Volumen = Breite ¨ Hohe ¨ Tiefe (es werden ganze Zahlen benutzt)
Oberflache = 2 ¨ Breite ¨ Hohe
+ 2 ¨ Breite ¨ Tiefe + 2 ¨ Hohe ¨ Tiefe= 2 ¨ ( Breite ¨ Hohe + Breite ¨ Tiefe + Hohe ¨ Tiefe )
Erstes Programm-Beispiel 1.2.3
1 Berechne Volumen und Oberflache eines Quaders
Breite Tiefe
Volumen = Breite ¨ Hohe ¨ Tiefe (es werden ganze Zahlen benutzt)
Oberflache = 2 ¨ Breite ¨ Hohe + 2 ¨ Breite ¨ Tiefe
+ 2 ¨ Hohe ¨ Tiefe= 2 ¨ ( Breite ¨ Hohe + Breite ¨ Tiefe + Hohe ¨ Tiefe )
Erstes Programm-Beispiel 1.2.3
1 Berechne Volumen und Oberflache eines Quaders
Tiefe
Hoh
e
Volumen = Breite ¨ Hohe ¨ Tiefe (es werden ganze Zahlen benutzt)
Oberflache = 2 ¨ Breite ¨ Hohe + 2 ¨ Breite ¨ Tiefe + 2 ¨ Hohe ¨ Tiefe
= 2 ¨ ( Breite ¨ Hohe + Breite ¨ Tiefe + Hohe ¨ Tiefe )
Erstes Programm-Beispiel 1.2.3
1 Berechne Volumen und Oberflache eines Quaders
Breite Tiefe
Hoh
e
Volumen = Breite ¨ Hohe ¨ Tiefe (es werden ganze Zahlen benutzt)
Oberflache = 2 ¨ Breite ¨ Hohe + 2 ¨ Breite ¨ Tiefe + 2 ¨ Hohe ¨ Tiefe= 2 ¨ ( Breite ¨ Hohe + Breite ¨ Tiefe + Hohe ¨ Tiefe )
Erstes Programm-Beispiel 1.2.3
Ein erstes Python-Programm
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
Hoehe = 5
Breite = 12
Tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
Volumen = Breite * Hoehe * Tiefe
Oberflaeche = 2 * ( Breite*Hoehe + Breite*Tiefe + Hoehe*Tiefe )
# Die berechneten Werte werden ausgegeben.
print(Volumen)
print(Oberflaeche)
Erstes Programm-Beispiel 1.2.4
Ein erstes Python-Programm
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
Hoehe = 5
Breite = 12
Tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
Volumen = Breite * Hoehe * Tiefe
Oberflaeche = 2 * ( Breite*Hoehe + Breite*Tiefe + Hoehe*Tiefe )
# Die berechneten Werte werden ausgegeben.
print(Volumen)
print(Oberflaeche)
Kommentar beginnt mit”#“. Von dort ab wird die Zeile ignoriert (. . . )
Erstes Programm-Beispiel 1.2.4
Ein erstes Python-Programm
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
Hoehe = 5
Breite = 12
Tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
Volumen = Breite * Hoehe * Tiefe
Oberflaeche = 2 * ( Breite*Hoehe + Breite*Tiefe + Hoehe*Tiefe )
# Die berechneten Werte werden ausgegeben.
print(Volumen)
print(Oberflaeche)
Hoehe, Breite, Tiefe, Oberflaeche und Volumen sind Variablen.Erstes Programm-Beispiel 1.2.4
Ein erstes Python-Programm
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
Hoehe = 5
Breite = 12
Tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
Volumen = Breite * Hoehe * Tiefe
Oberflaeche = 2 * ( Breite*Hoehe + Breite*Tiefe + Hoehe*Tiefe )
# Die berechneten Werte werden ausgegeben.
print(Volumen)
print(Oberflaeche)
Hoehe = . . . weist der Variablen Hoehe den Wert von . . . zu.Erstes Programm-Beispiel 1.2.4
Ein erstes Python-Programm
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
Hoehe = 5
Breite = 12
Tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
Volumen = Breite * Hoehe * Tiefe
Oberflaeche = 2 * ( Breite*Hoehe + Breite*Tiefe + Hoehe*Tiefe )
# Die berechneten Werte werden ausgegeben.
print(Volumen)
print(Oberflaeche)
Steht eine Variable nicht links von =, dann wird ihr Wert benutzt.Erstes Programm-Beispiel 1.2.4
Ein erstes Python-Programm
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
Hoehe = 5
Breite = 12
Tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
Volumen = Breite * Hoehe * Tiefe
Oberflaeche = 2 * ( Breite*Hoehe + Breite*Tiefe + Hoehe*Tiefe )
# Die berechneten Werte werden ausgegeben.
print(Volumen)
print(Oberflaeche)
Das Programm rechnet mit ganzen Zahlen und benutzt die Operatoren + und * .Erstes Programm-Beispiel 1.2.4
Ein erstes Python-Programm
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = breite * hoehe * tiefe
oberflaeche = 2 * ( breite*hoehe + breite*tiefe + hoehe*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
Konvention: Variablennamen beginnen mit kleinen Buchstaben.Erstes Programm-Beispiel 1.2.5
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe
5
breite
12
tiefe
32
volumen
1920
oberflaeche
1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe
5
breite
12
tiefe
32
volumen
1920
oberflaeche
1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe
5
breite
12
tiefe
32
volumen
1920
oberflaeche
1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite
12
tiefe
32
volumen
1920
oberflaeche
1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite
12
tiefe
32
volumen
1920
oberflaeche
1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite 12
tiefe
32
volumen
1920
oberflaeche
1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite 12
tiefe
32
volumen
1920
oberflaeche
1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite 12
tiefe 32
volumen
1920
oberflaeche
1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefevolumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite 12
tiefe 32
volumen
1920
oberflaeche
1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefevolumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite 12
tiefe 32
volumen 1920
oberflaeche
1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite 12
tiefe 32
volumen 1920
oberflaeche
1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite 12
tiefe 32
volumen 1920
oberflaeche 1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite 12
tiefe 32
volumen 1920
oberflaeche 1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)print(volumen)
print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite 12
tiefe 32
volumen 1920
oberflaeche 1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite 12
tiefe 32
volumen 1920
oberflaeche 1208
Erstes Programm-Beispiel 1.2.6
Was beim Start des Programms passiert . . . (sehr grobe Vorstellung)
Das Programm legt eine Folge von Anweisungen fest.Jede Anweisung liest und/oder schreibt im Speicher des Rechners.
hoehe = 5
breite = 12
tiefe = 32
volumen = breite * hoehe * tiefe
oberflaeche = 2*(breite*hoehe + breite*tiefe + hoehe*tiefe)
print(volumen)
print(oberflaeche)print(oberflaeche)
Beim Start des Programms werden die Anweisungen inder vorgegebenen Reihenfolge ausgefuhrtund der Speicher wird entsprechend verandert.
$ python3 oberflaeche v1.py
1920
1208
Einfache Vorstellung vom Speicher:
Variable Wert
hoehe 5
breite 12
tiefe 32
volumen 1920
oberflaeche 1208
Erstes Programm-Beispiel 1.2.6
2 Der Datentyp intinteger, ganze Zahlen
Literale (vom Typ int in Python-Programmen):
2019
2346283472947294
-1263516
0
Datentyp int 1.2.7
Der Datentyp intinteger, ganze Zahlen
Operatoren: + Addition 2+3
- Subtraktion, Vorzeichen 2-3, -2
* Multiplikation 2*3
** Potenz 2**3
// ganzzahlige Division 17//4
% Rest bei ganzzahliger Division, modulo 17%4
Funktionen: abs( ) Betrag eines int-Wertes abs(-17)
max( , ) Maximum zweier int-Werte max(17,4)
min( , ) Minimum zweier int-Werte min(17,4)
Datentyp int 1.2.8
Ausdrucke vom Typ int
bestehen aus
§ Literalen vom Typ int
§ Variablen, die an Objekte vom Typ int gebunden sind (s.u.)§ den Operatoren + - * ** // %
§ Klammern ( und )
§ Funktionen vom Typ int . . .
und werden zu einem Objekt vom Typ int ausgewertet.
Beispiele fur int-Ausdrucke ohne Variablen:60 * 60 * 24
(52-6)*40
max(32,17) + min(28, max(2,4))
(5+7)**2
5**2 + 2*5*7 + 7**max(9,12)Datentyp int 1.2.9
Operator // (ganzzahlige Division)
a // b ist die großte ganze Zahl kleiner oder gleich ab
:
17 // 6 ist 2 (da 176 “ 2` 5
6 ),
und -17 // 6 ist -3 (da ´176 “ ´3` 1
6 ).
Mathematische Schreibweise fur die ganzzahlige Division:
a // b entspricht t ab u
txu ist die großte ganze Zahl ď x (”untere Gaußklammer“)
Datentyp int 1.2.10
Operator % (modulo-Operator)
a % b ist der Rest bei der ganzzahligen Division von a durch b (fur positive Zahlen).
17 % 6 ist 5 (da 17 “ 2 ¨ 6` 5)und -17 % 6 ist 1 (da ´17 “ ´3 ¨ 6` 1).
Mathematische Schreibweise fur a % b ist a mod b .
Es gilt: a “ b ¨ t ab u` pa mod bq .
Beispiele fur int-Ausdrucke aus Literalen:
abs((16*60+15)-(17*60+45))//60
abs((16*60+15)-(17*60+45))%60
Die Operatoren haben unterschiedliche Bindungsstarke(entsprechend
”Punktrechnung geht vor Strichrechnung“).
Im Zweifel: Klammern setzen . . . Datentyp int 1.2.11
Weitere Beispiele fur int-Ausdrucke (mit int-Variablen (farbig notiert)):
hh * 60 * 60 + mm * 60 + sec
(52 - 6) * 40 // LP_pro_Jahr
(1+5*((jahr-1)%4)+4*((jahr-1)%100)+6*((jahr-1)%400))%7
Datentyp int 1.2.12
Anweisungen
Eine Anweisung besteht aus einer Variablen, = und einem Ausdruck.
Beispiele: jahr = 2019
jahr = jahr + 1
Beim Abarbeiten einer Anweisung, deren Wert einen grundlegenden Datentyp hat, wird§ zuerst der Ausdruck ausgewertet
und ein Objekt mit Typ und Wert des Ausdrucks erzeugt, und§ danach wird die Variable an das Objekt gebunden.
2019jahr
Variable ObjektBindung
(Objekt-Referenz)
2020
Datentyp int 1.2.13
Anweisungen
Eine Anweisung besteht aus einer Variablen, = und einem Ausdruck.
Beispiele: jahr = 2019
jahr = jahr + 1
Beim Abarbeiten einer Anweisung, deren Wert einen grundlegenden Datentyp hat, wird§ zuerst der Ausdruck ausgewertet
und ein Objekt mit Typ und Wert des Ausdrucks erzeugt, und§ danach wird die Variable an das Objekt gebunden.
jahr = 2019erzeugt ein Objekt mit Wert 2019 vom Typ int, und bindet jahr daran
2019
jahr
Variable
ObjektBindung
(Objekt-Referenz)
2020
Datentyp int 1.2.13
Anweisungen
Eine Anweisung besteht aus einer Variablen, = und einem Ausdruck.
Beispiele: jahr = 2019
jahr = jahr + 1
Beim Abarbeiten einer Anweisung, deren Wert einen grundlegenden Datentyp hat, wird§ zuerst der Ausdruck ausgewertet
und ein Objekt mit Typ und Wert des Ausdrucks erzeugt, und§ danach wird die Variable an das Objekt gebunden.
jahr = 2019erzeugt ein Objekt mit Wert 2019 vom Typ int, und bindet jahr daran
2019jahr
Variable Objekt
Bindung(Objekt-Referenz)
2020
Datentyp int 1.2.13
Anweisungen
Eine Anweisung besteht aus einer Variablen, = und einem Ausdruck.
Beispiele: jahr = 2019
jahr = jahr + 1
Beim Abarbeiten einer Anweisung, deren Wert einen grundlegenden Datentyp hat, wird§ zuerst der Ausdruck ausgewertet
und ein Objekt mit Typ und Wert des Ausdrucks erzeugt, und§ danach wird die Variable an das Objekt gebunden.
jahr = 2019erzeugt ein Objekt mit Wert 2019 vom Typ int, und bindet jahr daran
2019jahr
Variable ObjektBindung
(Objekt-Referenz)
2020
Datentyp int 1.2.13
Anweisungen
Eine Anweisung besteht aus einer Variablen, = und einem Ausdruck.
Beispiele: jahr = 2019
jahr = jahr + 1
Beim Abarbeiten einer Anweisung, deren Wert einen grundlegenden Datentyp hat, wird§ zuerst der Ausdruck ausgewertet
und ein Objekt mit Typ und Wert des Ausdrucks erzeugt, und§ danach wird die Variable an das Objekt gebunden.
jahr = 2019
jahr = jahr + 1
erzeugt ein Objekt mit Wert jahr+1 vom Typ int, und bindet jahr daran
2019jahr
Variable ObjektBindung
(Objekt-Referenz)
2020
Datentyp int 1.2.13
Anweisungen
Eine Anweisung besteht aus einer Variablen, = und einem Ausdruck.
Beispiele: jahr = 2019
jahr = jahr + 1
Beim Abarbeiten einer Anweisung, deren Wert einen grundlegenden Datentyp hat, wird§ zuerst der Ausdruck ausgewertet
und ein Objekt mit Typ und Wert des Ausdrucks erzeugt, und§ danach wird die Variable an das Objekt gebunden.
jahr = 2019
jahr = jahr + 1
erzeugt ein Objekt mit Wert jahr+1 vom Typ int, und bindet jahr daran
2019jahr
Variable ObjektBindung
(Objekt-Referenz)
2020
Datentyp int 1.2.13
Anweisungen
Eine Anweisung besteht aus einer Variablen, = und einem Ausdruck.
Beispiele: jahr = 2019
jahr = jahr + 1
Beim Abarbeiten einer Anweisung, deren Wert einen grundlegenden Datentyp hat, wird§ zuerst der Ausdruck ausgewertet
und ein Objekt mit Typ und Wert des Ausdrucks erzeugt, und§ danach wird die Variable an das Objekt gebunden.
jahr = 2019
jahr = jahr + 1
erzeugt ein Objekt mit Wert jahr+1 vom Typ int, und bindet jahr daran
2019jahr
Variable ObjektBindung
(Objekt-Referenz)
2020
Datentyp int 1.2.13
Weitere Beispiele fur Anweisungen:
w = (1+5*((jahr-1)%4)+4*((jahr-1)%100)+6*((jahr-1)%400))%7
arbeitsstundenProLP = (52 - 6) * 40 // LP_pro_Jahr
zaehler = zaehler + 1
zaehler += 1
Datentyp int 1.2.14
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
#-----------------------------------------------------------------
# python3 oberflaeche.py
# 1920
# 1208
hoehe
breite
tiefe
volumen
oberflaeche
5
12
32
1920
1208
Datentyp int 1.2.15
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
#-----------------------------------------------------------------
# python3 oberflaeche.py
# 1920
# 1208
hoehe
breite
tiefe
volumen
oberflaeche
5
12
32
1920
1208
Datentyp int 1.2.15
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
#-----------------------------------------------------------------
# python3 oberflaeche.py
# 1920
# 1208
hoehe
breite
tiefe
volumen
oberflaeche
5
12
32
1920
1208
Datentyp int 1.2.15
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
#-----------------------------------------------------------------
# python3 oberflaeche.py
# 1920
# 1208
hoehe
breite
tiefe
volumen
oberflaeche
5
12
32
1920
1208
Datentyp int 1.2.15
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
#-----------------------------------------------------------------
# python3 oberflaeche.py
# 1920
# 1208
hoehe
breite
tiefe
volumen
oberflaeche
5
12
32
1920
1208
Datentyp int 1.2.15
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
#-----------------------------------------------------------------
# python3 oberflaeche.py
# 1920
# 1208
hoehe
breite
tiefe
volumen
oberflaeche
5
12
32
1920
1208
Datentyp int 1.2.15
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
#-----------------------------------------------------------------
# python3 oberflaeche.py
# 1920
# 1208
hoehe
breite
tiefe
volumen
oberflaeche
5
12
32
1920
1208
Datentyp int 1.2.15
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
#-----------------------------------------------------------------
# python3 oberflaeche.py
# 1920
# 1208
hoehe
breite
tiefe
volumen
oberflaeche
5
12
32
1920
1208
Datentyp int 1.2.15
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
#-----------------------------------------------------------------
# python3 oberflaeche.py
# 1920
# 1208
hoehe
breite
tiefe
volumen
oberflaeche
5
12
32
1920
1208
Datentyp int 1.2.15
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
#-----------------------------------------------------------------
# python3 oberflaeche.py
# 1920
# 1208
hoehe
breite
tiefe
volumen
oberflaeche
5
12
32
1920
1208
Datentyp int 1.2.15
#-----------------------------------------------------------------
# oberflaeche_v1.py
#-----------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
#-----------------------------------------------------------------
# Zuerst werden die Maße des Quaders angegeben.
hoehe = 5
breite = 12
tiefe = 32
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print(volumen)
print(oberflaeche)
#-----------------------------------------------------------------
# python3 oberflaeche.py
# 1920
# 1208
hoehe
breite
tiefe
volumen
oberflaeche
5
12
32
1920
1208
Datentyp int 1.2.15
3 Der Datentyp strstring, Zeichenfolgen
. . . dient dem Verarbeiten von Texten (das betrifft auch Ein- und Ausgabe).
Die Literale vom Typ str sind Folgen von Zeichen,
die durch ' ... ' oder " ... " eingeschlossen sind.
'Das ist ein str-Literal.' '1234'
Es gibt”spezielle“ Zeichen wie z.B. den Zeilenumbruch \n.
print('Zeile 1\nZeile 2')
liefert die Ausgabe
Zeile1
Zeile2
Achtung: das Literal 1234 ist vom Typ int
das Literal '1234' ist vom Typ strDatentyp str 1.2.16
3 Der Datentyp strstring, Zeichenfolgen
. . . dient dem Verarbeiten von Texten (das betrifft auch Ein- und Ausgabe).
Die Literale vom Typ str sind Folgen von Zeichen,
die durch ' ... ' oder " ... " eingeschlossen sind.
'Das ist ein str-Literal.' '1234'
Es gibt”spezielle“ Zeichen wie z.B. den Zeilenumbruch \n.
print('Zeile 1\nZeile 2')
liefert die Ausgabe
Zeile1
Zeile2
Achtung: das Literal 1234 ist vom Typ int
das Literal '1234' ist vom Typ strDatentyp str 1.2.16
3 Der Datentyp strstring, Zeichenfolgen
. . . dient dem Verarbeiten von Texten (das betrifft auch Ein- und Ausgabe).
Die Literale vom Typ str sind Folgen von Zeichen,
die durch ' ... ' oder " ... " eingeschlossen sind.
'Das ist ein str-Literal.' '1234'
Es gibt”spezielle“ Zeichen wie z.B. den Zeilenumbruch \n.
print('Zeile 1\nZeile 2')
liefert die Ausgabe
Zeile1
Zeile2
Achtung: das Literal 1234 ist vom Typ int
das Literal '1234' ist vom Typ strDatentyp str 1.2.16
Der Datentyp strOperatoren + *
Die Operation + schreibt Strings hintereinander (Konkatenation).
Der Ausdruck 'Das ist ' + 'ein Satz.'
ergibt den String 'Das ist ein Satz.' .
Die Operation * ist eine Operation zwischen str und int.
Der Ausdruck 'Ole' * 4
ergibt den String 'OleOleOleOle'.
Datentyp str 1.2.17
Beispiel: Gib die Einteilungsmarken auf einem Zollstock aus
Die Striche sind im Millimeter-Abstand.Alle 5mm ist der Strich langer, und alle 10mm ist der Strich noch langer.
Beispiel fur die ersten 29 Striche:
| |
| | | | |
|||||||||||||||||||||||||||||
Datentyp str 1.2.18
Beispiel: Gib die Einteilungsmarken auf einem Zollstock aus
Die Striche sind im Millimeter-Abstand.Alle 5mm ist der Strich langer, und alle 10mm ist der Strich noch langer.
Beispiel fur die ersten 29 Striche:
| |
| | | | |
|||||||||||||||||||||||||||||
unterste Zeile : male 29 Striche '|' * 29
vorletzte Zeile : male 4 Leerzeichen und einen Strich,bis 29 Zeichen gemalt wurden ' |' * (29//5)
vorvorletzte Zeile : male 9 Leerzeichen und einen Strich,bis 29 Zeichen gemalt wurden ' |' * (29//10)
Datentyp str 1.2.18
#--------------------------------------------------------------------------------
# einteilungsmarken.py
#--------------------------------------------------------------------------------
# Die Variable laenge gibt die Lange des Zollstocks in Millimeter an.
laenge = 79
# Die Variable untersteZeile besteht aus den Millimeter-Strichen des Zollstocks.
untersteZeile = '|' * laenge
# Die Variable vorletzteZeile besteht aus 5-Millimeter-Strichen.
vorletzteZeile = ' |' * ( laenge//5 )
# Die Variable vorvorletzteZeile besteht aus 10-Millimeter-Strichen.
vorvorletzteZeile = ((' '*9) + '|') * (laenge//10)
# Die Einteilungsmarken werden ausgegeben.
print(vorvorletzteZeile)
print(vorletzteZeile)
print(untersteZeile)
#----------------------------------------------------------------------------------
# python3 einteilungsmarken.py 79
# | | | | | | |
# | | | | | | | | | | | | | | |
# |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Datentyp str 1.2.19
int-Werte zu str-Werten umwandeln
Um den Wert eines Ausdrucks a mit print(a) ausgeben zu konnen,muss a vom Typ str sein oder in ein Objekt vom Typ str umgewandelt werden konnen.
Die Funktion str(x) macht aus einem Objekt x eines grundlegenden Datentyps ein Objekt vomTyp str
”mit dem entsprechenden Wert“. Z.B. liefert str(123) den String '123'.
#--------------------------------------------------------------------
# oberflaeche_v2.py
#--------------------------------------------------------------------
hoehe = 5
breite = 12
tiefe = 32
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print('Das Volumen des Quaders ist ' + str(volumen) + '.')
print('Die Oberflache des Quaders ist ' + str(oberflaeche) + '.')
#---------------------------------------------------------------------
# python3 oberflaeche_v2.py
# Das Volumen des Quaders ist 1920.
# Die Oberflache des Quaders ist 1208.Datentyp str 1.2.20
Eingaben von der Kommandozeile lesen
Beim Starten eines Programms konnen Argumente von der Kommandozeile an das Programmubergeben werden – sie sind stets vom Typ str.
#-------------------------------------------------------------------------
# einundausgabe.py
#-------------------------------------------------------------------------
# Lies drei (durch Leerzeichen getrennte) Strings von der Kommandozeile
# und gib sie in umgekehrter Reihenfolge wieder aus (auf standard output).
#-------------------------------------------------------------------------
import sys
a = sys.argv[1]
b = sys.argv[2]
c = sys.argv[3]
print( c + ' ' + b + ' ' + a )
#------------------------------------------------------
# python3 einundausgabe.py Hallo Martin .
# . Martin Hallo
#
Datentyp str 1.2.21
Eingaben von der Kommandozeile lesen
Beim Starten eines Programms konnen Argumente von der Kommandozeile an das Programmubergeben werden – sie sind stets vom Typ str.
#-------------------------------------------------------------------------
# einundausgabe.py
#-------------------------------------------------------------------------
# Lies drei (durch Leerzeichen getrennte) Strings von der Kommandozeile
# und gib sie in umgekehrter Reihenfolge wieder aus (auf standard output).
#-------------------------------------------------------------------------
import sys
a = sys.argv[1]
b = sys.argv[2]
c = sys.argv[3]
print( c + ' ' + b + ' ' + a )
#------------------------------------------------------
# python3 einundausgabe.py Hallo Martin .
# . Martin Hallo
#
# python3 einundausgabe.py 1 zwei 3.0
# 3.0 zwei 1
#
# python3 einundausgabe.py 1 2 3 4
# 3 2 1
#
# python3 einundausgabe.py 1 2
# Traceback (most recent call last):
# File "einundausgabe.py", line 12, in <module>
# c = sys.argv[3]
# IndexError: list index out of range
Datentyp str 1.2.21
str-Werte zu int-Werten umwandeln
Entsprechend str( ) macht die Funktion int( ) aus einem Objekt ein int-Objekt.Z.B. liefert int('123') ein int-Objekt mit Wert 123.
#--------------------------------------------------------------------------
# oberflaeche_v3.py
#--------------------------------------------------------------------------
# Lies Hohe, Breite und Tiefe (int) eines Quaders von der Kommandozeile ein
# und gib das Volumen und die Oberflache des Quaders aus.
#--------------------------------------------------------------------------
import sys
# Die Maße des Quaders werden von der Kommandozeile eingelesen.
hoehe = int(sys.argv[1])
breite = int(sys.argv[2])
tiefe = int(sys.argv[3])
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print('Das Volumen des Quaders ist ' + str(volumen) + '.')
print('Die Oberflache des Quaders ist ' + str(oberflaeche) + '.')
# python3 oberflaeche_v3.py 5 12 32
# Das Volumen des Quaders ist 1920.
# Die Oberflache des Quaders ist 1208.
#
# python3 oberflaeche_v3.py 12 34 56
# Das Volumen des Quaders ist 22848.
# Die Oberflache des Quaders ist 5968.
Datentyp str 1.2.22
4 Der Datentyp boolboolean, Wahrheitswerte (George Boole, 1815-1864)
. . . dient dem Rechnen mit Wahrheitswerten True und False.
Literale sind True (fur den Wahrheitswert wahr)
False (fur den Wahrheitswert falsch)
Datentyp bool 1.2.23
Operationen fur Ausdrucke vom Typ bool
Es gibt die 2-stelligen Operation and und or, und die 1-stellige Operation not auf bool-Objekten.
Das Ergebnis ist vom Typ bool.
Die folgenden Tabellen beschreiben die Operationen.
a b a and b
False False False
False True False
True False False
True True True
a b a or b
False False False
False True True
True False True
True True True
a not a
False True
True False
Beispiele fur Ausdrucke und deren Werte:
True and (False or True) hat den Wert True.
(False or not (True and False)) and False hat den Wert False.Datentyp bool 1.2.24
Beispiel: bestimme, ob ein Jahr ein Schaltjahr ist
Schaltjahre werden nach dem Gregorianischen Kalender wie folgt bestimmt:
1. Die (ohne Rest) durch 4 teilbaren Jahre sind Schaltjahre.
2. Die (ohne Rest) durch 100 teilbaren Jahre sind keine Schaltjahre.Damit sind z.B. 1800, 1900, 2000, 2100 und 2200 keine Schaltjahre.
3. Aber die (ohne Rest) durch 400 teilbaren Jahre sind doch Schaltjahre.Damit sind z.B. 1600, 2000 und 2400 doch wieder Schaltjahre.
Jahr x ist also ein Schaltjahr genau dann, wenn
§ x ist durch 4 teilbar und nicht durch 100 teilbar, oder
§ x ist durch 400 teilbar.
Datentyp bool 1.2.25
Verzweigung des Programmflusses – if
Lies das Jahr von der Kommandozeile.Berechne, ob das Jahr durch 4, durch 100 bzw. durch 400 teilbar ist.Berechne, ob das Jahr die Bedingungs-Kombination fur ein Schaltjahr erfullt.
Ist das Jahr ein Schaltjahr?
Gib aus, dass das Jahr ein Schaltjahr ist. Gib aus, dass das Jahr kein Schaltjahr ist.
Gib noch eine Leerzeile aus.
ja nein
Datentyp bool 1.2.26
Verzweigung des Programmflusses – if
jahr = int(sys.argv[1])
Berechne, ob das Jahr durch 4, durch 100 bzw. durch 400 teilbar ist.Berechne, ob das Jahr die Bedingungs-Kombination fur ein Schaltjahr erfullt.
Ist das Jahr ein Schaltjahr?
Gib aus, dass das Jahr ein Schaltjahr ist. Gib aus, dass das Jahr kein Schaltjahr ist.
Gib noch eine Leerzeile aus.
ja nein
Datentyp bool 1.2.26
Verzweigung des Programmflusses – if
jahr = int(sys.argv[1])
bedingung1 = (jahr % 4 == 0)
bedingung2 = (jahr % 100 == 0)
bedingung3 = (jahr % 400 == 0)
Berechne, ob das Jahr die Bedingungs-Kombination fur ein Schaltjahr erfullt.
Ist das Jahr ein Schaltjahr?
Gib aus, dass das Jahr ein Schaltjahr ist. Gib aus, dass das Jahr kein Schaltjahr ist.
Gib noch eine Leerzeile aus.
ja nein
Datentyp bool 1.2.26
Verzweigung des Programmflusses – if
jahr = int(sys.argv[1])
bedingung1 = (jahr % 4 == 0)
bedingung2 = (jahr % 100 == 0)
bedingung3 = (jahr % 400 == 0)
istSchaltjahr = ( bedingung1 and not bedingung2 ) or bedingung3
Ist das Jahr ein Schaltjahr?
Gib aus, dass das Jahr ein Schaltjahr ist. Gib aus, dass das Jahr kein Schaltjahr ist.
Gib noch eine Leerzeile aus.
ja nein
Datentyp bool 1.2.26
Verzweigung des Programmflusses – if
jahr = int(sys.argv[1])
bedingung1 = (jahr % 4 == 0)
bedingung2 = (jahr % 100 == 0)
bedingung3 = (jahr % 400 == 0)
istSchaltjahr = ( bedingung1 and not bedingung2 ) or bedingung3
istSchaltjahr
Gib aus, dass das Jahr ein Schaltjahr ist. Gib aus, dass das Jahr kein Schaltjahr ist.
Gib noch eine Leerzeile aus.
True False
Datentyp bool 1.2.26
Verzweigung des Programmflusses – if
jahr = int(sys.argv[1])
bedingung1 = (jahr % 4 == 0)
bedingung2 = (jahr % 100 == 0)
bedingung3 = (jahr % 400 == 0)
istSchaltjahr = ( bedingung1 and not bedingung2 ) or bedingung3
istSchaltjahr
print(str(jahr) + ’ ist ein Schaltjahr.’) Gib aus, dass das Jahr kein Schaltjahr ist.
Gib noch eine Leerzeile aus.
True False
Datentyp bool 1.2.26
Verzweigung des Programmflusses – if
jahr = int(sys.argv[1])
bedingung1 = (jahr % 4 == 0)
bedingung2 = (jahr % 100 == 0)
bedingung3 = (jahr % 400 == 0)
istSchaltjahr = ( bedingung1 and not bedingung2 ) or bedingung3
istSchaltjahr
print(str(jahr) + ’ ist ein Schaltjahr.’) print(str(jahr) + ’ ist kein Schaltjahr.’)
Gib noch eine Leerzeile aus.
True False
Datentyp bool 1.2.26
Verzweigung des Programmflusses – if
jahr = int(sys.argv[1])
bedingung1 = (jahr % 4 == 0)
bedingung2 = (jahr % 100 == 0)
bedingung3 = (jahr % 400 == 0)
istSchaltjahr = ( bedingung1 and not bedingung2 ) or bedingung3
istSchaltjahr
print(str(jahr) + ’ ist ein Schaltjahr.’) print(str(jahr) + ’ ist kein Schaltjahr.’)
print()
True False
Datentyp bool 1.2.26
# schaltjahr.py
#-------------------------------------------------------------------------
# Liest int jahr von der Kommandozeile
# und gibt aus, ob das Jahr jahr ein Schaltjahr ist.
#-------------------------------------------------------------------------
import sys
# Lies das Jahr von der Kommandozeile
# und speichere es in Variable jahr (Typ int).
jahr = int(sys.argv[1])
# Bestimme, welche der 3 Bedingungen erfullt werden
# und speichere die Ergebnisse in den Variablen
# bedingung1, bedingung2 und bedingung3 (alle vom Typ bool).
bedingung1 = (jahr % 4 == 0) # jahr ist durch 4 teilbar
bedingung2 = (jahr % 100 == 0) # jahr ist durch 100 teilbar
bedingung3 = (jahr % 400 == 0) # jahr ist durch 400 teilbar
# Bestimme, ob jahr ein Schaltjahr ist
# und speichere das Ergebnis in Variable istSchaltjahr (Typ bool).
istSchaltjahr = ( bedingung1 and not bedingung2 ) or bedingung3
# Gib das Ergebnis aus.
if istSchaltjahr:
print( str(jahr) + ' ist ein Schaltjahr.' )
else:
print( str(jahr) + ' ist kein Schaltjahr.' )
print()
# python3 schaltjahr.py 2019
# 2019 ist kein Schaltjahr.
#
# python3 schaltjahr.py 2100
# 2100 ist kein Schaltjahr.
#
# python3 schaltjahr.py 2000
# 2000 ist kein Schaltjahr.
Datentyp bool 1.2.27
Vergleichsoperationen fur Zahlenwerte liefern bool-Werte
Operator Bedeutung Beispiel
True False
== gleich 3==3 2==3
!= ungleich 2!=3 3!=3
< kleiner als 2<3 3<3
<= kleiner oder gleich 3<=3 4<=3
> großer als 4>3 3>4
>= großer oder gleich 4>=3 3>=4
Datentyp bool 1.2.28
5 Der Datentyp floatfloating point numbers, Fließkommazahlen
. . . dient dem Rechnen mit Dezimalbruchen.
Literale sind z.B. 4.0 (hat den Wert 4)
123.45 (hat den Wert 123, 45)
3.141e+6 (hat den Wert 3,141 ¨ 106 “ 3141000 )
1.234e-6 (hat den Wert 1,234 ¨ 10´6 “ 0, 000001234 )
Operatoren: + Addition- Subtraktion, Vorzeichen* Multiplikation/ Division** Potenz
Datentyp float 1.2.29
Ausdrucke vom Typ float
Kommt in einem Ausdruck mit ints ein float-Wert oder eine float-Operation vor,
dann hat das Ergebnis Typ float (und nicht Typ int).
Beispiel: i = 15 # Variable i hat Typ int
f = 1.0 * i # Variable f hat Typ float
a = 4/2 # Variable a hat Typ float, da / nur fur float definiert ist
print(i) # erzeugt Ausgabe 15
print(a) # erzeugt Ausgabe 2.0
float-Werte haben nur beschrankte Genauigkeit.
print(1.234567890123456789e+18) hat Ausgabe
1.2345678901234568e+18 (in Python3),
1.23456789012e+18 (in Python2).
Datentyp float 1.2.30
float-Werte konnen ungenau sein
int-Werte konnen beliebig groß sein — float-Werte haben nur beschrankte Stellenzahl.Das fuhrt schnell zu falschen Rechenergebnissen – also Augen auf mit float!
#----------------------------------------------------------
# fehler_mit_float.py
#----------------------------------------------------------
# Liest s (int) von der Komandozeile,
# berechnet 10**s+1 (int),
# berechnet 10.0**s+1 (float)
# und die Differenz der beiden Zahlen.
import sys
s = int(sys.argv[1])
intZahl = 10**s + 1
floatZahl = 10.0**s + 1
differenz = intZahl - floatZahl
# Die beiden Zahlen und ihre Differenz werden ausgegeben.
print( 'int Zahl: ' + str(intZahl) )
print( 'float Zahl: ' + str(floatZahl) )
print( 'Differenz : ' + str(differenz) )
#----------------------------------------------------------
#------------------------------------
# python3 fehler_mit_float.py 15
# int Zahl: 1000000000000001
# float Zahl: 1000000000000001.0
# Differenz : 0.0
#
# python3 fehler_mit_float.py 16
# int Zahl: 10000000000000001
# float Zahl: 1e+16
# Differenz : 0.0
#
# python3 fehler_mit_float.py 22
# int Zahl: 10000000000000000000001
# float Zahl: 1e+22
# Differenz : 0.0
#
# python3 fehler_mit_float.py 23
# int Zahl: 100000000000000000000001
# float Zahl: 1e+23
# Differenz : 16777216.0Datentyp float 1.2.31
Funktionen fur float
”Eingebaute“ Funktionen:
abs(x) der Betrag von x
max(x,y), min(x,y) Maximum bzw. Minimum von x und y
round(x) nachster int-Wert zu x (in Python3),nachster ganzzahliger float-Wert zu x (in Python2).
str(x), int(x), bool(x) Umwandlung in Objekt des jeweiligen Typs
Funktionen aus dem Modul math von Python:math.sqrt(x) Wurzelfunktionmath.log(x,b) Logarithmus von x zur Basis b
Funktion aus dem Modul random von Python:random.random() eine zufallige float-Zahl x mit 0 ď x ă 1
Datentyp float 1.2.32
Zusammenfassung
§ Wir haben die elementaren Daten-Typen int, float, str und bool von Python
kennengelernt.
§ Wir konnen Ausdrucke aus Literalen, Variablen, Operatoren und Funktionen schreiben und
deren Typen bestimmen.
§ Wir konnen sehr einfache Programme mit
Eingabe von Argumenten (von der Kommandozeile)
Abarbeitung einer festen Folge von Anweisungen
Ausgabe von Ergebnissen (auf dem Bildschirm)
schreiben und deren Ausfuhrung nachvollziehen.
1.2.33
Anhang: Eingabe von der Tastatur
Die Funktion input(s) gibt String s auf dem Bildschirm aus (standard output)
und hat als Wert die nachste auf der Tastatur eingegebene Zeile (Typ str),
die mit <return> beendet wird.# oberflaeche_v4.py
#--------------------------------------------------------------------
# Berechne das Volumen und die Oberflache eines Quaders.
# Die Seitenlangen des Quaders werden uber die Tastatur eingegeben.
#--------------------------------------------------------------------
# Zuerst werden die Maße des Quaders uber die Tastatur eingegeben.
print('Bitte geben Sie die Seitenlangen des Quaders an.')
hoehe = int(input('Hohe: '))
breite = int(input('Breite: '))
tiefe = int(input('Tiefe: '))
# Daraus konnen nach den bekannten Formeln
# das Volumen und die Oberflache berechnet werden.
volumen = hoehe * breite * tiefe
oberflaeche = 2 * ( hoehe*breite + hoehe*tiefe + breite*tiefe )
# Die berechneten Werte werden ausgegeben.
print('Das Volumen des Quaders ist ' + str(volumen) + '.')
print('Die Oberflache des Quaders ist ' + str(oberflaeche) + '.')
#---------------------------------------------------------------------
# python3 oberflaeche_v4.py
# Bitte geben Sie die Seitenlangen des Quaders an.
# Hohe: 123
# Breite: 456
# Tiefe: 789
# Das Volumen des Quaders ist 44253432.
# Die Oberflache des Quaders ist 1025838.
Anhang: Eingabe von der Tastatur 1.2.34
Anhang: berechne die Losungen der quadratischen
Gleichung a ¨ x2 ` b ¨ x ` c “ 0
Die quadratische Gleichung a ¨ x2 ` b ¨ x ` c “ 0 hat die Losungen
x1 “´b `
?b2 ´ 4 ¨ a ¨ c
2 ¨ aund
x2 “´b ´
?b2 ´ 4 ¨ a ¨ c
2 ¨ a.
Anhang: Berechnung der Mitternachtsformel 1.2.35
Die quadratische Gleichung a ¨ x2` b ¨ x ` c “ 0 hat die Losungen x1,2 “
´b ˘
Diskriminantehkkkkkkkkikkkkkkkkj
a
b2 ´ 4 ¨ a ¨ c
2 ¨ a.
#----------------------------------------------------------------------------
# mitternacht.py
# Liest float-Werte a, b und c von der Kommandozeile ein
# und gibt die beiden durch die Mitternachtsformel bestimmten Losungen aus.
#----------------------------------------------------------------------------
import sys
import math
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
diskriminante = math.sqrt(b**2 - 4 * a * c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
#----------------------------------------------------------------------------
# python3 mitternacht.py 4 -20.3 3.141
# 4.915241838383638
# 0.15975816161636258
Anhang: Berechnung der Mitternachtsformel 1.2.36
1.3 Verzweigungen und Schleifen
Die bisher betrachteten Programme (bis auf schaltjahr.py) bestanden aus Anweisungen,
die der Reihe nach von der ersten bis zur letzten ausgefuhrt werden.
Nun werden wir sehen, wie man diese Reihenfolge beeinflussen kann.
Abhangig von Bedingungen konnen Anweisungs-Blocke ausgefuhrt oder nicht ausgefuhrt werden
(Verzweigungen),
oder Anweisungs-Blocke konnen mehrfach ausgefuhrt werden (Schleifen).
Mittels Verzweigungen und Schleifen werden wir bereits viel machtigere Programme schreiben
konnen als bisher.
Anhang: Berechnung der Mitternachtsformel 1.3.1
Vorlesung 02
1. Elemente des Programmierens
1.2 Grundlegende Daten-Typen
1.3 Verzweigungen und SchleifenVerzweigungen – if
Schleifen – while
Schleifen – for
Abschließendes Beispiel: Was Euler nicht wusste . . .
1.4 Arrays
1.5 Ein- und Ausgabe
1.6 Dictionaries und Abschluss-Beispiel Page Rank
2. Funktionen und Module
3. Objekt-orientierte Programmierung (erste Schritte)
4. Algorithmen
Anhang: Berechnung der Mitternachtsformel 1.3.2
1 Verzweigungen – ifberechne die Losungen der quadratischen Gleichung a ¨ x2
` b ¨ x ` c “ 0
Die quadratische Gleichung a ¨ x2 ` b ¨ x ` c “ 0 hat die Losungen
x “´b `
?b2 ´ 4 ¨ a ¨ c
2 ¨ aund
x “´b ´
?b2 ´ 4 ¨ a ¨ c
2 ¨ a.
if-Verzweigung 1.3.3
Die quadratische Gleichung a ¨ x2` b ¨ x ` c “ 0 hat die Losungen x “
´b ˘
Diskriminantehkkkkkkkkikkkkkkkkj
a
b2 ´ 4 ¨ a ¨ c
2 ¨ a.
#----------------------------------------------------------------------------
# mitternacht_v0.py
# Liest float-Werte a, b und c von der Kommandozeile ein
# und gibt die beiden durch die Mitternachtsformel bestimmten Losungen aus.
#----------------------------------------------------------------------------
import sys
import math
# Lies float-Werte a, b und c von der Kommandozeile ein.
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
# Berechne die Diskriminante.
diskriminante = math.sqrt(b**2 - 4 * a * c)
# Gib die Ergebnisse fur x aus.
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
#----------------------------------------------------------------------------if-Verzweigung 1.3.4
Die quadratische Gleichung a ¨ x2` b ¨ x ` c “ 0 hat die Losungen x “
´b ˘
Diskriminantehkkkkkkkkikkkkkkkkj
a
b2 ´ 4 ¨ a ¨ c
2 ¨ a.
#----------------------------------------------------------------------------
# mitternacht_v0.py
# Liest float-Werte a, b und c von der Kommandozeile ein
# und gibt die beiden durch die Mitternachtsformel bestimmten Losungen aus.
#----------------------------------------------------------------------------
import sys
import math
# Lies float-Werte a, b und c von der Kommandozeile ein.
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
# Berechne die Diskriminante.
diskriminante = math.sqrt(b**2 - 4 * a * c)
# Gib die Ergebnisse fur x aus.
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
#----------------------------------------------------------------------------
# python3 mitternacht_v0.py 4 -20.3 3.141
# 4.915241838383638
# 0.15975816161636258
#
# python3 mitternacht_v0.py 22 56.78 -11.11
# 0.1827300776950099
# -2.763639168604101
if-Verzweigung 1.3.4
Der Programmfluss . . .
Der Programmfluss besteht bei jeder Eingabe aus der gleichen Folge von Anweisungen.
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b+diskriminante) / (2*a) )
print( (-b-diskriminante) / (2*a) )
# mitternacht.py
#---------------------------------------------------------------
# Lies a, b und c (float) von der Kommandozeile ein und
# gib die durch die Mitternachtsformel bestimmten Losungen aus.
#---------------------------------------------------------------
import sys, math
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
diskriminante = math.sqrt(b**2 - 4 * a * c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
if-Verzweigung 1.3.5
Der Programmfluss . . .
Der Programmfluss besteht bei jeder Eingabe aus der gleichen Folge von Anweisungen.
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b+diskriminante) / (2*a) )
print( (-b-diskriminante) / (2*a) )
# python3 mitternacht.py 4 15 2
# -0.1384445013187745
# -3.6115554986812253
if-Verzweigung 1.3.5
Der Programmfluss . . .
Der Programmfluss besteht bei jeder Eingabe aus der gleichen Folge von Anweisungen.
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b+diskriminante) / (2*a) )
print( (-b-diskriminante) / (2*a) )
# python3 mitternacht.py 4 15 2
# -0.1384445013187745
# -3.6115554986812253
# python3 mitternacht.py 0 2 4
# Traceback (most recent call last):
# File "mitternacht.py", line 17, in <module>
# print( (-b + diskriminante) / (2*a) )
# ZeroDivisionError: float division by zero
if-Verzweigung 1.3.5
Der Programmfluss . . .
Der Programmfluss besteht bei jeder Eingabe aus der gleichen Folge von Anweisungen.
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b+diskriminante) / (2*a) )
print( (-b-diskriminante) / (2*a) )
# python3 mitternacht.py 0 2 4
# Traceback (most recent call last):
# File "mitternacht.py", line 17, in <module>
# print( (-b + diskriminante) / (2*a) )
# ZeroDivisionError: float division by zero
# python3 mitternacht.py 4 2 4
# Traceback (most recent call last):
# File "mitternacht.py", line 15, in <module>
# diskriminante = math.sqrt(b**2 - 4*a*c)
# ValueError: math domain error
if-Verzweigung 1.3.5
Der Programmfluss . . .
Der Programmfluss besteht bei jeder Eingabe aus der gleichen Folge von Anweisungen.
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b+diskriminante) / (2*a) )
print( (-b-diskriminante) / (2*a) )
# python3 mitternacht.py 0 2 4
# Traceback (most recent call last):
# File "mitternacht.py", line 17, in <module>
# print( (-b + diskriminante) / (2*a) )
# ZeroDivisionError: float division by zero
# python3 mitternacht.py 4 2 4
# Traceback (most recent call last):
# File "mitternacht.py", line 15, in <module>
# diskriminante = math.sqrt(b**2 - 4*a*c)
# ValueError: math domain error
# python3 mitternacht.py 4 4 1
# -0.5
# -0.5
if-Verzweigung 1.3.5
Der Programmfluss . . .
Der Programmfluss besteht bei jeder Eingabe aus der gleichen Folge von Anweisungen.
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b+diskriminante) / (2*a) )
print( (-b-diskriminante) / (2*a) )
# python3 mitternacht.py 0 2 4
# Traceback (most recent call last):
# File "mitternacht.py", line 17, in <module>
# print( (-b + diskriminante) / (2*a) )
# ZeroDivisionError: float division by zero
# python3 mitternacht.py 4 2 4
# Traceback (most recent call last):
# File "mitternacht.py", line 15, in <module>
# diskriminante = math.sqrt(b**2 - 4*a*c)
# ValueError: math domain error
# python3 mitternacht.py 4 4 1
# -0.5
# -0.5
Kann man die Programmabsturze etc. vermeiden?
if-Verzweigung 1.3.5
Drei Falle, die mitternacht.py nicht berucksichtigt
Fall 1:Durch 0 kann man nicht teilen.Dieser Fall tritt ein,wenn fur a auf der Kommandozeile 0 eingegeben wird.
# python3 mitternacht.py 0 2 4
# Traceback (most recent call last):
# File "mitternacht.py", line 17, in <module>
# print( (-b + diskriminante) / (2*a) )
# ZeroDivisionError: float division by zero
# mitternacht.py
#-------------------------------------------
import sys, math
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
diskriminante = math.sqrt(b**2 - 4 * a * c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
if-Verzweigung 1.3.6
Drei Falle, die mitternacht.py nicht berucksichtigt
Fall 1:Durch 0 kann man nicht teilen.Dieser Fall tritt ein,wenn fur a auf der Kommandozeile 0 eingegeben wird.
Fall 2:Aus negativen Zahlen kann man keine Wurzel ziehen.Dieser Fall tritt ein, wenn b**2 - 4*a*c kleiner als 0 ist.
# python3 mitternacht.py 4 2 4
# Traceback (most recent call last):
# File "mitternacht.py", line 15, in <module>
# diskriminante = math.sqrt(b**2 - 4*a*c)
# ValueError: math domain error
# mitternacht.py
#-------------------------------------------
import sys, math
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
diskriminante = math.sqrt(b**2 - 4 * a * c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
if-Verzweigung 1.3.6
Drei Falle, die mitternacht.py nicht berucksichtigt
Fall 1:Durch 0 kann man nicht teilen.Dieser Fall tritt ein,wenn fur a auf der Kommandozeile 0 eingegeben wird.
Fall 2:Aus negativen Zahlen kann man keine Wurzel ziehen.Dieser Fall tritt ein, wenn b**2 - 4*a*c kleiner als 0 ist.
Fall 3:Es gibt nur eine Losung der quadratischen Gleichung.Dieser Fall tritt ein, wenn die Diskriminante 0 ist.
# python3 mitternacht.py 4 4 1
# -0.5
# -0.5
# mitternacht.py
#-------------------------------------------
import sys, math
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
diskriminante = math.sqrt(b**2 - 4 * a * c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
if-Verzweigung 1.3.6
Vermeidung des Fehlers bei”
Eingabe 0 fur a“Verzweigung des Programmflusses – if
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
a != 0 ?
print('Die Gleichung hat keine Losung!')
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b+diskriminante) / (2*a) )
print( (-b-diskriminante) / (2*a) )
ja nein
if-Verzweigung 1.3.7
Vermeidung des Fehlers bei”
Eingabe 0 fur a“Verzweigung des Programmflusses – if
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
a != 0 ?
print('Die Gleichung hat keine Losung!')
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b+diskriminante) / (2*a) )
print( (-b-diskriminante) / (2*a) )
ja nein
# mitternacht_v1.py
#-------------------------------------------
import sys, math
# Lies a, b und c (float)
# von der Kommandozeile ein.
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
# Es gibt nur dann Ergebnisse,
# wenn a ungleich 0 ist.
if a != 0:
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
else:
print('Die Gleichung hat keine Losung!')
if-Verzweigung 1.3.7
Vermeidung des Fehlers bei”
Eingabe 0 fur a“Verzweigung des Programmflusses – if
# mitternacht_v1.py
#-------------------------------------------
import sys, math
# Lies a, b und c (float)
# von der Kommandozeile ein.
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
# Es gibt nur dann Ergebnisse,
# wenn a ungleich 0 ist.
if a != 0:
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
else:
print('Die Gleichung hat keine Losung!')
Zeile-1
Zeile-2...
if Bedingung b:
Zeile-b-1
Zeile-b-2...
else:
Zeile-not-b-1
Zeile-not-b-2...
Zeile-x...
Block
Block
Block
Blockstruktur einer if-Anweisungif-Verzweigung 1.3.7
Vermeidung des Fehlers bei”
Eingabe 0 fur a“Verzweigung des Programmflusses – if
# mitternacht_v1.py
#-------------------------------------------
import sys, math
# Lies a, b und c (float)
# von der Kommandozeile ein.
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
# Es gibt nur dann Ergebnisse,
# wenn a ungleich 0 ist.
if a != 0:
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
else:
print('Die Gleichung hat keine Losung!')
Zeile-1
Zeile-2...
if Bedingung b:
Zeile-b-1
Zeile-b-2...
else:
Zeile-not-b-1
Zeile-not-b-2...
Zeile-x...
Block
Block
Block
Blockstruktur einer if-Anweisungif-Verzweigung 1.3.7
Vermeidung des Fehlers bei”
Eingabe 0 fur a“Verzweigung des Programmflusses – if
# mitternacht_v1.py
#-------------------------------------------
import sys, math
# Lies a, b und c (float)
# von der Kommandozeile ein.
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
# Es gibt nur dann Ergebnisse,
# wenn a ungleich 0 ist.
if a != 0:
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
else:
print('Die Gleichung hat keine Losung!')
Zeile-1
Zeile-2...
if Bedingung b:
Zeile-b-1
Zeile-b-2...
else:
Zeile-not-b-1
Zeile-not-b-2...
Zeile-x...
Block
Block
Block
Blockstruktur einer if-Anweisungif-Verzweigung 1.3.7
Vermeidung des Fehlers bei”
Eingabe 0 fur a“Verzweigung des Programmflusses – if
# mitternacht_v1.py
#-------------------------------------------
import sys, math
# Lies a, b und c (float)
# von der Kommandozeile ein.
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
# Es gibt nur dann Ergebnisse,
# wenn a ungleich 0 ist.
if a != 0:
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
else:
print('Die Gleichung hat keine Losung!')
Zeile-1
Zeile-2...
if Bedingung b:
Zeile-b-1
Zeile-b-2...
else:
Zeile-not-b-1
Zeile-not-b-2...
Zeile-x...
Block
Block
Block
Blockstruktur einer if-Anweisungif-Verzweigung 1.3.7
Vermeidung des Fehlers bei”
Eingabe 0 fur a“Verzweigung des Programmflusses – if
# mitternacht_v1.py
#-------------------------------------------
import sys, math
# Lies a, b und c (float)
# von der Kommandozeile ein.
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
# Es gibt nur dann Ergebnisse,
# wenn a ungleich 0 ist.
if a != 0:
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
else:
print('Die Gleichung hat keine Losung!')
Zeile-1
Zeile-2...
if Bedingung b:
Zeile-b-1
Zeile-b-2...
else:
Zeile-not-b-1
Zeile-not-b-2...
Zeile-x...
Block
Block
Block
Blockstruktur einer if-Anweisungif-Verzweigung 1.3.7
Vermeidung des Fehlers bei”b**2 - 4*a*c ist negativ“
Verzweigung des Programmflusses – if
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
a != 0 and b**2 - 4*a*c >= 0?
print('Die Gleichung hat keine Losung!')
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b+diskriminante) / (2*a) )
print( (-b-diskriminante) / (2*a) )
ja nein
if-Verzweigung 1.3.8
Vermeidung des Fehlers bei”b**2 - 4*a*c ist negativ“
Verzweigung des Programmflusses – if
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
a != 0 and b**2 - 4*a*c >= 0?
print('Die Gleichung hat keine Losung!')
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b+diskriminante) / (2*a) )
print( (-b-diskriminante) / (2*a) )
ja nein
# mitternacht_v2.py
#-------------------------------------------
import sys, math
# Lies a, b und c (float)
# von der Kommandozeile ein.
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
# Es gibt nur dann Ergebnisse,
# wenn a ungleich 0 und b**2 - 4*a*c >= 0 ist.
if a != 0 and b**2 - 4*a*c >= 0:
diskriminante = math.sqrt(b**2 - 4*a*c)
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
else:
print('Die Gleichung hat keine Losung!')
if-Verzweigung 1.3.8
Vermeidung der zweiten Ausgabe, wenn diskriminante Wert 0 hat
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
a != 0 and b**2 - 4*a*c >= 0?
print('Die Gleichung hat keine Losung!')
diskriminante = math.sqrt(b**2 - 4*a*c)
diskriminante != 0 ?
print( (-b+diskriminante) / (2*a) )
print( -b / (2*a) )
print( (-b-diskriminante) / (2*a) )
ja nein
ja nein
if-Verzweigung 1.3.9
Vermeidung der zweiten Ausgabe, wenn diskriminante Wert 0 hat
a = float(sys.argv[1])
b = float(sys.argv[2])
c = float(sys.argv[3])
a != 0 and b**2 - 4*a*c >= 0?
print('Die Gleichung hat keine Losung!')
diskriminante = math.sqrt(b**2 - 4*a*c)
diskriminante != 0 ?
print( (-b+diskriminante) / (2*a) )
print( -b / (2*a) )
print( (-b-diskriminante) / (2*a) )
ja nein
ja nein
# mitternacht_v3.py
#-------------------------------------------
import sys, math
# Lies a, b und c (float)
# von der Kommandozeile ein.
a = float( sys.argv[1] )
b = float( sys.argv[2] )
c = float( sys.argv[3] )
# Es gibt nur dann Ergebnisse,
# wenn a ungleich 0 ist.
if a != 0 and b**2 - 4*a*c >= 0:
diskriminante = math.sqrt(b**2 - 4*a*c)
# Wenn diskriminante nicht 0 ist, dann
# gibt es zwei Ergebnisse, sonst nur eines.
if diskriminante != 0:
print( (-b + diskriminante) / (2*a) )
print( (-b - diskriminante) / (2*a) )
else:
print( -b/(2*a) )
else:
print('Die Gleichung hat keine Losung!')if-Verzweigung 1.3.9
Schleifen im Programmfluss
Ublicherweise bestehen Programme aus Anweisungen,
die haufig wiederholt werden.
Die while-Schleife erlaubt die Wiederholung eines Anweisungs-Blocks,
solange eine vorgegebene Bedingung erfullt ist.
Die for-Schleife erlaubt die Wiederholung eines Anweisungs-Blocks
mit mitlaufender Veranderung eines Zahlers.
1.3.10
2 Schleifen – while
Aufgabe: Ein Schuldner hat 1000 ¿ Schulden.Der Zinssatz ist 5% pro Jahr und er zahlt eine Jahresrate von 100 ¿.Wieviele Jahre muss er zahlen, bis die Schulden abbezahlt sind?
Zinsen alte Schulden + Zinsen - Rate = Schuldenstand
Anfang 2001 1000.00Ende 2001 50.00 950.00Ende 2002 47.50 897.50Ende 2003 44.87 842.37Ende 2004 42.12 784.49Ende 2005 39.22 723.71Ende 2006 36.19 659.90Ende 2007 32.99 592.89Ende 2008 29.65 522.54Ende 2009 26.13 448.67Ende 2010 22.43 371.10Ende 2011 18.56 289.66Ende 2012 14.48 204.14Ende 2013 10.21 114.35Ende 2014 5.71 20.06Ende 2015 1.00 -78.92
while-Schleife 1.3.11
Schleifen – while
Wieviele Jahre dauert die Ruckzahlung der Schulden beider Jahresrate und dem Zinssatz?
Um diese Jahreszahl zu berechnen,berechnet man Jahr fur Jahr den Schuldenstand,bis der Schuldenstand ď 0 ist.Dabei zahlt man mit, wieviele Jahre das ging.Der Endstand dieses Zahlers
ist die gesuchte Jahreszahl.
Lies die Eingabe.
Sind die Schulden ą 0 ?
Berechne den Schuldenstand nach Ablauf eines Jahres.
Zahle mit, dass ein weiteres Jahr vergangen ist.
Gib aus, wieviele Jahre vergangen sind.
ja
nein
while-Schleife 1.3.12
Schleifen – while
Wieviele Jahre dauert die Ruckzahlung der Schulden beider Jahresrate und dem Zinssatz?
Um diese Jahreszahl zu berechnen,berechnet man Jahr fur Jahr den Schuldenstand,bis der Schuldenstand ď 0 ist.Dabei zahlt man mit, wieviele Jahre das ging.Der Endstand dieses Zahlers
ist die gesuchte Jahreszahl.
schulden = int(sys.argv[1])
zinssatz = float(sys.argv[2])
jahresrate = int(sys.argv[3])
jahreZaehler = 0
schulden > 0 ?
zinsen = schulden * zinssatz / 100
schulden = schulden + zinsen - jahresrate
jahreZaehler = jahreZaehler+1
print('Die Ruckzahlung dauert ' + str(jahreZaehler) + ' Jahre.')
ja
nein
while-Schleife 1.3.13
Schleifen – while
Wieviele Jahre dauert die Ruckzahlung der Schulden beider Jahresrate und dem Zinssatz?
Schleifenbedingung
schulden = int(sys.argv[1])
zinssatz = float(sys.argv[2])
jahresrate = int(sys.argv[3])
jahreZaehler = 0
schulden > 0 ?
zinsen = schulden * zinssatz / 100
schulden = schulden + zinsen - jahresrate
jahreZaehler = jahreZaehler+1
print('Die Ruckzahlung dauert ' + str(jahreZaehler) + ' Jahre.')
ja
nein
while-Schleife 1.3.13
Schleifen – while
Wieviele Jahre dauert die Ruckzahlung der Schulden beider Jahresrate und dem Zinssatz?
Schleifenbedingung
Schleifenrumpf (Block)
schulden = int(sys.argv[1])
zinssatz = float(sys.argv[2])
jahresrate = int(sys.argv[3])
jahreZaehler = 0
schulden > 0 ?
zinsen = schulden * zinssatz / 100
schulden = schulden + zinsen - jahresrate
jahreZaehler = jahreZaehler+1
print('Die Ruckzahlung dauert ' + str(jahreZaehler) + ' Jahre.')
ja
nein
while-Schleife 1.3.13
Schleifen – while
Wieviele Jahre dauert die Ruckzahlung der Schulden beider Jahresrate und dem Zinssatz?
import sys
schulden = int(sys.argv[1])
zinssatz = float(sys.argv[2])
jahresrate = int(sys.argv[3])
jahreZaehler = 0 # Zahler fur die Jahre mit Ratenzahlungen
while schulden > 0 :
# Berechnung des Schuldenstandes nach einem weiteren Jahr.
zinsen = schulden * zinssatz / 100
schulden = schulden + zinsen - jahresrate
jahreZaehler += 1
print('Die Ruckzahlung dauert ' + str(jahreZaehler) + ' Jahre.')
schulden = int(sys.argv[1])
zinssatz = float(sys.argv[2])
jahresrate = int(sys.argv[3])
jahreZaehler = 0
schulden > 0 ?
zinsen = schulden * zinssatz / 100
schulden = schulden + zinsen - jahresrate
jahreZaehler = jahreZaehler+1
print('Die Ruckzahlung dauert ' + str(jahreZaehler) + ' Jahre.')
ja
nein
while-Schleife 1.3.13
Blockstruktur von while-Schleifen#-----------------------------------------------------------------------
# rueckzahlungsdauer.py
#-----------------------------------------------------------------------
# Das Programm liest von der Kommandozeile die Werte
# schulden (int), zinssatz (float) und jahresrate (int).
# Es wird berechnet, wieviele Jahre die jahresrate bezahlt werden muss,
# bis die schulden beim angegebenen zinssatz beglichen sind.
#-----------------------------------------------------------------------
import sys
schulden = int(sys.argv[1])
zinssatz = float(sys.argv[2])
jahresrate = int(sys.argv[3])
jahreZaehler = 0 # Zahler fur die Jahre mit Ratenzahlungen
while schulden > 0 :
# Berechnung des Schuldenstandes nach einem weiteren Jahr.
zinsen = schulden * zinssatz / 100
schulden = schulden + zinsen - jahresrate
jahreZaehler += 1
print('Die Ruckzahlung dauert ' + str(jahreZaehler) + ' Jahre.')
#------------------------------------------------------------------------
# python rueckzahlungsdauer.py 200000 3.5 12000
# Die Ruckzahlung dauert 26 Jahre.
Zeile-1
Zeile-2...
while Bedingung b:
Zeile-b-1
Zeile-b-2...
Zeile-x...
Block
Block
while-Schleife 1.3.14
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
Bestimmung aller Teiler einer Zahl
Bestimmung aller Teiler von 18:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18X X X ˆ ˆ X ˆ ˆ X ˆ ˆ ˆ ˆ ˆ ˆ ˆ ˆ X
Idee fur den Algorithmus:
zur Bestimmung aller Teiler einer ganzen Zahl n:
gehe alle Zahlen z von 1 bis n durch
falls z ein Teiler von n ist (d.h. n%z == 0), dann gib z aus
while-Schleife 1.3.15
# alleteiler1.py
#------------------------------------------------------------------------------------
# Das Programm liest int-Wert n von der Kommandozeile ein
# und gibt alle Teiler von n aus.
#------------------------------------------------------------------------------------
import sys
# Lies n von der Kommandozeile.
n = int( sys.argv[1] )
print('Die Teiler von ' + str(n) + ' sind:')
# zaehler soll alle Werte im Bereich 1...n durchlaufen.
zaehler = 1
while zaehler <= n:
# Falls zaehler ein Teiler von n ist, dann wird zaehler ausgegeben.
if n%zaehler == 0:
print(zaehler)
# Nimm den nachsten Wert fur zaehler.
zaehler = zaehler + 1
#------------------------------------------------------------------------------------
# python alleteiler1.py 8
# Die Teiler von 8 sind:
# 1
# 2
# 4
# 8while-Schleife 1.3.16
3 Schleifen – for
Haufig wird in einer Schleife u.a. eine Variable hochgezahlt
und die Schleifen-Wiederholung endet, wenn ein bestimmter Wert erreicht wurde.
Die for-Schleife erleichtert das Aufschreiben solcher Schleifen.
for-Schleife 1.3.17
# alleteiler2.py
#------------------------------------------------------------------------------------
# Das Programm liest int-Wert n von der Kommandozeile ein
# und gibt alle Teiler von n aus.
#------------------------------------------------------------------------------------
import sys
# Lies n (int) von der Kommandozeile.
n = int( sys.argv[1] )
# zaehler soll alle Werte im Bereich 1..n durchlaufen.
for zaehler in range(1, n+1):
# Falls zaehler ein Teiler von n ist, dann wird zaehler ausgegeben.
if n%zaehler == 0:
print(zaehler)
#------------------------------------------------------------------------------------
# python alleteiler2.py 8
# Die Teiler von 8 sind:
# 1
# 2
# 4
# 8
zaehler in range(1,9) durchlauft fur zaehler die Werte 1, 2, 3, 4, 5, 6, 7, 8.
zaehler in range(a,b) durchlauft fur zaehler die Werte a, a` 1, a` 2, . . . , b ´ 1.for-Schleife 1.3.18
Simulation von Zufallsexperimenten
Zwei Wurfel werden geworfen. Wie wahrscheinlich ist es, dass die Augensumme 7 ist?
Statt die Wahrscheinlichkeit exakt auszurechnen,simulieren wir ein Experiment mit einem Programm.
Das Experiment besteht aus dem Wurf von zwei Wurfeln.Das Experiment ist erfolgreich, wenn die Wurfelsumme 7 ist.Anderenfalls ist das Experiment nicht erfolgreich.
Dieses Experiment wiederholen wir z.B. 100000-malund zahlen, wie oft das Experiment erfolgreich ist.
Die experimentell bestimmte Wahrscheinlichkeit, die Wurfelsumme 7 zu wurfeln,ist dann der Quotient
Anzahl der erfolgreichen Experimente
Anzahl aller Experimente.
Je ofter das Experiment wiederholt wird,desto wahrscheinlicher ist es, die
”richtige“ Wahrscheinlichkeit herauszubekommen.
Bestimmung einer Wahrscheinlichkeit durch Simulation 1.3.19
Wie wurfelt Python?
Schreibweise fur Intervalle: ra, bq fur int-Werte istdas Intervall mit den Zahlen a, a` 1, a` 2, . . . , b ´ 1 (entspricht range(a,b)).
Z.B. ist r1, 7q das Intervall 1, 2, 3, 4, 5, 6.
ra, bq fur float-Werte istdas Intervall mit den Zahlen r mit a ď r ă b.
Z.B. ist r0, 1q das Intervall mit allen reellen Zahlen x mit 0 ď x ă 1,das sind alle Dezimalbruche 0, xyz . . . mit 0 vor dem Komma.
Standardfunktionen aus Pythons Modul random:
randrange(a,b) ein zufallig gewahlter int-Wert aus [a,b) fur int-Werte a und b
random() ein zufallig gewahlter float-Wert aus dem Intervall r0, 1q
Die Funktionswerte sind gleichverteilt.
Ein Wurf mit einem Wurfel entspricht einem Aufruf von random.randrange(1,7) in Python.
Bestimmung einer Wahrscheinlichkeit durch Simulation 1.3.20
Aufgabe:
bestimme die Wahrscheinlichkeit,
dass beim Wurf mit zwei Wurfeln Augensumme 7 geworfen wird,
mittels Simulation.
Idee fur den Algorithmus:
wiederhole n-mal:
Experiment: wurfele mit zwei Wurfeln
Auswertung: das Experiment war erfolgreich, falls Augensumme 7 gewurfelt wurde
gib”Anzahl erfolgreicher Experimente / n“ aus
Bestimmung einer Wahrscheinlichkeit durch Simulation 1.3.21
#----------------------------------------------------------------------------------------------------------
# siebenwuerfeln.py
#----------------------------------------------------------------------------------------------------------
import sys, random
# Die Experimentreihe wird vorbereitet. n ist die Anzahl der Wiederholungen des Experiments.
n = int( sys.argv[1] )
erfolgsZaehler = 0 # zahlt die erfolgreichen Experimente
# Die Experimentreihe wird durchgefuhrt.
for i in range(0,n): # es werden n Experimente durchgefuhrt
# Das Experiment: zwei Wurfel werden geworfen.
wuerfel1 = random.randrange(1,7)
wuerfel2 = random.randrange(1,7)
# Die Auswertung des Experiments: das Experiment ist erfolgreich, wenn die Wurfelsumme 7 ist.
if wuerfel1 + wuerfel2 == 7: erfolgsZaehler += 1
# Das Ergebnis der Experimentreihe wird ausgegeben.
erfolgsWkeit = erfolgsZaehler/n
print('Die Wahrscheinlichkeit fur ein erfolgreiches Experiment ist ' + str(float(erfolgsWkeit)) + '.' )
print('D.h. etwa einer von ' + str(round(1/erfolgsWkeit)) + ' Wurfen ist erfolgreich.' )
#-----------------------------------------------------------------------------------------------------------
# python siebenwuerfeln.py 100
# Die Wahrscheinlichkeit fur ein erfolgreiches Experiment ist 0.2.
# D.h. etwa einer von 5 Wurfen ist erfolgreich.
#
# python siebenwuerfeln.py 100
# Die Wahrscheinlichkeit fur ein erfolgreiches Experiment ist 0.15.
# D.h. etwa einer von 7 Wurfen ist erfolgreich. Bestimmung einer Wahrscheinlichkeit durch Simulation 1.3.22
#----------------------------------------------------------------------------------------------------------
# siebenwuerfeln.py
#----------------------------------------------------------------------------------------------------------
import sys, random
# Die Experimentreihe wird vorbereitet. n ist die Anzahl der Wiederholungen des Experiments.
n = int( sys.argv[1] )
erfolgsZaehler = 0 # zahlt die erfolgreichen Experimente
# Die Experimentreihe wird durchgefuhrt.
for i in range(0,n): # es werden n Experimente durchgefuhrt
# Das Experiment: zwei Wurfel werden geworfen.
wuerfel1 = random.randrange(1,7)
wuerfel2 = random.randrange(1,7)
# Die Auswertung des Experiments: das Experiment ist erfolgreich, wenn die Wurfelsumme 7 ist.
if wuerfel1 + wuerfel2 == 7: erfolgsZaehler += 1
# Das Ergebnis der Experimentreihe wird ausgegeben.
erfolgsWkeit = erfolgsZaehler/n
print('Die Wahrscheinlichkeit fur ein erfolgreiches Experiment ist ' + str(float(erfolgsWkeit)) + '.' )
print('D.h. etwa einer von ' + str(round(1/erfolgsWkeit)) + ' Wurfen ist erfolgreich.' )
#-----------------------------------------------------------------------------------------------------------
# python siebenwuerfeln.py 1000000
# Die Wahrscheinlichkeit fur ein erfolgreiches Experiment ist 0.166619.
# D.h. etwa einer von 6 Wurfen ist erfolgreich.
#
# python siebenwuerfeln.py 1000000
# Die Wahrscheinlichkeit fur ein erfolgreiches Experiment ist 0.166767.
# D.h. etwa einer von 6 Wurfen ist erfolgreich. Bestimmung einer Wahrscheinlichkeit durch Simulation 1.3.22
4 Zum Abschluss: Jetzt konnen wir schon mehr als Euler . . .
Euler hat 1769 vermutet,
dass es z.B. keine ganzen Zahlen a, b, c , d , e ě 1 gibt, so dass
a5 ` b5 ` c5 ` d5 “ e5 .
Die Vermutung wurde 1966 von L.J.Lander und T.R.Parkin widerlegt:
fur a “ 133, b “ 110, c “ 84, d “ 27 und e “ 144 gilt
a5 ` b5 ` c5 ` d5 “ e5 (1335 ` 1105 ` 845 ` 275 “ 1445).
Beantwortung einer Frage von Euler 1.3.23
4 Zum Abschluss: Jetzt konnen wir schon mehr als Euler . . .
Euler hat 1769 vermutet,
dass es z.B. keine ganzen Zahlen a, b, c , d , e ě 1 gibt, so dass
a5 ` b5 ` c5 ` d5 “ e5 .
Die Vermutung wurde 1966 von L.J.Lander und T.R.Parkin widerlegt:
fur a “ 133, b “ 110, c “ 84, d “ 27 und e “ 144 gilt
a5 ` b5 ` c5 ` d5 “ e5 (1335 ` 1105 ` 845 ` 275 “ 1445).
Die Zahlen wurden mit einem Programm gefunden, das auf einer CDC 6600 lief.Sie war 1964–1969 der schnellste Rechner der Welt.
CDC 6600: 3 megaFLOPS, d.h. 3 ¨ 106 floating point operations per secondheutiger PC: 100 gigaFLOPS, d.h. 100 ¨ 109
Summit (IBM): 122 petaFLOPS, d.h. 122 ¨ 1015
Beantwortung einer Frage von Euler 1.3.23
4 Zum Abschluss: Jetzt konnen wir schon mehr als Euler . . .
Euler hat 1769 vermutet,
dass es z.B. keine ganzen Zahlen a, b, c , d , e ě 1 gibt, so dass
a5 ` b5 ` c5 ` d5 “ e5 .
Die Vermutung wurde 1966 von L.J.Lander und T.R.Parkin widerlegt:
fur a “ 133, b “ 110, c “ 84, d “ 27 und e “ 144 gilt
a5 ` b5 ` c5 ` d5 “ e5 (1335 ` 1105 ` 845 ` 275 “ 1445).
Wir konnen ein Programm schreiben,
das systematisch durch die moglichen Werte von a, b, c , d , e geht
und uberpruft, ob sie die gewunschte Eigenschaft haben.
Da wir bereits wissen, dass es Werte a, b, c , d , e mit a5 ` b5 ` c5 ` d5 “ e5 gibt,
mussen wir nur warten, bis das Programm sie gefunden hat.
Wenn wir das nicht wussten, konnte das Programm endlos laufen . . .
Beantwortung einer Frage von Euler 1.3.23
Gibt es ganze Zahlen a, b, c , d , e ě 1 mit a5 ` b5 ` c5 ` d5 “ e5 ?
Nur”brutal“ alle moglichen Werte von a, b, c , d , e durchzugehen,
dauert selbst auf einem schnellen Rechner sehr lange.
Mein”brutales“ Programm durchlauft etwa 65 Milliarden Kombinationen a, b, c , d , e,
bis es die Losung gefunden hat.
Das dauert langer als 28 Stunden (auf meinem Rechner im Buro).
Ein Problem dabei ist es, dass viele Kombinationen vielfach durchlaufen werden.
Um das zu vermeiden, hatte ich (mit unseren bisherigen Programmierkenntnissen)
ein Programm von etwa 300 Programmzeilen schreiben mussen.
Das hatte die Rechendauer halbiert . . .
Beantwortung einer Frage von Euler 1.3.24
Gibt es ganze Zahlen a, b, c , d , e ě 1 mit a5 ` b5 ` c5 ` d5 “ e5 ?
Nur”brutal“ alle moglichen Werte von a, b, c , d , e durchzugehen,
dauert selbst auf einem schnellen Rechner sehr lange.
Mein”brutales“ Programm durchlauft etwa 65 Milliarden Kombinationen a, b, c , d , e,
bis es die Losung gefunden hat.
Das dauert langer als 28 Stunden (auf meinem Rechner im Buro).
Ein Problem dabei ist es, dass viele Kombinationen vielfach durchlaufen werden.
Um das zu vermeiden, hatte ich (mit unseren bisherigen Programmierkenntnissen)
ein Programm von etwa 300 Programmzeilen schreiben mussen.
Das hatte die Rechendauer halbiert . . .
Beantwortung einer Frage von Euler 1.3.24
Gibt es ganze Zahlen a, b, c , d , e ě 1 mit a5 ` b5 ` c5 ` d5 “ e5 ?
Also mussen wir die Frage analysieren und versuchen, sie so umzuformulieren,
dass man sie”schneller“ losen kann.
Euler fragt ja, ob es ganze Zahlen a, b, c , d ě 1 gibt,
so dass die Summe a5 ` b5 ` c5 ` d5 die 5te Potenz einer ganzen Zahl ist.
Um das festzustellen, reicht es, alle moglichen Kombinationen von a, b, c , d zu durchsuchen
und jeweils zu uberprufen, a5 ` b5 ` c5 ` d5 die 5te Potenz einer ganzen Zahl ist.
Bei meinem Brutalo-Programm sind das nur noch 26 Milliarden Kombinationen.
Kann man diese Zahl noch verringern?
Insgesamt mussen wir zwei Teilaufgaben losen.
(F1) Wenn wir eine ganze Zahl x haben,
wie konnen wir feststellen, ob x die 5te Potenz einer ganzen Zahl ist?
(F2) Wie konnen wir systematisch alle notigen Werte fur a, b, c , d durchsuchen?Beantwortung einer Frage von Euler 1.3.25
Gibt es ganze Zahlen a, b, c , d , e ě 1 mit a5 ` b5 ` c5 ` d5 “ e5 ?
Also mussen wir die Frage analysieren und versuchen, sie so umzuformulieren,
dass man sie”schneller“ losen kann.
Euler fragt ja, ob es ganze Zahlen a, b, c , d ě 1 gibt,
so dass die Summe a5 ` b5 ` c5 ` d5 die 5te Potenz einer ganzen Zahl ist.
Um das festzustellen, reicht es, alle moglichen Kombinationen von a, b, c , d zu durchsuchen
und jeweils zu uberprufen, a5 ` b5 ` c5 ` d5 die 5te Potenz einer ganzen Zahl ist.
Bei meinem Brutalo-Programm sind das nur noch 26 Milliarden Kombinationen.
Kann man diese Zahl noch verringern?
Insgesamt mussen wir zwei Teilaufgaben losen.
(F1) Wenn wir eine ganze Zahl x haben,
wie konnen wir feststellen, ob x die 5te Potenz einer ganzen Zahl ist?
(F2) Wie konnen wir systematisch alle notigen Werte fur a, b, c , d durchsuchen?Beantwortung einer Frage von Euler 1.3.25
Gibt es ganze Zahlen a, b, c , d , e ě 1 mit a5 ` b5 ` c5 ` d5 “ e5 ?
Also mussen wir die Frage analysieren und versuchen, sie so umzuformulieren,
dass man sie”schneller“ losen kann.
Euler fragt ja, ob es ganze Zahlen a, b, c , d ě 1 gibt,
so dass die Summe a5 ` b5 ` c5 ` d5 die 5te Potenz einer ganzen Zahl ist.
Um das festzustellen, reicht es, alle moglichen Kombinationen von a, b, c , d zu durchsuchen
und jeweils zu uberprufen, a5 ` b5 ` c5 ` d5 die 5te Potenz einer ganzen Zahl ist.
Bei meinem Brutalo-Programm sind das nur noch 26 Milliarden Kombinationen.
Kann man diese Zahl noch verringern?
Insgesamt mussen wir zwei Teilaufgaben losen.
(F1) Wenn wir eine ganze Zahl x haben,
wie konnen wir feststellen, ob x die 5te Potenz einer ganzen Zahl ist?
(F2) Wie konnen wir systematisch alle notigen Werte fur a, b, c , d durchsuchen?Beantwortung einer Frage von Euler 1.3.25
Gibt es ganze Zahlen a, b, c , d , e ě 1 mit a5 ` b5 ` c5 ` d5 “ e5 ?
Also mussen wir die Frage analysieren und versuchen, sie so umzuformulieren,
dass man sie”schneller“ losen kann.
Euler fragt ja, ob es ganze Zahlen a, b, c , d ě 1 gibt,
so dass die Summe a5 ` b5 ` c5 ` d5 die 5te Potenz einer ganzen Zahl ist.
Um das festzustellen, reicht es, alle moglichen Kombinationen von a, b, c , d zu durchsuchen
und jeweils zu uberprufen, a5 ` b5 ` c5 ` d5 die 5te Potenz einer ganzen Zahl ist.
Bei meinem Brutalo-Programm sind das nur noch 26 Milliarden Kombinationen.
Kann man diese Zahl noch verringern?
Insgesamt mussen wir zwei Teilaufgaben losen.
(F1) Wenn wir eine ganze Zahl x haben,
wie konnen wir feststellen, ob x die 5te Potenz einer ganzen Zahl ist?
(F2) Wie konnen wir systematisch alle notigen Werte fur a, b, c , d durchsuchen?Beantwortung einer Frage von Euler 1.3.25
(F1) Ist x die 5te Potenz einer ganzen Zahl?
Um das festzustellen, berechnen wir die 5te Wurzel von x :wurzel = x**0.2
Da im Ausdruck x**0.2 ein float-Wert vorkommt,ist das Ergebnis ebenfalls vom Typ float.
float-Werte enthalten oft Rundungsfehler (Berechnungsungenauigkeiten).
Obwohl p 5?
2q5 mathematisch das Ergebnis 2 hat,macht print((2**0.2)**5) Ausgabe 2.000000000000001 !
Deshalb liefert der Ausdruck (2**0.2)**5 == 2 (also 5?
25“ 2?)
den Wert False.
Wie umgehen wir diesen Fehler?
Beantwortung einer Frage von Euler 1.3.26
(F1) Ist x die 5te Potenz einer ganzen Zahl?
Zuerst berechnen wir die funfte Wurzel von x (mit moglichem Rundungsfehler):fWurzel = x**0.2
fWurzel hat den Typ float.Da wir nur an ganzzahligen funften Wurzeln interessiert sind,runden wir fWurzel zur nachsten ganzen Zahl.
fuenfteWurzel = round(fWurzel)
fuenfteWurzel hat den Typ int (das ist nur in Python3 so),und fuenfteWurzel**5 ist die korrekte 5te Potenz von fuenfteWurzel.
Wenn nun x == fuenfteWurzel**5 den Wert True hat,dann haben wir festgestellt, dass x die 5te Potenz einer ganzen Zahl ist.
Wenn aber x == fuenfteWurzel**5 den Wert False hat,dann ist x nicht die 5te Potenz einer ganzen Zahl
oder beim Wurzelziehen ist ein Rundungsfehler aufgetreten, der das Ergebnis verfalscht.(Hier gehen wir davon aus, dass der Rundungsfehler nicht zu groß ist . . . In diesem Beispiel geht das gut . . . )
Beantwortung einer Frage von Euler 1.3.27
(F1) Ist x die 5te Potenz einer ganzen Zahl?
Zuerst berechnen wir die funfte Wurzel von x (mit moglichem Rundungsfehler):fWurzel = x**0.2
fWurzel hat den Typ float.Da wir nur an ganzzahligen funften Wurzeln interessiert sind,runden wir fWurzel zur nachsten ganzen Zahl.
fuenfteWurzel = round(fWurzel)
fuenfteWurzel hat den Typ int (das ist nur in Python3 so),und fuenfteWurzel**5 ist die korrekte 5te Potenz von fuenfteWurzel.
Wenn nun x == fuenfteWurzel**5 den Wert True hat,dann haben wir festgestellt, dass x die 5te Potenz einer ganzen Zahl ist.
Wenn aber x == fuenfteWurzel**5 den Wert False hat,dann ist x nicht die 5te Potenz einer ganzen Zahl
oder beim Wurzelziehen ist ein Rundungsfehler aufgetreten, der das Ergebnis verfalscht.(Hier gehen wir davon aus, dass der Rundungsfehler nicht zu groß ist . . . In diesem Beispiel geht das gut . . . )
Beantwortung einer Frage von Euler 1.3.27
(F1) Ist x die 5te Potenz einer ganzen Zahl?
Zuerst berechnen wir die funfte Wurzel von x (mit moglichem Rundungsfehler):fWurzel = x**0.2
fWurzel hat den Typ float.Da wir nur an ganzzahligen funften Wurzeln interessiert sind,runden wir fWurzel zur nachsten ganzen Zahl.
fuenfteWurzel = round(fWurzel)
fuenfteWurzel hat den Typ int (das ist nur in Python3 so),und fuenfteWurzel**5 ist die korrekte 5te Potenz von fuenfteWurzel.
Wenn nun x == fuenfteWurzel**5 den Wert True hat,dann haben wir festgestellt, dass x die 5te Potenz einer ganzen Zahl ist.
Wenn aber x == fuenfteWurzel**5 den Wert False hat,dann ist x nicht die 5te Potenz einer ganzen Zahl
oder beim Wurzelziehen ist ein Rundungsfehler aufgetreten, der das Ergebnis verfalscht.(Hier gehen wir davon aus, dass der Rundungsfehler nicht zu groß ist . . . In diesem Beispiel geht das gut . . . )
Beantwortung einer Frage von Euler 1.3.27
(F1) Ist x die 5te Potenz einer ganzen Zahl?
Zuerst berechnen wir die funfte Wurzel von x (mit moglichem Rundungsfehler):fWurzel = x**0.2
fWurzel hat den Typ float.Da wir nur an ganzzahligen funften Wurzeln interessiert sind,runden wir fWurzel zur nachsten ganzen Zahl.
fuenfteWurzel = round(fWurzel)
fuenfteWurzel hat den Typ int (das ist nur in Python3 so),und fuenfteWurzel**5 ist die korrekte 5te Potenz von fuenfteWurzel.
Wenn nun x == fuenfteWurzel**5 den Wert True hat,dann haben wir festgestellt, dass x die 5te Potenz einer ganzen Zahl ist.
Wenn aber x == fuenfteWurzel**5 den Wert False hat,dann ist x nicht die 5te Potenz einer ganzen Zahl
oder beim Wurzelziehen ist ein Rundungsfehler aufgetreten, der das Ergebnis verfalscht.(Hier gehen wir davon aus, dass der Rundungsfehler nicht zu groß ist . . . In diesem Beispiel geht das gut . . . )
Beantwortung einer Frage von Euler 1.3.27
(F1) Ist x die 5te Potenz einer ganzen Zahl?
Zuerst berechnen wir die funfte Wurzel von x (mit moglichem Rundungsfehler):fWurzel = x**0.2
fWurzel hat den Typ float.Da wir nur an ganzzahligen funften Wurzeln interessiert sind,runden wir fWurzel zur nachsten ganzen Zahl.
fuenfteWurzel = round(fWurzel)
fuenfteWurzel hat den Typ int (das ist nur in Python3 so),und fuenfteWurzel**5 ist die korrekte 5te Potenz von fuenfteWurzel.
Wenn nun x == fuenfteWurzel**5 den Wert True hat,dann haben wir festgestellt, dass x die 5te Potenz einer ganzen Zahl ist.
Wenn aber x == fuenfteWurzel**5 den Wert False hat,dann ist x nicht die 5te Potenz einer ganzen Zahl
oder beim Wurzelziehen ist ein Rundungsfehler aufgetreten, der das Ergebnis verfalscht.(Hier gehen wir davon aus, dass der Rundungsfehler nicht zu groß ist . . . In diesem Beispiel geht das gut . . . )
Beantwortung einer Frage von Euler 1.3.27
(F2) Wie konnen wir alle notigen Werte fur a, b, c , d (schnell?) durchsuchen?
Die brutale Idee ist es, alle moglichen Werte fur a, b, c, d zu durchsuchen.
Das ist hier aber nicht notig.
Z.B. ist 25 ` 85 ` 65 ` 45 “ 85 ` 65 ` 45 ` 25.
Es reicht also, die Werte fur a, b, c , d zu durchsuchen,
bei denen a ě b ě c ě d ist.
Dazu zahlen wir a “ 1, 2, 3, . . . hoch
und gehen systematisch alle passenden Moglichkeiten fur b, c , d durch,
also b, c , d “ 1, 2, . . . , a und b ě c ě d .
a = 0
while True:
a = a+1
for b in range(1,a+1):
for c in range(1,b+1):
for d in range(1,c+1):
# teste die Euler-Bedingung fur a,b,c,d
Beantwortung einer Frage von Euler 1.3.28
(F2) Wie konnen wir alle notigen Werte fur a, b, c , d (schnell?) durchsuchen?
Die brutale Idee ist es, alle moglichen Werte fur a, b, c, d zu durchsuchen.
Das ist hier aber nicht notig.
Z.B. ist 25 ` 85 ` 65 ` 45 “ 85 ` 65 ` 45 ` 25.
Es reicht also, die Werte fur a, b, c , d zu durchsuchen,
bei denen a ě b ě c ě d ist.
Dazu zahlen wir a “ 1, 2, 3, . . . hoch
und gehen systematisch alle passenden Moglichkeiten fur b, c , d durch,
also b, c , d “ 1, 2, . . . , a und b ě c ě d .
a = 0
while True:
a = a+1
for b in range(1,a+1):
for c in range(1,b+1):
for d in range(1,c+1):
# teste die Euler-Bedingung fur a,b,c,d
Beantwortung einer Frage von Euler 1.3.28
Gib alle 2-Tupel pa, bq aus mit a ě b ě 1
#--------------------------------------------------------
# alle2Tupel.py
#--------------------------------------------------------
# Gib alle 2-Tupel (a,b) aus mit a>=b>=1.
#--------------------------------------------------------
a = 0
while True:
a = a+1
for b in range(1,a+1):
print(a,b)
#--------------------------------------------------------
# python3 alle2Tupel.py
# 1 1
# 2 1
# 2 2
# 3 1
# 3 2
# 3 3
# 4 1
# 4 2
# 4 3
# 4 4
# 5 1
# 5 2
# 5 3
# 5 4
# 5 5
# 6 1
# 6 2
# ...
Beantwortung einer Frage von Euler 1.3.29
Gib alle 3-Tupel pa, b, cq aus mit a ě b ě c ě 1
#------------------------------------------------------
# alle3Tupel.py
#------------------------------------------------------
# Gib alle 3-Tupel (a,b,c) aus mit a>=b>=c>=1.
#------------------------------------------------------
a = 0
while True:
a = a+1
for b in range(1,a+1):
for c in range(1,b+1):
print(a,b,c)
#------------------------------------------------------
# python3 alle3Tupel.py
# 1 1 1
# 2 1 1
# 2 2 1
# 2 2 2
# 3 1 1
# 3 2 1
# 3 2 2
# 3 3 1
# 3 3 2
# 3 3 3
# 4 1 1
# 4 2 1
# 4 2 2
# 4 3 1
# 4 3 2
# 4 3 3
# 4 4 1
# ...
Beantwortung einer Frage von Euler 1.3.30
Gib alle 4-Tupel pa, b, c , dq aus mit a ě b ě c ě d ě 1
#----------------------------------------------------------
# alle4Tupel.py
#----------------------------------------------------------
# Gib alle 4-Tupel (a,b,c,d) aus mit a>=b>=c>=d>=1.
#----------------------------------------------------------
a = 0
while True:
a = a+1
for b in range(1,a+1):
for c in range(1,b+1):
for d in range(1,c+1):
print(a,b,c,d)
#---------------------------------------------------------
# python3 alle4Tupel.py
# 1 1 1 1
# 2 1 1 1
# 2 2 1 1
# 2 2 2 1
# 2 2 2 2
# 3 1 1 1
# 3 2 1 1
# 3 2 2 1
# 3 2 2 2
# 3 3 1 1
# 3 3 2 1
# 3 3 2 2
# 3 3 3 1
# 3 3 3 2
# 3 3 3 3
# 4 1 1 1
# 4 2 1 1
# ...
Nun konnen wir beide Teile zu einem Programm zusammenbauen,
das die Vermutung von Euler widerlegt. Beantwortung einer Frage von Euler 1.3.31
#------------------------------------------------------------------------------------------------
# euler-vermutung.py
#------------------------------------------------------------------------------------------------
zaehler = 0 # wir zahlen, wieviele Zahlenkombinationen durchprobiert werden
erfolg = False # wird auf True gesetzt, wenn die gesuchte Kombination gefunden wurde
a = 0
while not erfolg: # teste alle Tupel a,b,c,d mit a>=b>=c>=d>=1, bis ein Test erfolgreich war
a += 1
print(a) # damit wir sehen, wie weit das Programm gekommen ist
for b in range(1,a+1):
for c in range(1,b+1):
for d in range(1,c+1):
zaehler += 1
summe = a**5 + b**5 + c**5 + d**5
fuenfteWurzel = round(summe**0.2)
if summe == fuenfteWurzel**5:
print('Versuch ' + str(zaehler) + ' war erfolgreich: ')
print(str(a) + '**5 + ' + str(b) + '**5 + ' + str(c) + '**5 + '
+ str(d) + '**5 == ' + str(fuenfteWurzel) + '**5')
print('Die Summe ist ' + str(summe) + '.')
erfolg = True
#------------------------------------------------------------------------------------------------
Beantwortung einer Frage von Euler 1.3.32
# python3 euler-vermutung.py
# 1
# 2
# 3
# 4
# ...
# 130
# 131
# 132
# 133
# Versuch 13458163 war erfolgreich:
# 133**5 + 110**5 + 84**5 + 27**5 == 144**5
# Die Summe ist 61917364224.
Beantwortung einer Frage von Euler 1.3.33
Zusammenfassung
§ Wir haben if-Anweisungen, while-Schleifen und for-Schleifen kennengelernt.
§ Wir kennen die Strukturierung von Programmen in Blocke.
§ Wir konnen einfache Programme mit
Eingabe von Argumenten (von der Konsole)
Abarbeitung von Anweisungs-Blocken,
die in Schleifen wiederholt oder
durch if-Anweisungen ausgefuhrt oder ubersprungen werden
Ausgabe von Ergebnissen (auf der Konsole)
schreiben und deren Ausfuhrung nachvollziehen.
1.3.34
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus
Um den ganzzahligen Logarithmus einer Zahl zur Basis 2 zu berechnen,
teilt man die Zahl immer wieder ganzzahlig durch 2,
bis die Zahl 1 erreicht wird.
Der ganzzahlige Logarithmus der Zahl zur Basis 2 ist dann die Anzahl,
wie oft man durch 2 teilen konnte.
Beispiele:
Berechnung des ganzzahligen Logarithmus von 18 zur Basis 2:
18 9 4 2 1 : das Ergebnis ist 4 (24 ď 18 ă 25)
35 17 8 4 2 1 : das Ergebnis ist 5 (25 ď 35 ă 26)
Idee fur den Algorithmus:
teile die Zahl solange durch 2, wie sie ą 1 ist
und erhohe bei jedem Teilen einen Zahler um 1.
1.3.35
Berechnung des ganzzahligen Logarithmus zur Basis 2
zahl = int( sys.argv[1] )
zaehler = 0
zahl > 1 ?
zaehler = zaehler + 1
zahl = zahl // 2
print('Der Logarithmus von ' + str(zahl) + ' zur Basis 2 ist ' + str(zaehler) + '.')
ja
nein
1.3.36
Berechnung des ganzzahligen Logarithmus zur Basis 2
zahl = int( sys.argv[1] )
zaehler = 0
zahl > 1 ?
zaehler = zaehler + 1
zahl = zahl // 2
print('Der Logarithmus von ' + str(zahl) + ' zur Basis 2 ist ' + str(zaehler) + '.')
ja
neinSchleifenbedingung
1.3.36
Berechnung des ganzzahligen Logarithmus zur Basis 2
zahl = int( sys.argv[1] )
zaehler = 0
zahl > 1 ?
zaehler = zaehler + 1
zahl = zahl // 2
print('Der Logarithmus von ' + str(zahl) + ' zur Basis 2 ist ' + str(zaehler) + '.')
ja
neinSchleifenbedingung
Schleifenrumpf (Block)
1.3.36
#--------------------------------------------------------------------------------------
# ganzlog.py
#--------------------------------------------------------------------------------------
# Das Programm liest int-Wert n von der Kommandozeile ein
# und gibt den ganzzahligen Logarithmus von n zur Basis 2 aus.
import sys
zahl = int( sys.argv[1] )
zaehler = 0 # zaehler zahlt, wie oft durch 2 geteilt werden kann.
while zahl > 1:
print('zahl ist ' + str(zahl) + ', zaehler ist ' + str(zaehler))
zaehler = zaehler + 1
zahl = zahl//2
print('Der ganzzahlige Logarithmus von ' + str(zahl) + ' zur Basis 2 ist ' +
str(zaehler) + '.')
#------------------------------------------------------------------------------------
# python ganzlog.py 538
# zahl ist 538, zaehler ist 0
# zahl ist 269, zaehler ist 1
# zahl ist 134, zaehler ist 2
# zahl ist 67, zaehler ist 3
# zahl ist 33, zaehler ist 4
# zahl ist 16, zaehler ist 5
# zahl ist 8, zaehler ist 6
# zahl ist 4, zaehler ist 7
# zahl ist 2, zaehler ist 8
# Der ganzzahlige Logarithmus von 538 zur Basis 2 ist 9.
1.3.37
Jetzt wissen wir ungefahr die Wahrscheinlichkeit, mit zwei Wurfeln die Wurfelsumme 7 zu wurfeln.
Wie sind die Wahrscheinlichkeiten fur andere Wurfelsummen 2, 3, . . . , 12?
Wir erweitern das Programm so,
dass nacheinander alle Wurfelsummen durchprobiert werden.
Idee fur den Algorithmus:
fur alle Wurfelsummen 2, 3, . . . , 12:bestimme die Wkeit,mit zwei Wurfeln diese Wurfelsumme zu wurfeln und gib sie aus(das konnen wir wie in siebenwuerfeln.py machen)
1.3.38
#------------------------------------------------------------------------------------
# wuerfelsummen.py
#------------------------------------------------------------------------------------
# Ermittle die Wahrscheinlichkeit, dass mit zwei Wurfeln
# eine bestimmte Zahl gewurfelt wird, mittels Simulation.
# Die Anzahl der Experimente, die bei jeder Simulation durchgefuhrt werden,
# wird von der Kommandozeile eingelesen.
import sys, random
versuchszahl = int( sys.argv[1] ) # die Anzahl der Wiederholungen jedes Experiments
# Fur jede Wurfelsumme von 2 bis 12 wird das Experiment durchgefuhrt
for wuerfelsumme in range(2,13):
erfolgsZaehler = 0 # Zahler fur die erfolgreichen Experimente
# Das Experiment fur summe wird versuchszahl mal wiederholt.
for i in range(0,versuchszahl):
# Zwei Wurfel werden geworfen.
# Der Wurf ist erfolgreich, wenn summe die Wurfelsumme ist.
if random.randrange(1,7) + random.randrange(1,7) == summe:
erfolgsZaehler += 1
# Ausgabe der Erfolgswahrscheinlichkeit (mit gut lesbarer Darstellung).
print('Summe ' + ' '*(summe<10) + str(summe) + ': Wkeit. 1/'
+ str(int(round(1/(float(erfolgsZahler)/versuchszahl)))))
1.3.39
# python wuerfelsummen.py 100
# Summe 2: Wkeit. 1/33
# Summe 3: Wkeit. 1/50
# Summe 4: Wkeit. 1/11
# Summe 5: Wkeit. 1/10
# Summe 6: Wkeit. 1/6
# Summe 7: Wkeit. 1/10
# Summe 8: Wkeit. 1/10
# Summe 9: Wkeit. 1/8
# Summe 10: Wkeit. 1/11
# Summe 11: Wkeit. 1/13
# Summe 12: Wkeit. 1/50
# python wuerfelsummen.py 100000
# Summe 2: Wkeit. 1/36
# Summe 3: Wkeit. 1/18
# Summe 4: Wkeit. 1/12
# Summe 5: Wkeit. 1/9
# Summe 6: Wkeit. 1/7
# Summe 7: Wkeit. 1/6
# Summe 8: Wkeit. 1/7
# Summe 9: Wkeit. 1/9
# Summe 10: Wkeit. 1/12
# Summe 11: Wkeit. 1/18
# Summe 12: Wkeit. 1/36
1.3.40
17 und 4
Wir spielen 17+4 mit Wurfeln.
Zwei Spieler spielen.
Jeder wurfelt, ohne dass es der andere sehen kann.
Ziel des Spiels ist es, den Wert 21 zu erreichen.
Dazu wurfelt der Spieler mit seinem Wurfel und summiert die gewurfelten Zahlen.
Man kann jederzeit aufhoren zu wurfeln.
Das Ergebnis des Spielers ist seine Summe der gewurfelten Zahlen.
Ein Spieler mit einem Ergebnis ą 21 hat verloren.
Haben beide Spieler ein Ergebnis ď 21,
dann gewinnt der Spieler mit dem hoheren Ergebnis.
Wir wollen ein Programm entwickeln, mit dem man eine gute Strategie fur das Spiel finden kann.
1.3.41
Vorlesung 03
1. Elemente des Programmierens
1.2 Grundlegende Daten-Typen
1.3 Verzweigungen und Schleifen
1.4 ArraysEindimensionale Arrays
Allgemeines uber Objekte in Python
Zweidimensionale Arrays
1.5 Ein- und Ausgabe
1.6 Dictionaries und Abschluss-Beispiel Page Rank
1.4.1
1.4 Arrays
Bisher haben wir Variablen benutzt,
um ein einfaches”Datum“ zu speichern und darauf zuzugreifen –
eine Zahl, einen Text oder einen Wahrheitswert.
Was macht man, wenn man”sehr viele“ Daten speichern muss,
um daraus ein Ergebnis zu berechnen?
Das geht mit einer entsprechenden Datenstruktur.
Sie dient der Organisation von Daten zur Verarbeitung mit einem Computer-Programm.
Eine einfache Datenstruktur ist das Array (in Python list genannt),
mit dem man z.B. beliebig lange Folgen von Zahlen/Strings/Arrays etc. verarbeiten kann.
1.4.2
Beispiel: Berechnung der mittleren absoluten Abweichung vom Mittelwert
Bsp.: die Zahlen 17, 23, 16, 22, 7 haben Mittelwert 17`23`16`22`75 “ 17.
Die absoluten Abweichungen vom Mittelwert der Zahlen sind
Zahl: 17 23 16 22 7
absolute Abweichung von 17: 0 6 1 5 10
Also ist 0`6`1`5`105 “ 22
5 die mittlere absolute Abweichung der Zahlen von ihrem Mittelwert.
Idee fur den Algorithmus:
lies Zahlen von der Kommandozeile/Konsole und speichere sie (aber wie?)
berechne den Mittelwert der Zahlen
summiere die absoluten Abweichungen vom Mittelwert der Zahlen auf
das Ergebnis ist der Quotient aus dieser Summe und der Anzahl der Zahlen
Um die beliebig vielen Zahlen zu speichern, kann man ein Array benutzen . . .1.4.3
Beispiel: Berechnung der mittleren absoluten Abweichung vom Mittelwert
Bsp.: die Zahlen 17, 23, 16, 22, 7 haben Mittelwert 17`23`16`22`75 “ 17.
Die absoluten Abweichungen vom Mittelwert der Zahlen sind
Zahl: 17 23 16 22 7
absolute Abweichung von 17: 0 6 1 5 10
Also ist 0`6`1`5`105 “ 22
5 die mittlere absolute Abweichung der Zahlen von ihrem Mittelwert.
Idee fur den Algorithmus:
lies Zahlen von der Kommandozeile/Konsole und speichere sie (aber wie?)
berechne den Mittelwert der Zahlen
summiere die absoluten Abweichungen vom Mittelwert der Zahlen auf
das Ergebnis ist der Quotient aus dieser Summe und der Anzahl der Zahlen
Um die beliebig vielen Zahlen zu speichern, kann man ein Array benutzen . . .1.4.3
Beispiel: Berechnung der mittleren absoluten Abweichung vom Mittelwert
Bsp.: die Zahlen 17, 23, 16, 22, 7 haben Mittelwert 17`23`16`22`75 “ 17.
Die absoluten Abweichungen vom Mittelwert der Zahlen sind
Zahl: 17 23 16 22 7
absolute Abweichung von 17: 0 6 1 5 10
Also ist 0`6`1`5`105 “ 22
5 die mittlere absolute Abweichung der Zahlen von ihrem Mittelwert.
Idee fur den Algorithmus:
lies Zahlen von der Kommandozeile/Konsole und speichere sie (aber wie?)
berechne den Mittelwert der Zahlen
summiere die absoluten Abweichungen vom Mittelwert der Zahlen auf
das Ergebnis ist der Quotient aus dieser Summe und der Anzahl der Zahlen
Um die beliebig vielen Zahlen zu speichern, kann man ein Array benutzen . . .1.4.3
Datentyp list (Array) – Folge von Objekten
Die einfachste Vorstellung von einem Array ist eine Zuordnung von Indizes zu Werten.
Literal Vorstellung
['Gallia', 'est', 'div', 'omnis'] Index 0 1 2 3
Wert 'Gallia' 'est' 'div' 'omnis'
Die Programmzeilen
a = ['Gallia', 'est','div', 'omnis']
print(a)
print(a[3])
a[3] = a[2] + 'isa'
print(a[3])
a[2] = 'omnis'
print(a)
print(len(a))
erzeugen die Ausgabe
['Gallia', 'est', 'div', 'omnis']
omnis
divisa
['Gallia', 'est', 'omnis', 'divisa']
4
Die Lange von Array a[] ist 4. Sie ist der Funktionswert von len(a).Arrays 1.4.4
Datentyp list (Array) – Folge von Objekten
Die einfachste Vorstellung von einem Array ist eine Zuordnung von Indizes zu Werten.
Literal Vorstellung
['Gallia', 'est', 'div', 'omnis'] Index 0 1 2 3
Wert 'Gallia' 'est' 'div' 'omnis'
Die Programmzeilen
a = ['Gallia', 'est','div', 'omnis']
print(a)
print(a[3])
a[3] = a[2] + 'isa'
print(a[3])
a[2] = 'omnis'
print(a)
print(len(a))
erzeugen die Ausgabe
['Gallia', 'est', 'div', 'omnis']
omnis
divisa
['Gallia', 'est', 'omnis', 'divisa']
4
Die Lange von Array a[] ist 4. Sie ist der Funktionswert von len(a).Arrays 1.4.4
Beispiel: Berechnung des Mittelwertes der Werte eines Arrays
Literal Vorstellung
[ 17, 14, 23, 32, 25 ] Index 0 1 2 3 4
Wert 17 14 23 32 25
Aufgabe: berechne den Mittelwert der Werte eines Arrays
Idee fur den Algorithmus: Alle Zahlenwerte des Arrays werden summiert.Abschließend wird die Summe geteilt durch die Anzahl der Zahlen ausgegeben.
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
summe = summe + zahlen[0]
summe = summe + zahlen[1]
summe = summe + zahlen[2]
summe = summe + zahlen[3]
summe = summe + zahlen[4]
print(summe/5)Arrays durchlaufen 1.4.5
Beispiel: Berechnung des Mittelwertes der Werte eines Arrays
Literal Vorstellung
[ 17, 14, 23, 32, 25 ] Index 0 1 2 3 4
Wert 17 14 23 32 25
Aufgabe: berechne den Mittelwert der Werte eines Arrays
Idee fur den Algorithmus: Alle Zahlenwerte des Arrays werden summiert.Abschließend wird die Summe geteilt durch die Anzahl der Zahlen ausgegeben.
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
summe = summe + zahlen[0]
summe = summe + zahlen[1]
summe = summe + zahlen[2]
summe = summe + zahlen[3]
summe = summe + zahlen[4]
print(summe/5)Arrays durchlaufen 1.4.5
Beispiel: Berechnung des Mittelwertes der Werte eines Arrays
Literal Vorstellung
[ 17, 14, 23, 32, 25 ] Index 0 1 2 3 4
Wert 17 14 23 32 25
Aufgabe: berechne den Mittelwert der Werte eines Arrays
Idee fur den Algorithmus: Alle Zahlenwerte des Arrays werden summiert.Abschließend wird die Summe geteilt durch die Anzahl der Zahlen ausgegeben.
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
summe = summe + zahlen[0]
summe = summe + zahlen[1]
summe = summe + zahlen[2]
summe = summe + zahlen[3]
summe = summe + zahlen[4]
print(summe/5)
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
for i in range(0,5):
summe = summe + zahlen[i]
print(summe/5)Arrays durchlaufen 1.4.5
Beispiel: Berechnung des Mittelwertes der Werte eines Arrays
Literal Vorstellung
[ 17, 14, 23, 32, 25 ] Index 0 1 2 3 4
Wert 17 14 23 32 25
Aufgabe: berechne den Mittelwert der Werte eines Arrays
Idee fur den Algorithmus: Alle Zahlenwerte des Arrays werden summiert.Abschließend wird die Summe geteilt durch die Anzahl der Zahlen ausgegeben.
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
summe = summe + zahlen[0]
summe = summe + zahlen[1]
summe = summe + zahlen[2]
summe = summe + zahlen[3]
summe = summe + zahlen[4]
print(summe/5)
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
for i in range(5):
summe = summe + zahlen[i]
print(summe/5)Arrays durchlaufen 1.4.5
Beispiel: Berechnung des Mittelwertes der Werte eines Arrays
Literal Vorstellung
[ 17, 14, 23, 32, 25 ] Index 0 1 2 3 4
Wert 17 14 23 32 25
Aufgabe: berechne den Mittelwert der Werte eines Arrays
Idee fur den Algorithmus: Alle Zahlenwerte des Arrays werden summiert.Abschließend wird die Summe geteilt durch die Anzahl der Zahlen ausgegeben.
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
summe = summe + zahlen[0]
summe = summe + zahlen[1]
summe = summe + zahlen[2]
summe = summe + zahlen[3]
summe = summe + zahlen[4]
print(summe/5)
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
for i in range(len(zahlen)):
summe = summe + zahlen[i]
print(summe/len(zahlen))Arrays durchlaufen 1.4.5
Beispiel: Berechnung des Mittelwertes der Werte eines Arrays
Literal Vorstellung
[ 17, 14, 23, 32, 25 ] Index 0 1 2 3 4
Wert 17 14 23 32 25
Aufgabe: berechne den Mittelwert der Werte eines Arrays
Idee fur den Algorithmus: Alle Zahlenwerte des Arrays werden summiert.Abschließend wird die Summe geteilt durch die Anzahl der Zahlen ausgegeben.
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
summe = summe + zahlen[0]
summe = summe + zahlen[1]
summe = summe + zahlen[2]
summe = summe + zahlen[3]
summe = summe + zahlen[4]
print(summe/5)
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
for i in range(len(zahlen)):
summe += zahlen[i]
print(summe/len(zahlen))Arrays durchlaufen 1.4.5
Beispiel: Berechnung des Mittelwertes der Werte eines Arrays
Literal Vorstellung
[ 17, 14, 23, 32, 25 ] Index 0 1 2 3 4
Wert 17 14 23 32 25
Aufgabe: berechne den Mittelwert der Werte eines Arrays
Idee fur den Algorithmus: Alle Zahlenwerte des Arrays werden summiert.Abschließend wird die Summe geteilt durch die Anzahl der Zahlen ausgegeben.
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
for z in zahlen:
summe += z
print(summe/len(zahlen))
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
for i in range(len(zahlen)):
summe += zahlen[i]
print(summe/len(zahlen))Arrays durchlaufen 1.4.5
Beispiel: Berechnung des Mittelwertes der Werte eines Arrays
Literal Vorstellung
[ 17, 14, 23, 32, 25 ] Index 0 1 2 3 4
Wert 17 14 23 32 25
Aufgabe: berechne den Mittelwert der Werte eines Arrays
Idee fur den Algorithmus: Alle Zahlenwerte des Arrays werden summiert.Abschließend wird die Summe geteilt durch die Anzahl der Zahlen ausgegeben.
zahlen = [ 17, 14, 23, 32, 25 ]
summe = 0
for z in zahlen:
summe += z
print(summe/len(zahlen))
zahlen = [ 17, 14, 23, 32, 25 ]
print(sum(zahlen)/len(zahlen))Arrays durchlaufen 1.4.5
Beispiel: Berechnung des Mittelwertes der Werte eines Arrays
#-------------------------------------------------------------------------------
# mittelwert1.py
#-------------------------------------------------------------------------------
# Berechne den Mittelwert der Werte, die im Array zahlen[] gespeichert sind.
#-------------------------------------------------------------------------------
# Erzeuge das Array mit den Zahlen.
zahlen = [17, 4, 23, 999, 46, 24, 1, 1, 13, 18]
# summe ist die Summe der bisher aufsummierten Werte.
summe = 0
# Durchlaufe alle Indizes des Arrays zahlen[] und
# summiere die zugeordneten Zahlenwerte auf.
for i in range(len(zahlen)):
summe = summe + zahlen[i]
print('i: ' + str(i) + ' summe: ' + str(summe))
# Gib die berechnete Summe geteilt durch die Anzahl der aufsummierten Zahlenwerte aus.
print( 'Der Mittelwert ist ' + str(summe/len(zahlen)) + ' .' )
#----------------------------
# python3 mittelwert1.py
# i: 0 summe: 17
# i: 1 summe: 21
# i: 2 summe: 44
# i: 3 summe: 1043
# i: 4 summe: 1089
# i: 5 summe: 1113
# i: 6 summe: 1114
# i: 7 summe: 1115
# i: 8 summe: 1128
# i: 9 summe: 1146
# Der Mittelwert ist 114.6 .
zahlen[] ist ein Array der Lange 10.
Die Elemente von zahlen[] sind mit zahlen[0], zahlen[1],zahlen[2],. . . , zahlen[9] ansprechbar.
len(zahlen) ist die Lange des Arrays zahlen.Arrays durchlaufen 1.4.6
Das gleiche nochmal – aber anders aufgeschrieben
#-----------------------------------------------------------------------------
# mittelwert2.py
#-----------------------------------------------------------------------------
# Berechne den Mittelwert der Werte, die im Array zahlen[] gespeichert sind.
#-----------------------------------------------------------------------------
zahlen = [17, 4, 23, 999, 46, 24, 1, 1, 13, 18]
summe = 0 # Die Summe der bisher aufsummierten Zahlenwerte.
# Durchlaufe alle Werte, die im Array zahlen[] gespeichert
# sind, und summiere sie auf.
for i in zahlen:
summe += i
print('i: ' + str(i) + ' summe: ' + str(summe))
# Gib die berechnete Summe geteilt durch die Anzahl der aufsummierten Zahlenwerte aus.
print('Der Mittelwert ist ' + str(summe/len(zahlen)) + ' .')
#------------------------
# python3 mittelwert2.py
# i: 17 summe: 17
# i: 4 summe: 21
# i: 23 summe: 44
# i: 999 summe: 1043
# i: 46 summe: 1089
# i: 24 summe: 1113
# i: 1 summe: 1114
# i: 1 summe: 1115
# i: 13 summe: 1128
# i: 8 summe: 1146
# Der Mittelwert ist 114.6 .
Arrays durchlaufen 1.4.7
Beispiel:
Berechnung des Mittelwertes der uber die Kommandozeile eingegebenen Werte
Die Variable sys.argv ist ein Array.
sys.argv[0] ist der Name des aufgerufenen Python-Programms.sys.argv[1], sys.argv[2], . . . sind die beim Programmaufruf ubergebenen Argumente.
#--------------------------------------------------------------------------------------------
# mittelwert3.py
#--------------------------------------------------------------------------------------------
# Berechne den Mittelwert der Werte, die uber die Kommandozeile eingegeben werden.
# Sie stehen im Array sys.argv[] unter den Indizes 1,2,...,len(sys.argv)-1 .
#--------------------------------------------------------------------------------------------
import sys
summe = 0
for i in range(1,len(sys.argv)): # for i in sys.argv[1:] :
summe = summe + int(sys.argv[i]) # summe = summe + int(i)
print('Der Mittelwert der eingegebenen Zahlen ist ' + str(summe/(len(sys.argv)-1)) + ' .')
#--------------------------------------------------------------------------------------------
# python3 mittelwert3.py 1 2 3 4 5 6 7 8 9 10
# Der Mittelwert der eingegebenen Zahlen ist 5.5 .
Arrays durchlaufen 1.4.8
Bisherige Zusammenfassung: Benutzung des Datentyps list
Erzeugen eines Arrays:
[a0, a1, ... , an´1] ein Array der Lange n mit den Elementen a0, a1, ... , an´1
[ ] ein Array der Lange 0 (ohne Elemente)
Zugriff auf Elemente von Arrays:
a[i] das i-te Element von a[] (indizierter Zugriff)
a[i] = x ersetze das i-te Element von a[] durch x (indizierte Zuweisung)
for v in a: weise v jedes Element von a[] zu (Durchlaufen)
a[i:j] ein neues Array [a[i], a[i+1], ..., a[j-1]],
i hat Default 0 und j hat Default len(a) (Slicing)
v in a ergibt True, falls Element v in Array a vorkommt, sonst False
Funktionen zum Arbeiten mit Arrays:
len(a) die Anzahl der Elemente von a[]
sum(a) die Summe der Elemente von a[] (sie mussen summierbar sein)
min(a) ein kleinstes Element von a[] (sie mussen vergleichbar sein)
max(a) ein großtes Element von a[] (sie mussen vergleichbar sein) Operationen auf Arrays 1.4.9
Mehr uber den Datentyp listOperatoren + *
Die Operation + zwischen list und list schreibt Arrays hintereinander (Konkatenation).
Der Ausdruck [2, 4, 6] + [170, 14]
ergibt das neue Array [2, 4, 6, 170, 14] .
a += [3,4] hangt die Eintrage 3,4 an das Array a an (ahnlich zu a = a + [3,4]).
Die Operation * ist eine Operation zwischen list und int.
Der Ausdruck [10, 20, 30] * 4
ergibt das neue Array [10, 20, 30, 10, 20, 30, 10, 20, 30, 10, 20, 30] .
a *= 4 hangt das Array a 3mal an a an.
Operationen auf Arrays 1.4.10
Mehr uber den Datentyp listOperatoren + *
Die Operation + zwischen list und list schreibt Arrays hintereinander (Konkatenation).
Der Ausdruck [2, 4, 6] + [170, 14]
ergibt das neue Array [2, 4, 6, 170, 14] .
a += [3,4] hangt die Eintrage 3,4 an das Array a an (ahnlich zu a = a + [3,4]).
Die Operation * ist eine Operation zwischen list und int.
Der Ausdruck [10, 20, 30] * 4
ergibt das neue Array [10, 20, 30, 10, 20, 30, 10, 20, 30, 10, 20, 30] .
a *= 4 hangt das Array a 3mal an a an.
Operationen auf Arrays 1.4.10
Zuruck zum Anfangsbeispiel:
Berechnung der mittleren absoluten Abweichung vom Mittelwert
Bsp.: die Zahlen 17, 23, 16, 22, 7 haben Mittelwert 17`23`16`22`75 “ 17.
Die absoluten Abweichungen der einzelnen Zahlen vom Mittelwert sind
Zahl: 17 23 16 22 7
absolute Abweichung von 17: 0 6 1 5 10
Also ist 0`6`1`5`105 “ 22
5 die mittlere absolute Abweichung der Zahlen von ihrem Mittelwert.
Idee fur den Algorithmus:
lies Zahlen von der Konsole und speichere sie in einem Array
berechne den Mittelwert der Zahlen
summiere die absoluten Abweichungen vom Mittelwert der Zahlen auf
das Ergebnis ist der Quotient aus dieser Summe und der Anzahl der Zahlenmittlere Abweichung vom Mittelwert 1.4.11
Zuruck zum Anfangsbeispiel:
Berechnung der mittleren absoluten Abweichung vom Mittelwert
Bsp.: die Zahlen 17, 23, 16, 22, 7 haben Mittelwert 17`23`16`22`75 “ 17.
Die absoluten Abweichungen der einzelnen Zahlen vom Mittelwert sind
Zahl: 17 23 16 22 7
absolute Abweichung von 17: 0 6 1 5 10
Also ist 0`6`1`5`105 “ 22
5 die mittlere absolute Abweichung der Zahlen von ihrem Mittelwert.
Idee fur den Algorithmus:
lies Zahlen von der Konsole und speichere sie in einem Array
berechne den Mittelwert der Zahlen
summiere die absoluten Abweichungen vom Mittelwert der Zahlen auf
das Ergebnis ist der Quotient aus dieser Summe und der Anzahl der Zahlenmittlere Abweichung vom Mittelwert 1.4.11
#----------------------------------------------------------------------------------------
# mittlere-abweichung.py
#----------------------------------------------------------------------------------------
# Berechne die mittlere absolute Abweichung vom Mittelwert der Werte,
# die von standard input gelesen werden.
#----------------------------------------------------------------------------------------
import sys
print('Bitte geben Sie zeilenweise ganze Zahlen ein.\nDie Eingabe endet mit <Strg+d>.')
# Die eingegebenen Zahlen werden
# im Array zahlen gespeichert.
zahlen = []
# Lies Zahlen von standard input und
# fuge sie zum Array zahlen hinzu.
for z in sys.stdin:
zahlen += [int(z)]
# Berechne den Mittelwert der eingegebenen Zahlen.
mittelwert = sum(zahlen)/len(zahlen)
# Summiere die absoluten Abweichungen der eingegebenen Zahlen vom Mittelwert auf.
summe = 0
for z in zahlen:
summe += abs(z-mittelwert)
# Gib den Mittelwert der aufsummierten Werte aus.
print('Die mittlere absolute Abweichung vom Mittelwert ist ' + str(summe/len(zahlen)) + ' .')mittlere Abweichung vom Mittelwert 1.4.12
#----------------------------------------------------------------------------------------
# mittlere-abweichung.py
#----------------------------------------------------------------------------------------
# Berechne die mittlere absolute Abweichung vom Mittelwert der Werte,
# die von standard input gelesen werden.
#----------------------------------------------------------------------------------------
import sys
print('Bitte geben Sie zeilenweise ganze Zahlen ein.\nDie Eingabe endet mit <Strg+d>.')
# Die eingegebenen Zahlen werden
# im Array zahlen gespeichert.
zahlen = []
# Lies Zahlen von standard input und
# fuge sie zum Array zahlen hinzu.
for z in sys.stdin:
zahlen += [int(z)]
# Berechne den Mittelwert der eingegebenen Zahlen.
mittelwert = sum(zahlen)/len(zahlen)
# Summiere die absoluten Abweichungen der eingegebenen Zahlen vom Mittelwert auf.
summe = 0
for z in zahlen:
summe += abs(z-mittelwert)
# Gib den Mittelwert der aufsummierten Werte aus.
print('Die mittlere absolute Abweichung vom Mittelwert ist ' + str(summe/len(zahlen)) + ' .')
#----------------------------------------------------------
# python3 mittlere-abweichung.py
# Bitte geben Sie zeilenweise ganze Zahlen ein.
# Die Eingabe endet mit <Strg+d>.
# 1
# 2
# 3
# 4
# 5
# 6
## Strg+d
# Die mittlere absolute Abweichung vom Mittelwert ist 1.5 .
mittlere Abweichung vom Mittelwert 1.4.12
Beispiel: Wie oft wurfelt man Summe i “ 2, 3, . . . , 7, . . . , 12 mit zwei Wurfeln?
Um die Erwartungswerte zu bestimmen, fuhren wir das Experiment
wurfele mit 2 Wurfelndas Ergebnis des Experiments ist die Summe der Wurfelzahle mit, wie oft jede Summe gewurfelt wurde
haufig durch und berechnen fur jede Summe die relative Haufigkeit, mit der sie gewurfelt wurde.
Die Idee zur Durchfuhrung des Experiments:
Daten: wir speichern die Zahler fur die gewurfelten Summen im Array wuerfe[]
wenn i gewurfelt wurde, wird wuerfe[i] um 1 hochgezahlt
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
Wurfelwahrscheinlichkeiten 1.4.13
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
Vorstellung vom Ablauf der Experimentreihe
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei iwuerfe[i] = wuerfe[i] + 1
”Aktion“ i wuerfe
Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 0 0 0 0 0 0 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 0 0 0 0 0
wurfele 8 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 1 0 0 0 0 1 0 0 0 0
wurfele 3 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 0 2 0 0 0 0 1 0 0 0 0...
......
wurfele 9 Index 0 1 2 3 4 5 6 7 8 9 10 11 12
Wert 0 0 10 20 30 40 50 60 50 40 30 20 10
Wurfelwahrscheinlichkeiten 1.4.14
#--------------------------------------------------------------------------------------------------------
# wuerfeln.py
#--------------------------------------------------------------------------------------------------------
# Das Programm bestimmt fur alle Zahlen i=2,3,...12,
# mit welcher Wahrscheinlichkeit sie mit 2 Wurfeln gewurfelt werden.
#--------------------------------------------------------------------------------------------------------
import sys, random
# Die Experimentreihe wird vorbereitet.
n = int( sys.argv[1] ) # Die Anzahl der Experimente wird von der Kommandozeile eingelesen.
wuerfe = [0]*13 # wuerfe[i] speichert, wieoft i gewurfelt wurde
# Die Experimentreihe wird durchgefuhrt.
for e in range(0,n): # es werden n Experimente durchgefuhrt
# Das Experiment: zwei Wurfel werden geworfen und ihre Summe wird berechnet.
wuerfelsumme = random.randrange(1,7) + random.randrange(1,7)
# Auswertung des Experiments:
wuerfe[ wuerfelsumme ] += 1
# Das Ergebnis der Experimentreihe wird ausgegeben.
for i in range(2,13):
erfolgsWkeit = wuerfe[i]/n
print('Die Wahrscheinlichkeit, eine '+str(i)+' zu wurfeln, ist ' + str(erfolgsWkeit) + '.' )
print(' D.h. etwa einer von ' + str(round(1/erfolgsWkeit)) + ' Wurfen ist ' +str(i)+'.' )
Wurfelwahrscheinlichkeiten 1.4.15
#--------------------------------------------------------------------------------------------------------
# python3 wuerfeln.py 1000000
# Die Wahrscheinlichkeit, eine 2 zu wurfeln, ist 0.027759.
# D.h. etwa einer von 36 Wurfen ist 2.
# Die Wahrscheinlichkeit, eine 3 zu wurfeln, ist 0.055723.
# D.h. etwa einer von 18 Wurfen ist 3.
# Die Wahrscheinlichkeit, eine 4 zu wurfeln, ist 0.083432.
# D.h. etwa einer von 12 Wurfen ist 4.
# Die Wahrscheinlichkeit, eine 5 zu wurfeln, ist 0.110923.
# D.h. etwa einer von 9 Wurfen ist 5.
# Die Wahrscheinlichkeit, eine 6 zu wurfeln, ist 0.138998.
# D.h. etwa einer von 7 Wurfen ist 6.
# Die Wahrscheinlichkeit, eine 7 zu wurfeln, ist 0.166332.
# D.h. etwa einer von 6 Wurfen ist 7.
# Die Wahrscheinlichkeit, eine 8 zu wurfeln, ist 0.138795.
# D.h. etwa einer von 7 Wurfen ist 8.
# Die Wahrscheinlichkeit, eine 9 zu wurfeln, ist 0.111227.
# D.h. etwa einer von 9 Wurfen ist 9.
# Die Wahrscheinlichkeit, eine 10 zu wurfeln, ist 0.083128.
# D.h. etwa einer von 12 Wurfen ist 10.
# Die Wahrscheinlichkeit, eine 11 zu wurfeln, ist 0.055919.
# D.h. etwa einer von 18 Wurfen ist 11.
# Die Wahrscheinlichkeit, eine 12 zu wurfeln, ist 0.027764.
# D.h. etwa einer von 36 Wurfen ist 12.
Wurfelwahrscheinlichkeiten 1.4.16
Beispiel: Wie oft muss man wurfeln . . .
Wie oft muss man wurfeln, bis man erstmals eine Zahl zum zweiten Mal wurfelt?
Um den Erwartungswert zu bestimmen, fuhren wir das Experiment
wurfele solange, bis erstmals eine Zahl zum zweiten Mal gewurfelt wird;das Ergebnis des Experiments ist die Anzahl der Wurfe
haufig durch und berechnen den Mittelwert der Ergebnisse.
Die Idee zur Durchfuhrung des Experiments:
Daten: wir speichern False fur jede wurfelbare Zahl 1 . . . 6 im Array gewuerfelt[]
wenn i gewurfelt wurde, wird gewuerfelt[i] auf True gesetzt
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
Geburtstagsparadoxon 1.4.17
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wzahle, wie oft gewurfelt wurdefalls gewuerfelt[w],
dann beende das Experimentsonst setze gewuerfelt[w] = True
und wurfele weiter (s.o.)
”Aktion“ i zaehler gewuerfelt
0Index 0 1 2 3 4 5 6
Wert False False False False False False False
wurfele 3 1 Index 0 1 2 3 4 5 6
Wert False False False True False False False
wurfele 5 2 Index 0 1 2 3 4 5 6
Wert False False False True False True False
wurfele 2 3 Index 0 1 2 3 4 5 6
Wert False False True True False True False
wurfele 5 4Geburtstagsparadoxon 1.4.18
#---------------------------------------------------------------------------------------------
# doppeltgewuerfelt_v1.py
#---------------------------------------------------------------------------------------------
# Es wird experimentell bestimmt, wie oft man mit einem 6er-Wurfel
# wurfeln muss, bis man eine Zahl doppelt gewurfelt hat.
#---------------------------------------------------------------------------------------------
import random
# Das Experiment wird vorbereitet.
runden = 100000 # die Anzahl der Wiederholungen des Experiments
wurfzaehler = 0 # die Anzahl, wie oft insgesamt gewurfelt wurde
# Das Experiment wird runden mal ausgefuhrt.
# Es besteht darin, solange zu wurfeln, bis eine Zahl zweimal gewurfelt wurde.
for i in range(runden):
# gewuerfelt[i] ist zu Beginn False und wird auf True gesetzt, wenn i gewurfelt wurde
gewuerfelt = [False]*7
# Es wird wiederholt gewurfelt, bis erstmals eine bereits gewurfelte Zahl gewurfelt wird.
wurf = random.randrange(1,7)
wurfzaehler += 1
while not gewuerfelt[wurf]:
gewuerfelt[wurf] = True # speichere den Wurf in gewuerfelt
wurf = random.randrange(1,7) # wurfele nochmal
wurfzaehler += 1
# Die Experimente werden ausgewertet.
print('Um eine Zahl zweimal zu wurfeln, braucht man im Mittel ' + str(wurfzaehler/runden) + ' Wurfe.')
print('Das wurde mit ' + str(runden) + ' Experimenten ermittelt.')
Geburtstagsparadoxon 1.4.19
# python3 doppeltgewuerfelt_v1.py
Um eine Zahl zweimal zu wurfeln, braucht man im Mittel 3.78344 Wurfe.
Das wurde mit 100000 Experimenten ermittelt.
# python3 doppeltgewuerfelt_v1.py
Um eine Zahl zweimal zu wurfeln, braucht man im Mittel 3.77197 Wurfe.
Das wurde mit 100000 Experimenten ermittelt.
# python3 doppeltgewuerfelt_v1.py
Um eine Zahl zweimal zu wurfeln, braucht man im Mittel 3.77012 Wurfe.
Das wurde mit 100000 Experimenten ermittelt.
Geburtstagsparadoxon 1.4.20
Eine andere Idee zum Speichern der Wurfe
Die Idee zur Durchfuhrung des Experiments:
Daten: wir speichern die gewurfelten Zahlen im Array gewuerfelt[]
jede gewurfelte Zahl wird an gewuerfelt[] angehangt
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
Geburtstagsparadoxon 1.4.21
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
Vorstellung vom Ablauf eines Experiments
Algorithmus zur Durchfuhrung des Experiments: wurfele – das Ergebnis sei wfalls w in gewuerfelt,
dann beende das Experimentsonst hange w an gewuerfelt[] an
und setze das Experiment fort
”Aktion“ w w in gewuerfelt gewuerfelt[]
[]
wurfele 3 False [3]
wurfele 1 False [3,1]
wurfele 4 False [3,1,4]
wurfele 5 False [3,1,4,5]
wurfele 4 True
Ergebnis: es wurde 5mal gewurfelt, bis erstmals eine Zahl zum zweiten Mal gewurfelt wurde.Geburtstagsparadoxon 1.4.22
#------------------------------------------------------------------------------------------
# doppeltgewuerfelt_v2.py
#------------------------------------------------------------------------------------------
import random
# Das Experiment wird vorbereitet.
runden = 100000 # die Anzahl der Wiederholungen des Experiments
wurfzaehler = 0 # die Anzahl, wie oft insgesamt gewurfelt wurde
# Das Experiment wird runden mal ausgefuhrt.
# Es besteht darin, solange zu wurfeln, bis eine Zahl zweimal gewurfelt wurde.
for i in range(runden):
# gewuerfelt speichert die bereits gewurfelten Zahlen
gewuerfelt = []
# Es wird wiederholt gewurfelt, bis erstmals eine bereits gewurfelte Zahl gewurfelt wird.
wurf = random.randrange(1,7)
wurfzaehler += 1
while wurf not in gewuerfelt:
gewuerfelt += [wurf] # speichere den Wurf in gewuerfelt
wurf = random.randrange(1,7) # wurfele nochmal
wurfzaehler += 1
# Die Experimente werden ausgewertet.
print('Um eine Zahl zweimal zu wurfeln, braucht man im Mittel ' + str(wurfzaehler/runden) + ' Wurfe.')
print('Das wurde mit ' + str(runden) + ' Experimenten ermittelt.')
Geburtstagsparadoxon 1.4.23
# python3 doppeltgewuerfelt_v2.py
Um eine Zahl zweimal zu wurfeln, braucht man im Mittel 3.77905 Wurfe.
Das wurde mit 100000 Experimenten ermittelt.
# python3 doppeltgewuerfelt_v2.py
Um eine Zahl zweimal zu wurfeln, braucht man im Mittel 3.77618 Wurfe.
Das wurde mit 100000 Experimenten ermittelt.
# python3 doppeltgewuerfelt_v2.py
Um eine Zahl zweimal zu wurfeln, braucht man im Mittel 3.77245 Wurfe.
Das wurde mit 100000 Experimenten ermittelt.
Geburtstagsparadoxon 1.4.24
Wieviele Leute muss man fragen . . . ?
Wir verallgemeinern das Programm zum Wurfeln fur Wurfel mit beliebig vielen Zahlen.
Damit kann man auch das als Geburtstagsparadoxon bekannte Experiment ausfuhren.
Es fragt, was die erwartete Anzahl von Personen ist,die ich nach ihrem Geburtstag fragen muss,
bis ich zwei Personen gefunden habe, die am gleichen Tag des Jahres Geburtstag haben.
Abstrakter ausgedruckt: man wurfelt mit einem Wurfel mit den Zahlen 0..364.Wie lange muss man wurfeln, bis man eine Zahl zweimal gewurfelt hat?
Dazu mussen wir doppeltgewuerfelt.py so andern,dass man mit beliebig großen Wurfeln wurfeln kann.
Die Große des Wurfels wird von der Kommandozeile gelesen.
Geburtstagsparadoxon 1.4.25
# geburtstagsparadoxon.py
#------------------------------------------------------------------------------------------
import random, sys
# Die Versuchsreihe wird vorbereitet.
n = int(sys.argv[1]) # lies die Anzahl n der Tage eines Jahres von der Kommandozeile
runden = 100000 # die Anzahl der Wiederholungen des Experiments
fragenzaehler = 0 # die Anzahl, wie viele Personen gefragt wurden
# Das Experiment wird runden mal ausgefuhrt.
# Es besteht darin, solange zu fragen, bis zwei gleiche Geburstage geantwortet wurden.
# Die Geburtstage stammen aus dem Bereich 0...n-1.
for i in range(runden):
# genannt enthalt die bereits genannten Geburtstage
genannt = []
# Es wird wiederholt gefragt, bis erstmals eine bereits genannte Zahl auftaucht.
fragenzaehler += 1
antwort = random.randrange(n)
while not antwort in genannt:
# Speichere, dass die Antwort genannt wurde.
genannt += [antwort]
# Frage nach der nachsten Antwort.
fragenzaehler += 1
antwort = random.randrange(n)
# Die Versuchsreihe wird ausgewertet.
print('Um auf einem Planeten mit einem ' + str(n) + '-Tage-Jahr zwei Personen mit gleichem')
print('Geburtstag zu finden, braucht man im Mittel ' + str(fragenzaehler/runden) + ' Personen.')
print('Das wurde mit ' + str(runden) + ' Experimenten ermittelt.') Geburtstagsparadoxon 1.4.26
Wir konnen jetzt das Geburtstagsparadoxon fur Erden-, Merkur-, Mars- und Neptunbewohner
experimentell ausprobieren . . .
# python3 geburtstagsparadoxon.py 365
Um auf einem Planeten mit einem 365-Tage-Jahr zwei Personen mit gleichem
Geburtstag zu finden, braucht man im Mittel 24.54053 Personen.
Das wurde mit 100000 Experimenten ermittelt.
# python3 geburtstagsparadoxon.py 88
Um auf einem Planeten mit einem 88-Tage-Jahr zwei Personen mit gleichem
Geburtstag zu finden, braucht man im Mittel 12.40962 Personen.
Das wurde mit 100000 Experimenten ermittelt.
# python3 geburtstagsparadoxon.py 687
Um auf einem Planeten mit einem 687-Tage-Jahr zwei Personen mit gleichem
Geburtstag zu finden, braucht man im Mittel 33.44678 Personen.
Das wurde mit 100000 Experimenten ermittelt.
# python3 geburtstagsparadoxon.py 60265
Um auf einem Planeten mit einem 60265-Tage-Jahr zwei Personen mit gleichem
Geburtstag zu finden, braucht man im Mittel 309.387 Personen.
Das wurde mit 10000 Experimenten ermittelt.
Geburtstagsparadoxon 1.4.27
Allgemeines uber Objekte in Python
Die”grobe Vorstellung“ bei den informellen Programmablaufen uber die Speicherung von Daten stimmt
naturlich nicht – wir verfeinern die Vorstellung jetzt.
Die Daten werden durch Objekte reprasentiert.Jedes Objekt hat eine Identitat, einen Typ und einen Wert.
§ Die Identitat bestimmt das Objekt eindeutig.(Vorstellung: Adresse des Objektes im Speicher des Computers.)
§ Der Typ beschreibt das Verhalten des Objektes(d.h. die Werte, die es annehmen kann, und die Operationen, die auf ihm erlaubt sind).
§ Der Wert ist der Datentyp-Wert, den es reprasentiert/speichert.Bsp.: ein Objekt vom Typ int kann den Wert 99 speichern.
Eine Objekt-Referenz ist eine konkrete Darstellung der Identitat des Objektes.Python-Programme benutzen Objekt-Referenzen um
§ auf den Wert des Objektes zuzugreifen oder ihn zu andern,
§ auf die Objekt-Referenz zuzugreifen oder sie zu andern.Objekte in Python 1.4.28
§ Ein Literal weist Python an, ein Objekt mit einem bestimmten Wert zu erzeugen.Bsp.: das Literal 99 weist Python an, ein int-Objekt mit Wert 99 zu erzeugen.
§ Eine Variable ist ein Name fur eine Objekt-Referenz.
§ Ein Ausdruck weist Python an, ein Objekt mit dem Wert des Ausdrucks zu erzeugen.Bsp.: wenn das an die Variable a gebundene Objekt den Wert 3 hat, dann weist der Ausdruck 4*a+2
Python an, ein int-Objekt mit Wert 14 zu erzeugen.
§ Eine Zuweisung xVariabley=xAusdrucky weist Python an, ein Objekt mit dem Wert des Ausdrucks zuerzeugen und die Variable daran zu binden.Falls der Ausdruck nur eine Variable ist, dann wird kein neues Objekt erzeugt, sondern das an dieVariable gebundene Objekt genommen.Bsp.: wenn das an die Variable a gebundene Objekt den Wert 3 hat, dann wird fur die Zuweisungb = 4*a+2 ein Objekt mit dem Wert 14 erzeugt und dieses Objekt wird an die Variable b gebunden.
a = 3 3a
b = 4*a + 2 14b
Variable Objekt-Referenz ObjektObjekte in Python 1.4.29
Programmablauf auf dem Objekt-Level
Ein 3-zeiliges Python-Programm und dessen Wirkung auf dem Objekt-Level:
a = 1234 1234a
b = 47 47b
c = a + b 1281c
Objekte in Python 1.4.30
Programmablauf auf dem Objekt-Level
Ein 3-zeiliges Python-Programm und dessen Wirkung auf dem Objekt-Level:
a = 1234 1234a
b = 47 47b
c = a + b 1281c
Objekte in Python 1.4.30
Programmablauf auf dem Objekt-Level
Ein 3-zeiliges Python-Programm und dessen Wirkung auf dem Objekt-Level:
a = 1234 1234a
b = 47 47b
c = a + b 1281c
Objekte in Python 1.4.30
Programmablauf auf dem Objekt-Level
Ein 3-zeiliges Python-Programm und dessen Wirkung auf dem Objekt-Level:
a = 1234 1234a
b = 47 47b
c = a + b 1281c
Objekte in Python 1.4.30
Programmablauf auf dem Objekt-Level
Ein 3-zeiliges Python-Programm und dessen Wirkung auf dem Objekt-Level:
a = 1234 1234a
b = 47 47b
c = a + b 1281c
Objekte in Python 1.4.30
Programmablauf auf dem Objekt-Level
Ein 3-zeiliges Python-Programm und dessen Wirkung auf dem Objekt-Level:
a = 1234 1234a
b = 47 47b
c = a + b 1281c
Objekte in Python 1.4.30
Vertauschung der Werte zweier Variablen. 1234a
47b
t = a 1234a
47b
t
a = b 1234
47b
t
a
b = t 1234
47b
t
a
Objekte in Python 1.4.31
Vertauschung der Werte zweier Variablen. 1234a
47b
t = a 1234a
47b
t
a = b 1234
47b
t
a
b = t 1234
47b
t
a
Objekte in Python 1.4.31
Vertauschung der Werte zweier Variablen. 1234a
47b
t = a 1234a
47b
t
a = b 1234
47b
t
a
b = t 1234
47b
t
a
Objekte in Python 1.4.31
Vertauschung der Werte zweier Variablen. 1234a
47b
t = a 1234a
47b
t
a = b 1234
47b
t
a
b = t 1234
47b
t
a
Objekte in Python 1.4.31
Nicht-veranderbare Datentypen
Objekte der Standard-Typen int, float, string und bool sind nicht veranderbar.
Wenn einer Variablen ein Wert eines Ausdrucks einer dieser Typen zugewiesen wird,dann wird ein neues Objekt mit diesem Wert erzeugt.
s = 'Abcd' ’Abcd’s
s = s + ' ef' ’Abcd’
’ ef’
’Abcd ef’
s
i = 15 15i
i = i + 1 15
1
16
i
Objekte in Python 1.4.32
Nicht-veranderbare Datentypen
Objekte der Standard-Typen int, float, string und bool sind nicht veranderbar.
Wenn einer Variablen ein Wert eines Ausdrucks einer dieser Typen zugewiesen wird,dann wird ein neues Objekt mit diesem Wert erzeugt.
s = 'Abcd' ’Abcd’s
s = s + ' ef' ’Abcd’
’ ef’
’Abcd ef’
s
i = 15 15i
i = i + 1 15
1
16
i
Objekte in Python 1.4.32
Nicht-veranderbare Datentypen
Objekte der Standard-Typen int, float, string und bool sind nicht veranderbar.
Wenn einer Variablen ein Wert eines Ausdrucks einer dieser Typen zugewiesen wird,dann wird ein neues Objekt mit diesem Wert erzeugt.
s = 'Abcd' ’Abcd’s
s = s + ' ef' ’Abcd’
’ ef’
’Abcd ef’
s
i = 15 15i
i = i + 1 15
1
16
i
Objekte in Python 1.4.32
Nicht-veranderbare Datentypen
Objekte der Standard-Typen int, float, string und bool sind nicht veranderbar.
Wenn einer Variablen ein Wert eines Ausdrucks einer dieser Typen zugewiesen wird,dann wird ein neues Objekt mit diesem Wert erzeugt.
s = 'Abcd' ’Abcd’s
s = s + ' ef' ’Abcd’
’ ef’
’Abcd ef’
s
i = 15 15i
i = i + 1 15
1
16
i
Objekte in Python 1.4.32
Arrays
a = [5, 9, 11]0 1 2
3
5 9 11
a
b = a
5 9 11
0 1 2
3a
b
b[1] = 17
5 9 11 17
0 1 2
3a
b
Objekte vom Typ array sind veranderbar (mutable)(anders als Objekte der Standard-Typen int, float, string und bool)!
Objekte in Python 1.4.33
Arrays
a = [5, 9, 11]0 1 2
3
5 9 11
a
b = a
5 9 11
0 1 2
3a
b
b[1] = 17
5 9 11 17
0 1 2
3a
b
Objekte vom Typ array sind veranderbar (mutable)(anders als Objekte der Standard-Typen int, float, string und bool)!
Objekte in Python 1.4.33
Arrays
a = [5, 9, 11]0 1 2
3
5 9 11
a
b = a
5 9 11
0 1 2
3a
b
b[1] = 17
5 9 11 17
0 1 2
3a
b
Objekte vom Typ array sind veranderbar (mutable)(anders als Objekte der Standard-Typen int, float, string und bool)!
Objekte in Python 1.4.33
Arrays
a = [5, 9, 11]0 1 2
3
5 9 11
a
b = a
5 9 11
0 1 2
3a
b
b[1] = 17
5 9 11 17
0 1 2
3a
b
Objekte vom Typ array sind veranderbar (mutable)(anders als Objekte der Standard-Typen int, float, string und bool)!
Objekte in Python 1.4.33
Kopieren eines Arrays mit nicht-veranderbaren Elementen
a = [5, 9, 11]
5 9 11
0 1 2
3a
b = [0]*len(a)
for i in range(len(a)):
b[i] = a[i]
b[1] = 17
0 1 2
3b
0
1d-Array kopieren 1.4.34
Kopieren eines Arrays mit nicht-veranderbaren Elementen
a = [5, 9, 11]
5 9 11
0 1 2
3a
b = [0]*len(a)
for i in range(len(a)):
b[i] = a[i]
b[1] = 17
0 1 2
3b
0
1d-Array kopieren 1.4.34
Kopieren eines Arrays mit nicht-veranderbaren Elementen
a = [5, 9, 11]
5 9 11
0 1 2
3a
b = [0]*len(a)
for i in range(len(a)):
b[i] = a[i]
b[1] = 17
0 1 2
3b
0
1d-Array kopieren 1.4.34
Kopieren eines Arrays mit nicht-veranderbaren Elementen
a = [5, 9, 11]
5 9 11
0 1 2
3a
b = [0]*len(a)
for i in range(len(a)):
b[i] = a[i]
b[1] = 17
0 1 2
3b
0
1d-Array kopieren 1.4.34
Kopieren eines Arrays mit nicht-veranderbaren Elementen
a = [5, 9, 11]
5 9 11
0 1 2
3a
b = [0]*len(a)
for i in range(len(a)):
b[i] = a[i]
b[1] = 17
0 1 2
3b
0
1d-Array kopieren 1.4.34
Kopieren eines Arrays mit nicht-veranderbaren Elementen
a = [5, 9, 11]
5 9 11
0 1 2
3a
b = [0]*len(a)
for i in range(len(a)):
b[i] = a[i]
b[1] = 17
0 1 2
3b
1d-Array kopieren 1.4.34
Kopieren eines Arrays mit nicht-veranderbaren Elementen
a = [5, 9, 11]
5 9 11
0 1 2
3a
b = [0]*len(a)
for i in range(len(a)):
b[i] = a[i]
b[1] = 17
0 1 2
3b
1d-Array kopieren 1.4.34
Kopieren eines Arrays mit nicht-veranderbaren Elementen
a = [5, 9, 11]
5 9 11
0 1 2
3a
b = [0]*len(a)
for i in range(len(a)):
b[i] = a[i]
b[1] = 17
17
0 1 2
3b
1d-Array kopieren 1.4.34
Kopieren eines Arrays mit nicht-veranderbaren Elementen
a = [5, 9, 11]
5 9 11
0 1 2
3a
b = [0]*len(a)
for i in range(len(a)):
b[i] = a[i]
b[1] = 17
17
0 1 2
3b
1d-Array kopieren 1.4.34
#-------------------------------------------------------------
# array-1d-kopieren.py Drei Wege, ein 1d-Array zu kopieren.
#-------------------------------------------------------------
a = [1, 2, 3, 4, 5]
# Kopiere Array a ins Array b.
# Dazu wird zuerst ein Array der Lange len(a) erzeugt.
b = [0] * len(a)
print('Lange von b: ' + str(len(b)))
# Anschließend wird fur jeden Index der Wert eingetragen.
for i in range(len(a)): b[i] = a[i]
print('b: ' + str(b))
# Kopiere Array a ins Array c.
# Dazu wird zuerst ein Array der Lange 0 erzeugt.
c = []
# Anschließend wird das Array fur jeden Index i um den Wert a[i] verlangert.
for i in range(len(a)):
print('Lange von c: ' + str(len(c)))
c += [a[i]] # hange Wert a[i] an das Array c an
print('c: ' + str(c))
# Abschließend die kurzeste Variante.
d = a[:] # das ist Abkurzung von d = a[0:len(a)]
print('d: ' + str(d))
#----------------------------
# python3 array-1d-kopieren.py
# Lange von b: 5
# b: [1, 2, 3, 4, 5]
# Lange von c: 0
# Lange von c: 1
# Lange von c: 2
# Lange von c: 3
# Lange von c: 4
# c: [1, 2, 3, 4, 5]
# d: [1, 2, 3, 4, 5]
1d-Array kopieren 1.4.35
Der Datentyp tuple – Tupel
tuple ist wie list (Array), aber nicht-veranderbar.
Literale vom Typ tuple werden mit runden Klammern beschrieben:
( 17, 4, 23, 12 ) ( 'a', )
Benutzung von Elementen von Tupeln geht wie bei Arrays:
t = ('a', 1, 'b')
b = t[2]
Da Objekte vom Typ tuple nicht-veranderbar sind, geht Folgendes nicht:
t[2] = 42
tuple 1.4.36
Gerne benutzt wird das Unpacking (geht auch bei Arrays):
a = 15
b = 'hello'
( b, a ) = ( a, b )
vertauscht die Werte von a und b.
(a,b) auf der rechten Seite der Zuweisung
erzeugt ein Tupel mit den Werten von a und b (packing).
(b,a) auf der linken Seite der Zuweisung
packt das Tupel von der rechten Seite aus (unpacking):
Variable b wird als Wert das erste Element des”rechten“ Tupels zugewiesen
Variable a erhalt als Wert das nachste Element des”rechten“ Tupels.
Als Kurzschreibweise konnen die Klammern weggelassen werden.
b, a = a, b tuple 1.4.37
Nochmal was zum Datentyp string
Ein String ist wie ein Tupel aus Zeichen.
Also ist Folgendes mit String-Variable s moglich:
§ s[i] das Zeichen mit Index i
§ s[i:j] die Zeichen mit Indizes i...j-1
§ c in s ergibt True, falls Zeichen c in s vorkommt
§ for c in s: ... durchlauft alle Zeichen in s
string 1.4.38
Zusammenfassung
Wir kennen den Datentyp list (Array),
kennen den Unterschied zwischen veranderbaren und nicht-veranderbaren Datentypen,
konnen 1-dimensionale Arrays erzeugen und auf ihre Elemente zugreifen,
kennen die Probleme beim Kopieren von Arrays,
und kennen die”Variante“ tuple (Tupel).
Wir haben gesehen, dass es beim Entwickeln von Programmen
einfacher sein kann, erst ein Programm fur ein einfaches Beispiel zu schreiben
und das dann zu verallgemeinern.
1.4.39
Vorlesung 04
Das Kapitel uber Arrays wird fortgesetzt.
In der letzten Vorlesung wurden 1-dimensionale Arrays betrachtet.
Jetzt geht es weiter mit 2-dimensionalen Arrays.
1. Elemente des Programmierens
1.2 Grundlegende Daten-Typen
1.3 Verzweigungen und Schleifen
1.4 ArraysEindimensionale Arrays
Allgemeines uber Objekte in Python
Zweidimensionale Arrays
1.5 Ein- und Ausgabe
1.6 Dictionaries und Abschluss-Beispiel Page Rank
1.4.40
2-dimensionale Arrays
Beispiel-Aufgabe: Uber die Ergebnisse der Ubungsblatter fuhren wir Buch mittels einer Tabelle.
Zei
len
SpaltenName Blatt 1 Blatt 2 Blatt 3 Blatt 4 Blatt 5
A 20 15 12 8 13B 12 0 20 20 8C 13 12 15 11 9D 18 19 17 18 20E 11 12 0 12 13F 16 13 15 18 20
Wir mochten die mittlere Punktzahl jedes Studenten in allen Ubungsblatternund die mittlere Punktzahl jedes Ubungsblattes wissen.
Dazu speichern wir die Zahlenwerte der Tabelle als 2-dimensionales Array.Jeder Eintrag im Array tabelle ist ein Array, das fur eine Zeile der Tabelle steht.
tabelle = [ [ 20, 15, 12, 8, 13],
[ 12, 0, 20, 20, 8 ],
[ 13, 12, 15, 11, 9 ],
[ 18, 19, 17, 18, 20],
[ 11, 12, 0, 12, 13],
[ 16, 13, 15, 18, 20] ]
tabelle[2] ist [ 13, 12, 15, 11, 9 ].
tabelle[2][3] ist 11.
2d-Arrays benutzen 1.4.41
2-dimensionale Arrays
Beispiel-Aufgabe: Uber die Ergebnisse der Ubungsblatter fuhren wir Buch mittels einer Tabelle.
Zei
len
SpaltenName Blatt 1 Blatt 2 Blatt 3 Blatt 4 Blatt 5
A 20 15 12 8 13B 12 0 20 20 8C 13 12 15 11 9D 18 19 17 18 20E 11 12 0 12 13F 16 13 15 18 20
Wir mochten die mittlere Punktzahl jedes Studenten in allen Ubungsblatternund die mittlere Punktzahl jedes Ubungsblattes wissen.
Dazu speichern wir die Zahlenwerte der Tabelle als 2-dimensionales Array.Jeder Eintrag im Array tabelle ist ein Array, das fur eine Zeile der Tabelle steht.
tabelle = [ [ 20, 15, 12, 8, 13],
[ 12, 0, 20, 20, 8 ],
[ 13, 12, 15, 11, 9 ],
[ 18, 19, 17, 18, 20],
[ 11, 12, 0, 12, 13],
[ 16, 13, 15, 18, 20] ]
tabelle[2] ist [ 13, 12, 15, 11, 9 ].
tabelle[2][3] ist 11.
2d-Arrays benutzen 1.4.41
#-----------------------------------------------------------------------------------------------------
# tabelle-auswerten.py
#-----------------------------------------------------------------------------------------------------
# Berechne die Mittelwerte jeder Zeile und
# die Mittelwerte jeder Spalte der angegebenen Tabelle (d.h. des angegebenen 2-dimensionalen Arrays).
tabelle = [ [ 20, 15, 12, 8, 13],
[ 12, 0, 20, 20, 8 ],
[ 13, 12, 15, 11, 9 ],
[ 18, 19, 17, 20, 12],
[ 11, 12, 0, 12, 13],
[ 16, 13, 15, 18, 20] ]
# Berechne den Mittelwert jeder Zeile der Tabelle und gib ihn aus.
for zeilennr in range(len(tabelle)):
m = sum(tabelle[zeilennr])/len(tabelle[zeilennr])
print( 'Zeile ' + str(zeilennr) + ' hat Mittelwert ' + str(m) + ' .' )
# Berechne den Mittelwert jeder Spalte der Tabelle und gib ihn aus.
# Dabei gehen wir davon aus, dass alle Zeilen gleichviele Spalten haben.
for spaltennr in range(len(tabelle[0])):
spaltensumme = 0
for zeilennr in range(len(tabelle)):
spaltensumme += tabelle[zeilennr][spaltennr]
print('Spalte ' + str(spaltennr) + ' hat Mittelwert ' + str(spaltensumme/len(tabelle)) + ' .')
2d-Arrays benutzen 1.4.42
$ python3 tabelle-auswerten.py
Zeile 0 hat Mittelwert 13.6 .
Zeile 1 hat Mittelwert 12.0 .
Zeile 2 hat Mittelwert 12.0 .
Zeile 3 hat Mittelwert 17.2 .
Zeile 4 hat Mittelwert 9.6 .
Zeile 5 hat Mittelwert 16.4 .
Spalte 0 hat Mittelwert 15.0 .
Spalte 1 hat Mittelwert 11.833333333333334 .
Spalte 2 hat Mittelwert 13.166666666666666 .
Spalte 3 hat Mittelwert 14.833333333333334 .
Spalte 4 hat Mittelwert 12.5 .
tabelle = [ [ 20, 15, 12, 8, 13],
[ 12, 0, 20, 20, 8 ],
[ 13, 12, 15, 11, 9 ],
[ 18, 19, 17, 20, 12],
[ 11, 12, 0, 12, 13],
[ 16, 13, 15, 18, 20] ]
2d-Arrays benutzen 1.4.43
Erzeugung eines 2-dimensionalen Arrays
Erzeuge ein Array mit z Zeilen und s Spalten.Der Eintrag mit Zeilen-Index i und Spalten-Index j soll 'i,j' sein.
Zei
len
din
diz
es
Spaltenindizes0 1 2 3 4
0 '0,0' '0,1' '0,2' '0,3' '0,4'
1 '1,0' '1,1' '1,2' '1,3' '1,4'
2 '2,0' '2,1' '2,2' '2,3' '2,4'
3 '3,0' '3,1' '3,2' '3,3' '3,4'
Erzeuge zuerst ein Array b mit der gewunschten Anzahl von”Platzen“ fur die Zeilen.
Trage dann an jedem Platz von b die entsprechende Zeile ein.
b = [0]*z # Erzeuge Array b mit z Platzen fur die Zeilen.
for zeilennr in range(z): # Gehe durch alle Indizes zeilennr im Array b.
b[zeilennr] = [0]*s # Erzeuge ein Array mit s Platzen als zeilennr-te Zeile von b.
for spaltennr in range(s): # Fulle jeden Eintrag in der zeilennr-ten Zeile von b.
b[zeilennr][spaltennr] = str(zeilennr) + ',' + str(spaltennr)
2d-Arrays erzeugen 1.4.44
Erzeugung eines 2-dimensionalen Arrays
Erzeuge ein Array mit z Zeilen und s Spalten.Der Eintrag mit Zeilen-Index i und Spalten-Index j soll 'i,j' sein.
Zei
len
din
diz
es
Spaltenindizes0 1 2 3 4
0 '0,0' '0,1' '0,2' '0,3' '0,4'
1 '1,0' '1,1' '1,2' '1,3' '1,4'
2 '2,0' '2,1' '2,2' '2,3' '2,4'
3 '3,0' '3,1' '3,2' '3,3' '3,4'
Erzeuge zuerst ein Array b mit der gewunschten Anzahl von”Platzen“ fur die Zeilen.
Trage dann an jedem Platz von b die entsprechende Zeile ein.
b = [0]*z # Erzeuge Array b mit z Platzen fur die Zeilen.
for zeilennr in range(z): # Gehe durch alle Indizes zeilennr im Array b.
b[zeilennr] = [0]*s # Erzeuge ein Array mit s Platzen als zeilennr-te Zeile von b.
for spaltennr in range(s): # Fulle jeden Eintrag in der zeilennr-ten Zeile von b.
b[zeilennr][spaltennr] = str(zeilennr) + ',' + str(spaltennr)
[['0,0', '0,1', '0,2', '0,3', '0,4'], ['1,0', '1,1', '1,2', '1,3', '1,4'],
['2,0', '2,1', '2,2', '2,3', '2,4'], ['3,0', '3,1', '3,2', '3,3', '3,4']]2d-Arrays erzeugen 1.4.44
Das Modul stdarray.py
Zu den Modulen zum Buch gehort das Modul stdarray.py.
Es enthalt Funktionen zum Erzeugen von Arrays.
stdarray.create1D(n, val) Array der Lange n, jedes Element hat Wert valstdarray.create2D(n, m, val) n-mal-m Array, jedes Element hat Wert val
Modul stdarray.py 1.4.45
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [
]
zu 0 zu 1 zu 2 zu 3 zu 4von 0
0.1
0.35
0.05
0.2
Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [
]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2
0.1
0.35
0.05
0.2
Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2
0.1
0.35
0.05
0.2
Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2von 1 0.3 0.05 0.1 0.2 0.35
0.1
0.35
0.05
0.2
Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
[ 0.3, 0.05, 0.1, 0.2, 0.35],
]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2von 1 0.3 0.05 0.1 0.2 0.35
0.1
0.35
0.05
0.2
Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
[ 0.3, 0.05, 0.1, 0.2, 0.35],
]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2von 1 0.3 0.05 0.1 0.2 0.35von 2 0.2 0.2 0.2 0.2 0.2
0.1
0.35
0.05
0.2
Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
[ 0.3, 0.05, 0.1, 0.2, 0.35],
[ 0.2, 0.2, 0.2, 0.2, 0.2 ],
]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2von 1 0.3 0.05 0.1 0.2 0.35von 2 0.2 0.2 0.2 0.2 0.2
0.1
0.35
0.05
0.2
Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
[ 0.3, 0.05, 0.1, 0.2, 0.35],
[ 0.2, 0.2, 0.2, 0.2, 0.2 ],
]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2von 1 0.3 0.05 0.1 0.2 0.35von 2 0.2 0.2 0.2 0.2 0.2von 3 0.15 0.25 0.2 0.3 0.1
0.1
0.35
0.05
0.2
Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
[ 0.3, 0.05, 0.1, 0.2, 0.35],
[ 0.2, 0.2, 0.2, 0.2, 0.2 ],
[ 0.15, 0.25, 0.2, 0.3, 0.1 ],
]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2von 1 0.3 0.05 0.1 0.2 0.35von 2 0.2 0.2 0.2 0.2 0.2von 3 0.15 0.25 0.2 0.3 0.1
0.1
0.35
0.05
0.2
Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
[ 0.3, 0.05, 0.1, 0.2, 0.35],
[ 0.2, 0.2, 0.2, 0.2, 0.2 ],
[ 0.15, 0.25, 0.2, 0.3, 0.1 ],
]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2von 1 0.3 0.05 0.1 0.2 0.35von 2 0.2 0.2 0.2 0.2 0.2von 3 0.15 0.25 0.2 0.3 0.1von 4 0.1 0.3 0.05 0.1 0.45
0.1
0.35
0.05
0.2
Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
[ 0.3, 0.05, 0.1, 0.2, 0.35],
[ 0.2, 0.2, 0.2, 0.2, 0.2 ],
[ 0.15, 0.25, 0.2, 0.3, 0.1 ],
[ 0.1, 0.3, 0.05, 0.1, 0.45] ]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2von 1 0.3 0.05 0.1 0.2 0.35von 2 0.2 0.2 0.2 0.2 0.2von 3 0.15 0.25 0.2 0.3 0.1von 4 0.1 0.3 0.05 0.1 0.45
0.1
0.35
0.05
0.2
Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
[ 0.3, 0.05, 0.1, 0.2, 0.35],
[ 0.2, 0.2, 0.2, 0.2, 0.2 ],
[ 0.15, 0.25, 0.2, 0.3, 0.1 ],
[ 0.1, 0.3, 0.05, 0.1, 0.45] ]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2von 1 0.3 0.05 0.1 0.2 0.35von 2 0.2 0.2 0.2 0.2 0.2von 3 0.15 0.25 0.2 0.3 0.1von 4 0.1 0.3 0.05 0.1 0.45
0.1
0.35
0.05
0.2
Die Wahrscheinlichkeit, dass das Frisbee den Weg 0 – 1 – 4 – 2 – 1 geworfen wird,
ist 0.1 ¨ 0.35 ¨ 0.05 ¨ 0.2 “ 0.00035.Frisbee 1.4.46
Frisbee
5 Kinder werfen sich ein Frisbee zu.Die
”Zielwahrscheinlichkeiten“ sind in der Grafik angegeben und werden in das Array m eingetragen.
0
1
2
3
4
0.1
0.3
0.3
0.2
0.1
0.050.1
0.2
0.35
0.3
0.2
0.2
0.2
0.2
0.2
0.3
0.25
0.2
0.1
0.15
0.45
0.3
0.05
0.10.1
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
[ 0.3, 0.05, 0.1, 0.2, 0.35],
[ 0.2, 0.2, 0.2, 0.2, 0.2 ],
[ 0.15, 0.25, 0.2, 0.3, 0.1 ],
[ 0.1, 0.3, 0.05, 0.1, 0.45] ]
zu 0 zu 1 zu 2 zu 3 zu 4von 0 0.1 0.1 0.3 0.3 0.2von 1 0.3 0.05 0.1 0.2 0.35von 2 0.2 0.2 0.2 0.2 0.2von 3 0.15 0.25 0.2 0.3 0.1von 4 0.1 0.3 0.05 0.1 0.45
0.1
0.35
0.05
0.2
Mit welcher Wahrscheinlichkeit landet das Frisbee mit Start 0 nach 4 Wurfen bei 1?
Frisbee 1.4.46
Frisbee-Problem: die Berechnung der Wahrscheinlichkeiten fur n Wurfe
Wir haben das 2d-Array m mit den Wahrscheinlichkeiten m[z][s],
dass das Frisbee von Spieler z mit einem Wurf zu Spieler s kommt.
Wir wollen ein 2d-Array e mit den Wahrscheinlichkeiten e[z][s] berechnen,
dass das Frisbee von Spieler z mit n Wurfen zu Spieler s kommt.
Zum Beispiel:
Start:Das 2d-Array m mit
”m[z][s] ist die Wkeit, dass
das Frisbee von z mit einem Wurf zu s kommt“.
[ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
[ 0.3, 0.05, 0.1, 0.2, 0.35],
[ 0.2, 0.2, 0.2, 0.2, 0.2 ],
[ 0.15, 0.25, 0.2, 0.3, 0.1 ],
[ 0.1, 0.3, 0.05, 0.1, 0.45] ]
Ziel:Das 2d-Array e mit
”e[z][s] ist die Wkeit, dass
das Frisbee von z mit vier Wurfen zu s kommt“.
[ [ 0.1648, 0.1926, 0.1581, 0.2116, 0.2735 ],
[ 0.1651, 0.1921, 0.1577, 0.2098, 0.2780 ],
[ 0.1642, 0.1923, 0.1566, 0.2112, 0.2751 ],
[ 0.1625, 0.1929, 0.1582, 0.2156, 0.2718 ],
[ 0.1630, 0.1943, 0.1513, 0.2060, 0.2841 ] ]
Das Frisbee-Problem 1.4.47
Wir werden drei Losungen fur das Problem betrachten.
§ exakte Losung mit einem”brute force“-Algorithmus,
der durch alle moglichen Wurffolgen geht und deren Wahrscheinlichkeiten aufsummiert
(bei 5 Spielern und Wurffolgen aus 16 Wurfen braucht der Algorithmus 16 ¨ 517 (« 12 Milliarden)
Multiplikationen)
die Losung ist exakt, aber ihre Berechnung dauert sehr lange
§ Losung mittels Simulation der Wurffolgen der Spieler
(die Rechenzeit hangt von der erwunschten Exaktheit ab,
ist aber recht lang fur einigermaßen exakte Ergebnisse)
die Losung ist nicht exakt, aber die Berechnung kann recht schnell gehen
§ exakte Losung mittels”Dynamischem Programmieren“
dabei wird vermieden, mehrfach vorkommende Teil-Wurffolgen wiederholt zu berechnen
(bei 5 Spielern und Wurffolgen aus 16 Wurfen braucht der Algorithmus 4 ¨ 53 (=500) Multiplikationen)
die Losung ist exakt (bis auf Rundungsfehler . . . ) und schnell
Das Frisbee-Problem 1.4.48
Exakte Berechnung des Frisbee-Problems”
brute force“
Wir haben das 2d-Array m mit den Wahrscheinlichkeiten m[z][s],
dass das Frisbee von Spieler z mit einem Wurf zu Spieler s kommt.
Wir wollen ein 2d-Array e mit den Wahrscheinlichkeiten e[z][s] berechnen,
dass das Frisbee von Spieler z mit n Wurfen zu Spieler s kommt.
Zum Beispiel:
Start:Das 2d-Array m mit
”m[z][s] ist die Wkeit, dass
das Frisbee von z mit einem Wurf zu s kommt“.
[ [ 0.1, 0.1, 0.3, 0.3, 0.2 ],
[ 0.3, 0.05, 0.1, 0.2, 0.35],
[ 0.2, 0.2, 0.2, 0.2, 0.2 ],
[ 0.15, 0.25, 0.2, 0.3, 0.1 ],
[ 0.1, 0.3, 0.05, 0.1, 0.45] ]
Ziel:Das 2d-Array e mit
”e[z][s] ist die Wkeit, dass
das Frisbee von z mit vier Wurfen zu s kommt“.
[ [ 0.1648, 0.1926, 0.1581, 0.2116, 0.2735 ],
[ 0.1651, 0.1921, 0.1577, 0.2098, 0.2780 ],
[ 0.1642, 0.1923, 0.1566, 0.2112, 0.2751 ],
[ 0.1625, 0.1929, 0.1582, 0.2156, 0.2718 ],
[ 0.1630, 0.1943, 0.1513, 0.2060, 0.2841 ] ]
Frisbee”
brute force“ 1.4.49
Um e zu berechnen, schauen wir uns alle moglichen Folgen aus n Wurfen an.
Beispiel: Fur n “ 5 ist 2–4–2–3–1–4 ein mogliche Wurffolge aus 5 Wurfen
(2 wirft zu 4, 4 wirft zu 2, 2 wirft zu 3, 3 wirft zu 1, und 1 wirft zu 4).
Die Wahrscheinlichkeit dieser Wurffolge ist
das Produkt aus den Wahrscheinlichkeiten der einzelnen Wurfe:
Wurf 2–4 4–2 2–3 3–1 1–4
Wkeit 0.2 0.05 0.2 0.15 0.35
Das Produkt der Wkeiten ist 0.2 ¨ 0.05 ¨ 0.2 ¨ 0.15 ¨ 0.35 “ 0.000105.
Am Anfang haben alle Eintrage e[z][s] in e den Wert 0.
Fur jede mogliche Wurffolge x– . . . –y
wird ihre Wahrscheinlichkeit zu e[x][y] hinzuaddiert (im Beispiel zu e[2][4]).
Dadurch hat man nach Durchlaufen aller Wurffolgen in e die exakten Wahrscheinlichkeiten
e[z][s], dass das Frisbee von z nach n Wurfen bei s landet.Frisbee
”brute force“ 1.4.50
Wie durchlauft man alle Wurffolgen einer festen Lange?
Analog zu: wie durchlauft man alle n-stelligen Dezimalzahlen/Folgen von Ziffern?
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 2
......
1 1 1 1 1 9 9 9
1 1 1 1 1 9 9 0
1 1 1 1 1 9 0 0
1 1 1 1 1 0 0 0
1 1 1 1 2 0 0 0
1 1 1 1 2 0 0 0
......
9 9 9 9 9 9 9 9
beginne mit der”kleinsten“ Wurffolge
Frisbee”
brute force“ 1.4.51
Wie durchlauft man alle Wurffolgen einer festen Lange?
Analog zu: wie durchlauft man alle n-stelligen Dezimalzahlen/Folgen von Ziffern?
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 2...
...
1 1 1 1 1 9 9 9
1 1 1 1 1 9 9 0
1 1 1 1 1 9 0 0
1 1 1 1 1 0 0 0
1 1 1 1 2 0 0 0
1 1 1 1 2 0 0 0
......
9 9 9 9 9 9 9 9
beginne mit der”kleinsten“ Wurffolge
zahle an der letzten Stelle 1 dazu, falls sie ă 9 ist
Frisbee”
brute force“ 1.4.51
Wie durchlauft man alle Wurffolgen einer festen Lange?
Analog zu: wie durchlauft man alle n-stelligen Dezimalzahlen/Folgen von Ziffern?
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 2...
...
1 1 1 1 1 9 9 9
1 1 1 1 1 9 9 0
1 1 1 1 1 9 0 0
1 1 1 1 1 0 0 0
1 1 1 1 2 0 0 0
1 1 1 1 2 0 0 0
......
9 9 9 9 9 9 9 9
beginne mit der”kleinsten“ Wurffolge
zahle an der letzten Stelle 1 dazu, falls sie ă 9 ist
sonst:
gehe von rechts nach links,
bis die erste Stelle ă 9 gefunden wurde;
ersetze dabei jede 9 durch eine 0;
zahle an der ersten Stelle ă 9 nun 1 dazu;
das ist die nachste Wurffolge
Frisbee”
brute force“ 1.4.51
Wie durchlauft man alle Wurffolgen einer festen Lange?
Analog zu: wie durchlauft man alle n-stelligen Dezimalzahlen/Folgen von Ziffern?
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 2...
...
1 1 1 1 1 9 9 9
1 1 1 1 1 9 9 0
1 1 1 1 1 9 0 0
1 1 1 1 1 0 0 0
1 1 1 1 2 0 0 0
1 1 1 1 2 0 0 0
......
9 9 9 9 9 9 9 9
beginne mit der”kleinsten“ Wurffolge
zahle an der letzten Stelle 1 dazu, falls sie ă 9 ist
sonst:
gehe von rechts nach links,
bis die erste Stelle ă 9 gefunden wurde;
ersetze dabei jede 9 durch eine 0;
zahle an der ersten Stelle ă 9 nun 1 dazu;
das ist die nachste Wurffolge
Frisbee”
brute force“ 1.4.51
Wie durchlauft man alle Wurffolgen einer festen Lange?
Analog zu: wie durchlauft man alle n-stelligen Dezimalzahlen/Folgen von Ziffern?
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 2...
...
1 1 1 1 1 9 9 9
1 1 1 1 1 9 9 0
1 1 1 1 1 9 0 0
1 1 1 1 1 0 0 0
1 1 1 1 2 0 0 0
1 1 1 1 2 0 0 0
......
9 9 9 9 9 9 9 9
beginne mit der”kleinsten“ Wurffolge
zahle an der letzten Stelle 1 dazu, falls sie ă 9 ist
sonst:
gehe von rechts nach links,
bis die erste Stelle ă 9 gefunden wurde;
ersetze dabei jede 9 durch eine 0;
zahle an der ersten Stelle ă 9 nun 1 dazu;
das ist die nachste Wurffolge
Frisbee”
brute force“ 1.4.51
Wie durchlauft man alle Wurffolgen einer festen Lange?
Analog zu: wie durchlauft man alle n-stelligen Dezimalzahlen/Folgen von Ziffern?
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 2...
...
1 1 1 1 1 9 9 9
1 1 1 1 1 9 9 0
1 1 1 1 1 9 0 0
1 1 1 1 1 0 0 0
1 1 1 1 2 0 0 0
1 1 1 1 2 0 0 0
......
9 9 9 9 9 9 9 9
beginne mit der”kleinsten“ Wurffolge
zahle an der letzten Stelle 1 dazu, falls sie ă 9 ist
sonst:
gehe von rechts nach links,
bis die erste Stelle ă 9 gefunden wurde;
ersetze dabei jede 9 durch eine 0;
zahle an der ersten Stelle ă 9 nun 1 dazu;
das ist die nachste Wurffolge
Frisbee”
brute force“ 1.4.51
Wie durchlauft man alle Wurffolgen einer festen Lange?
Analog zu: wie durchlauft man alle n-stelligen Dezimalzahlen/Folgen von Ziffern?
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 2...
...
1 1 1 1 1 9 9 9
1 1 1 1 1 9 9 0
1 1 1 1 1 9 0 0
1 1 1 1 1 0 0 0
1 1 1 1 2 0 0 0
1 1 1 1 2 0 0 0
......
9 9 9 9 9 9 9 9
beginne mit der”kleinsten“ Wurffolge
zahle an der letzten Stelle 1 dazu, falls sie ă 9 ist
sonst:
gehe von rechts nach links,
bis die erste Stelle ă 9 gefunden wurde;
ersetze dabei jede 9 durch eine 0;
zahle an der ersten Stelle ă 9 nun 1 dazu;
das ist die nachste Wurffolge
Frisbee”
brute force“ 1.4.51
Wie durchlauft man alle Wurffolgen einer festen Lange?
Analog zu: wie durchlauft man alle n-stelligen Dezimalzahlen/Folgen von Ziffern?
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 2...
...
1 1 1 1 1 9 9 9
1 1 1 1 1 9 9 0
1 1 1 1 1 9 0 0
1 1 1 1 1 0 0 0
1 1 1 1 2 0 0 0
1 1 1 1 2 0 0 0...
...
9 9 9 9 9 9 9 9
beginne mit der”kleinsten“ Wurffolge
zahle an der letzten Stelle 1 dazu, falls sie ă 9 ist
sonst:
gehe von rechts nach links,
bis die erste Stelle ă 9 gefunden wurde;
ersetze dabei jede 9 durch eine 0;
zahle an der ersten Stelle ă 9 nun 1 dazu;
das ist die nachste Wurffolge
Frisbee”
brute force“ 1.4.51
# wurffolgen.py
#----------------------------------------------------------------------------------------
# Lies n und c (beides int) von der Kommandozeile.
# Erzeuge der Reihe nach alle Wurffolgen (Array) mit n Wurfen und Spielern 0...c.
#----------------------------------------------------------------------------------------
import sys
# Lies n und c (int) von der Kommandozeile ein.
n = int(sys.argv[1])
c = int(sys.argv[2])
# Erzeuge die "kleinste" Wurffolge k nur aus 0en, und gib sie aus.
k = [0]*(n+1)
print(k)
# Solange nicht die "großte" Wurffolge erreicht wurde, erzeuge die nachste.
while min(k)<c:
for i in range(len(k)-1,-1,-1):
# Falls an Stelle i "ohne Ubertrag" 1 hinzuaddiert werden kann,
# dann mache das und verlasse die for-Schleife.
if k[i]<c:
k[i] += 1
break
# sonst: ersetze die Stelle durch 0 und gehe in der for-Schleife weiter nach links.
else: k[i] = 0
# Gib die Wurffolge aus.
print(k)Frisbee
”brute force“ 1.4.52
$ python3 wurffolgen.py 2 2
[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 1, 0]
[0, 1, 1]
[0, 1, 2]
[0, 2, 0]
[0, 2, 1]
[0, 2, 2]
[1, 0, 0]
[1, 0, 1]
[1, 0, 2]
[1, 1, 0]
[1, 1, 1]
[1, 1, 2]
[1, 2, 0]
[1, 2, 1]
[1, 2, 2]
[2, 0, 0]
[2, 0, 1]
[2, 0, 2]
[2, 1, 0]
[2, 1, 1]
[2, 1, 2]
[2, 2, 0]
[2, 2, 1]
[2, 2, 2]
$ python3 wurffolgen.py 4 1
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 1]
[0, 0, 0, 1, 0]
[0, 0, 0, 1, 1]
[0, 0, 1, 0, 0]
[0, 0, 1, 0, 1]
[0, 0, 1, 1, 0]
[0, 0, 1, 1, 1]
[0, 1, 0, 0, 0]
[0, 1, 0, 0, 1]
[0, 1, 0, 1, 0]
[0, 1, 0, 1, 1]
[0, 1, 1, 0, 0]
[0, 1, 1, 0, 1]
[0, 1, 1, 1, 0]
[0, 1, 1, 1, 1]
[1, 0, 0, 0, 0]
[1, 0, 0, 0, 1]
...
[1, 1, 0, 0, 1]
[1, 1, 0, 1, 0]
[1, 1, 0, 1, 1]
[1, 1, 1, 0, 0]
[1, 1, 1, 0, 1]
[1, 1, 1, 1, 0]
[1, 1, 1, 1, 1]
Frisbee”
brute force“ 1.4.53
# frisbee-bruteforce.py
#-------------------------------------------------------------------------------------------------------------
import sys
# Die Lange der Wurffolge n (int) wird von der Kommandozeile eingelesen.
n = int(sys.argv[1])
# m ist das 2d-Array mit den Wahrscheinlichkeiten m[z][s], dass Spieler z zu Spieler s wirft.
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ], [ 0.3, 0.05,0.1, 0.2, 0.35], [ 0.2, 0.2, 0.2, 0.2, 0.2 ],
[0.15, 0.25,0.3, 0.3, 0.0 ], [ 0.1, 0.3,0.05, 0.1, 0.45] ]
# e ist das 2d-Array der gleichen Große wie m, bei der am Ende in e[z][s] die Wahrscheinlichkeit steht,
# dass von Spieler z nach n Wurfen das Frisbee bei Spieler s landet. Am Anfang sind alle Eintrage 0.
e = [0]*len(m)
for i in range(len(e)): e[i] = [0]*len(m)
# Es werden systematisch alle Wurffolgen betrachtet, die das Frisbee mit n Wurfen durchlaufen kann.
# Die erste Wurffolge besteht nur aus 0en, und die Wahrscheinlichkeit fur sie wird in e[0][0] eingetragen.
k = [0]*(n+1)
e[0][0] = m[0][0]**n
while min(k)<len(m)-1: # solange nicht die "großte" Wurffolge [4,4,4,4,4] durchlaufen wurde
for j in range(len(k)-1,-1,-1): # erzeuge die nachste Wurffolge
if k[j]<len(m)-1:
k[j] += 1
break
else: k[j] = 0
produkt = 1.0 # berechne die Wahrscheinlichkeit der Wurffolge
for i in range(len(k)-1):
produkt *= m[k[i]][k[i+1]]
e[k[0]][k[-1]] += produkt # addiere die Wkeit an der richtigen Stelle zu e hinzu
Frisbee”
brute force“ 1.4.54
#----- Die Ausgabe des Ergebnisses.
# Es wird ausgegeben, mit welcher Wkeit das Frisbee bei welchem Spieler landet.
# Dazu wird das berechnete 2d-Array e schon ausgegeben.
print('''
Die Wahrscheinlichkeiten, dass das Frisbee mit %d Wurfen von x zu y kommt,
sind wie folgt:
''' % 2**n)
# Die erste Zeile der Ausgabe mit den Namen der Spalten.
print(' '*8 + '|', end='')
for i in range(len(e)): print(' zu %2d |' % i, end='')
print()
# Die zweite Zeile der Ausgabe: ein langer Strich.
print('-'*11*(len(e)+1))
# Das Array e wird zeilenweise ausgegeben.
for z in range(len(e)):
# Der Name der Zeile.
print(' von %2d |' % z, end='')
# Die Wahrscheinlichkeiten in den Spalten der Zeile.
for s in range(len(e[z])):
print( ' %.6f |' % e[z][s], end='')
print()
print()
#----------------------------------------------------------------------------------------------
Frisbee”
brute force“ 1.4.55
$ python3 frisbee-bruteforce.py 1
Die Wahrscheinlichkeiten, dass das Frisbee mit 1 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.100000 | 0.100000 | 0.300000 | 0.300000 | 0.200000 |
von 1 | 0.300000 | 0.050000 | 0.100000 | 0.200000 | 0.350000 |
von 2 | 0.200000 | 0.200000 | 0.200000 | 0.200000 | 0.200000 |
von 3 | 0.150000 | 0.250000 | 0.300000 | 0.300000 | 0.000000 |
von 4 | 0.100000 | 0.300000 | 0.050000 | 0.100000 | 0.450000 |
Frisbee”
brute force“ 1.4.56
$ python3 frisbee-bruteforce.py 1
Die Wahrscheinlichkeiten, dass das Frisbee mit 1 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.100000 | 0.100000 | 0.300000 | 0.300000 | 0.200000 |
von 1 | 0.300000 | 0.050000 | 0.100000 | 0.200000 | 0.350000 |
von 2 | 0.200000 | 0.200000 | 0.200000 | 0.200000 | 0.200000 |
von 3 | 0.150000 | 0.250000 | 0.300000 | 0.300000 | 0.000000 |
von 4 | 0.100000 | 0.300000 | 0.050000 | 0.100000 | 0.450000 |
$ python3 frisbee-bruteforce.py 4
Die Wahrscheinlichkeiten, dass das Frisbee mit 4 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.166275 | 0.189950 | 0.184938 | 0.215225 | 0.243613 |
von 1 | 0.166425 | 0.189669 | 0.181056 | 0.212862 | 0.249988 |
von 2 | 0.167450 | 0.189800 | 0.182550 | 0.213800 | 0.246400 |
von 3 | 0.168650 | 0.188694 | 0.187725 | 0.217325 | 0.237606 |
von 4 | 0.165725 | 0.192463 | 0.174656 | 0.208213 | 0.258944 |Frisbee
”brute force“ 1.4.56
$ python3 frisbee-bruteforce.py 4
Die Wahrscheinlichkeiten, dass das Frisbee mit 4 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.166275 | 0.189950 | 0.184938 | 0.215225 | 0.243613 |
von 1 | 0.166425 | 0.189669 | 0.181056 | 0.212862 | 0.249988 |
von 2 | 0.167450 | 0.189800 | 0.182550 | 0.213800 | 0.246400 |
von 3 | 0.168650 | 0.188694 | 0.187725 | 0.217325 | 0.237606 |
von 4 | 0.165725 | 0.192463 | 0.174656 | 0.208213 | 0.258944 |
$ python3 frisbee-bruteforce.py 8
Die Wahrscheinlichkeiten, dass das Frisbee mit 8 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.166898 | 0.190211 | 0.181854 | 0.213256 | 0.247781 |
von 1 | 0.166884 | 0.190230 | 0.181792 | 0.213213 | 0.247880 |
von 2 | 0.166890 | 0.190220 | 0.181828 | 0.213238 | 0.247825 |
von 3 | 0.166909 | 0.190193 | 0.181920 | 0.213302 | 0.247676 |
von 4 | 0.166861 | 0.190259 | 0.181692 | 0.213143 | 0.248046 |Frisbee
”brute force“ 1.4.56
$ python3 frisbee-bruteforce.py 8
Die Wahrscheinlichkeiten, dass das Frisbee mit 8 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.166898 | 0.190211 | 0.181854 | 0.213256 | 0.247781 |
von 1 | 0.166884 | 0.190230 | 0.181792 | 0.213213 | 0.247880 |
von 2 | 0.166890 | 0.190220 | 0.181828 | 0.213238 | 0.247825 |
von 3 | 0.166909 | 0.190193 | 0.181920 | 0.213302 | 0.247676 |
von 4 | 0.166861 | 0.190259 | 0.181692 | 0.213143 | 0.248046 |
Man sieht, dass die Wahrscheinlichkeiten in einer Spalte sich immer ahnlicher werden.Man weiß auch
”mathematisch“, dass diese Werte fur
”unendliche“ Wurffolgen gleich werden.
Wenn man nur an diesen Grenzwerten interessiert ist,wurde es auch reichen, nur die erste Zeile des Arrays auszurechnen.
Dafur braucht man dann nur 15 der Zeit, die man fur das ganze Array braucht.
Das ist aber auch noch sehr lang.
Frisbee”
brute force“ 1.4.56
Der Aufruf
python3 frisbee-bruteforce.py 16
dauert bereits sehr lange.
Bei 5 Spielern mussen 517 “ 762939453125 (726 Milliarden) Wurffolgen durchlaufen
und etwa 16 ¨ 517 “ 12207031250000 (12 Billionen) Multiplikationen gemacht werden.
Das dauert . . .
Frisbee”
brute force“ 1.4.57
Approximative Berechnung des Frisbee-Problems mittels Simulation
Jetzt wollen wir die erste Zeile der Matrix e experimentell bestimmen.Dazu schreiben wir ein Programm, das das Experiment
”Ein Frisbee wird beginnend mit Spieler 0 n-mal geworfen. Bei welchem Mitspieler landet es?“
sehr oft wiederholt (Experimentreihe) und zahlt, wie oft das Frisbee bei welchem Mitspieler landet.
In jedem Experiment wird also zufallig eine Wurffolge gewahlt.Die Anzahl der Wiederholungen des Experiments wird kleiner sein als die Anzahl aller Wurffolgen.Dadurch lauft das Programm schneller als frisbee-bruteforce.py,
liefert aber kein exaktes Ergebnis sondern nur eine naherungsweise exakte Losung(Approximation).
Damit das Ergebnis nicht”zu schlecht“ wird, werden die Wurffolgen so gewahlt,
dass Wurffolgen mit hoher Wahrscheinlichkeit eher gewahlt werden als solche mit geringerWahrscheinlichkeit.
Das erreichen wir, indem die einzelnen Wurfe mit ihren Wahrscheinlichkeiten simuliert werden.
Frisbee-Simulation 1.4.58
Die”wichtigen“ Daten, die das Programms verarbeitet:
(1) die Wurfwahrscheinlichkeiten der Mitspieler stehen in einem 2d-Array m
(2) fur jeden Mitspieler i wird in ende[i] gezahlt, wie oft das Frisbee am Ende bei ihm landet(das entspricht der ersten Zeile des Arrays e in frisbee-bruteforce.py).
Der Ablauf eines Experiments und seine Auswertung:
das Frisbee liegt bei Spieler p=0wiederhole n-mal:
lasse p das Frisbee werfenes landet mit den in m[p] gegebenen Wahrscheinlichkeiten bei einem Spieler ip=i
ende[p] += 1
Frisbee-Simulation 1.4.59
Wie simuliert man einen zufalligen Wurf?
Beispiel: zu 0 zu 1 zu 2 zu 3 zu 4
mit Wahrscheinlichkeit
0 wirft 0.1 0.1 0.3 0.3 0.2
”Zeichne“ die Wahrscheinlichkeiten hintereinander auf dem Zahlenstrahl von 0 bis 1.
0.0 1.00.1 0.2 0.5 0.8
0.1 0.1 0.3 0.3 0.2
Jedem Abschnitt ist ein Ziel des Wurfes zugeordnet.
Idee zur Simulation eines Wurfs von p:
ziehe eine Zufallszahl z aus r0, 1q
bestimme
dann wirft p zu iFrisbee-Simulation 1.4.60
Wie simuliert man einen zufalligen Wurf?
Beispiel: zu 0 zu 1 zu 2 zu 3 zu 4
mit Wahrscheinlichkeit
0 wirft 0.1 0.1 0.3 0.3 0.2
”Zeichne“ die Wahrscheinlichkeiten hintereinander auf dem Zahlenstrahl von 0 bis 1.
0.0 1.00.1 0.2 0.5 0.8
0.1 0.1 0.3 0.3 0.2
Jedem Abschnitt ist ein Ziel des Wurfes zugeordnet.
Idee zur Simulation eines Wurfs von p:
ziehe eine Zufallszahl z aus r0, 1q
bestimme
dann wirft p zu iFrisbee-Simulation 1.4.60
Wie simuliert man einen zufalligen Wurf?
Beispiel: zu 0 zu 1 zu 2 zu 3 zu 4
mit Wahrscheinlichkeit
0 wirft 0.1 0.1 0.3 0.3 0.2
”Zeichne“ die Wahrscheinlichkeiten hintereinander auf dem Zahlenstrahl von 0 bis 1.
0.0 1.00.1 0.2 0.5 0.8
0.1 0.1 0.3 0.3 0.2
Jedem Abschnitt ist ein Ziel des Wurfes zugeordnet.
Idee zur Simulation eines Wurfs von p:
ziehe eine Zufallszahl z aus r0, 1q
bestimme
dann wirft p zu iFrisbee-Simulation 1.4.60
Wie simuliert man einen zufalligen Wurf?
Beispiel: zu 0 zu 1 zu 2 zu 3 zu 4
mit Wahrscheinlichkeit
0 wirft 0.1 0.1 0.3 0.3 0.2
”Zeichne“ die Wahrscheinlichkeiten hintereinander auf dem Zahlenstrahl von 0 bis 1.
0.0 1.00.1 0.2 0.5 0.8
0.1 0.1 0.3 0.3 0.2
zu 0 zu 1 zu 2 zu 3 zu 4
Jedem Abschnitt ist ein Ziel des Wurfes zugeordnet.
Idee zur Simulation eines Wurfs von p:
ziehe eine Zufallszahl z aus r0, 1q
bestimme
dann wirft p zu iFrisbee-Simulation 1.4.60
Wie simuliert man einen zufalligen Wurf?
Beispiel: zu 0 zu 1 zu 2 zu 3 zu 4
mit Wahrscheinlichkeit
0 wirft 0.1 0.1 0.3 0.3 0.2
”Zeichne“ die Wahrscheinlichkeiten hintereinander auf dem Zahlenstrahl von 0 bis 1.
0.0 1.00.1 0.2 0.5 0.8
0.1 0.1 0.3 0.3 0.2
zu 0 zu 1 zu 2 zu 3 zu 4
Jedem Abschnitt ist ein Ziel des Wurfes zugeordnet.
Idee zur Simulation eines Wurfs von p:
ziehe eine Zufallszahl z aus r0, 1q
bestimme den Abschnitt i, in dem z in obiger Graphik liegt
dann wirft p zu iFrisbee-Simulation 1.4.60
Wie simuliert man einen zufalligen Wurf?
Beispiel: zu 0 zu 1 zu 2 zu 3 zu 4
mit Wahrscheinlichkeit
0 wirft 0.1 0.1 0.3 0.3 0.2
”Zeichne“ die Wahrscheinlichkeiten hintereinander auf dem Zahlenstrahl von 0 bis 1.
0.0 1.00.1 0.2 0.5 0.8
0.1 0.1 0.3 0.3 0.2
zu 0 zu 1 zu 2 zu 3 zu 4
Jedem Abschnitt ist ein Ziel des Wurfes zugeordnet.
Idee zur Simulation eines Wurfs von p:
ziehe eine Zufallszahl z aus r0, 1q
bestimme die kleinste Zahl i mit z < m[p][0] + m[p][1] +...+ m[p][i]loooooooooooooooooooooooomoooooooooooooooooooooooon
dann wirft p zu iFrisbee-Simulation 1.4.60
Wie simuliert man einen zufalligen Wurf?
Beispiel: zu 0 zu 1 zu 2 zu 3 zu 4
mit Wahrscheinlichkeit
0 wirft 0.1 0.1 0.3 0.3 0.2
”Zeichne“ die Wahrscheinlichkeiten hintereinander auf dem Zahlenstrahl von 0 bis 1.
0.0 1.00.1 0.2 0.5 0.8
0.1 0.1 0.3 0.3 0.2
zu 0 zu 1 zu 2 zu 3 zu 4
Jedem Abschnitt ist ein Ziel des Wurfes zugeordnet.
Idee zur Simulation eines Wurfs von p:
ziehe eine Zufallszahl z aus r0, 1q
bestimme die kleinste Zahl i mit z < m[p][0] + m[p][1] +...+ m[p][i]loooooooooooooooooooooooomoooooooooooooooooooooooon
dann wirft p zu i sum(m[p][0:i+1])Frisbee-Simulation 1.4.60
# frisbee-simulation.py
#-----------------------------------------------------------------------------------------------------------------------
import sys, random
# ----- Die Experimentreihe wird vorbereitet. -----
n = int(sys.argv[1]) # Das Frisbee wird n-mal geworfen.
runden = int(sys.argv[2]) # Das Experiment wird runden-mal wiederholt.
# m ist die Matrix mit den Wahrscheinlichkeiten m[z][s], dass Spieler z zu Spieler s wirft.
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ], # Spieler 0 wirft mit Wkeit 0.1 zu Spieler 0 und 1,
[ 0.3, 0.05,0.1, 0.2, 0.35], # mit Wkeit 0.2 zu 2 und 3, und mit Wkeit 0.2 zu 4
[ 0.2, 0.2, 0.2, 0.2, 0.2 ],
[0.15, 0.25,0.2, 0.3, 0.1 ],
[ 0.1, 0.3,0.05, 0.1, 0.45] ]
ende = [0]*len(m) # In ende[i] wird gezahlt, wie oft das Frisbee nach n Wurfen bei Spieler i landet.
# ----- Das Experimentreihe wird durchgefuhrt. Sie besteht aus runden vielen Experimenten. -----
for q in range(runden): # In jeder Runde wird das Frisbee n-mal geworfen und es wird nachgesehen, wo es am Ende landet.
p = 0 # Das Frisbee startet bei Spieler p=0.
for w in range(n): # Das Frisbee wird n-mal geworfen.
z = random.random() # Es wird eine Zufallszahl z aus 0..1 gezogen.
# Finde das kleinste i mit z < m[p][0] + m[p][1] +...+ m[p][i]
i = 0
while z>=sum(m[p][0:i+1]):
i += 1
# i ist nun die Nummer des Spielers, zu dem geworfen wird.
p = i
# Das Experiment wird ausgewertet.
ende[p] += 1 # Nach n Wurfen ist das Frisbee bei Spieler p gelandet.Frisbee-Simulation 1.4.61
# ----- Das Ergebnis der Experimentreihe wird ausgegeben. -----
#----- Die Ausgabe des Ergebnisses.
# Es wird ausgegeben, mit welcher Wkeit das Frisbee bei welchem Spieler landet.
# Dazu wird das berechnete Array ende schon ausgegeben.
print('Im Experiment kommt das Frisbee mit %d Wurfen von 0 zu y mit folgenden Wahrscheinlichkeiten:' % n)
# Die erste Zeile der Ausgabe enthalt die Namen der Spalten.
print(' '*8 + '|', end='')
for i in range(len(ende)): print(' zu %2d |' % i, end='')
print()
# Die zweite Zeile der Ausgabe ist ein langer Strich.
print('-'*11*(len(ende)+1))
# Das Array ende wird in der nachsten Zeile ausgegeben.
# Die erste Spalte der Zeile ist der Name der Zeile.
print(' von %2d |' % z, end='')
# Danach kommen die Spalten mit den Wahrscheinlichkeiten aus ende.
for s in range(len(ende)):
print( ' %.6f |' % (ende[s]/runden), end='')
print('\n\n')
#----------------------------------------------------------------------------------------------
Frisbee-Simulation 1.4.62
Bei einem Wurf mussten die Ergebnisse der ersten Zeile der Matrix m entsprechen.
$ python3 frisbee-simulation.py 1 100000
Im Experiment kommt das Frisbee mit 1 Wurfen von 0 zu y mit folgenden Wahrscheinlichkeiten:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.100760 | 0.099420 | 0.302050 | 0.297050 | 0.200720 |
Frisbee-Simulation 1.4.63
Wir vergleichen die Ergebnisse der Simulation mit den exakten Ergebnissen:(2 Wurfe ergeben 52 Wurffolgen beginnend bei 0.)
$ python3 frisbee-simulation.py 2 100000
Im Experiment kommt das Frisbee mit 2 Wurfen von 0 zu y mit folgenden Wahrscheinlichkeiten:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.165280 | 0.209900 | 0.170950 | 0.218700 | 0.235170 |
$ python3 frisbee-bruteforce.py 2
Die Wahrscheinlichkeiten, dass das Frisbee mit 2 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.165000 | 0.210000 | 0.170000 | 0.220000 | 0.235000 |
von 1 | 0.130000 | 0.207500 | 0.172500 | 0.215000 | 0.275000 |
von 2 | 0.170000 | 0.180000 | 0.170000 | 0.220000 | 0.260000 |
von 3 | 0.185000 | 0.172500 | 0.175000 | 0.235000 | 0.232500 |
von 4 | 0.170000 | 0.195000 | 0.112500 | 0.175000 | 0.347500 |
Frisbee-Simulation 1.4.63
Wir vergleichen die Ergebnisse der Simulation mit den exakten Ergebnissen:(4 Wurfe ergeben 54
“ 625 Wurffolgen beginnend bei 0.)
$ python3 frisbee-simulation.py 4 100000
Im Experiment kommt das Frisbee mit 4 Wurfen von 0 zu y mit folgenden Wahrscheinlichkeiten:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.164750 | 0.193560 | 0.157380 | 0.210980 | 0.273330 |
$ python3 frisbee-bruteforce.py 4
Die Wahrscheinlichkeiten, dass das Frisbee mit 4 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.164075 | 0.192600 | 0.158113 | 0.211675 | 0.273538 |
von 1 | 0.164275 | 0.192119 | 0.155781 | 0.209813 | 0.278012 |
von 2 | 0.165250 | 0.192300 | 0.156600 | 0.210700 | 0.275150 |
von 3 | 0.165700 | 0.192019 | 0.158238 | 0.212200 | 0.271844 |
von 4 | 0.163975 | 0.194363 | 0.151381 | 0.206013 | 0.284269 |
Frisbee-Simulation 1.4.63
Wir vergleichen die Ergebnisse der Simulation mit den exakten Ergebnissen:(8 Wurfe ergeben 58
“ 390625 Wurffolgen beginnend bei 0.)
$ python3 frisbee-simulation.py 8 100000
Im Experiment kommt das Frisbee mit 8 Wurfen von 0 zu y mit folgenden Wahrscheinlichkeiten:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.166090 | 0.192200 | 0.154910 | 0.207010 | 0.279790 |
$ python3 frisbee-bruteforce.py 8
Die Wahrscheinlichkeiten, dass das Frisbee mit 8 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.164616 | 0.192819 | 0.155610 | 0.209724 | 0.277231 |
von 1 | 0.164610 | 0.192829 | 0.155584 | 0.209701 | 0.277276 |
von 2 | 0.164612 | 0.192823 | 0.155602 | 0.209717 | 0.277246 |
von 3 | 0.164617 | 0.192816 | 0.155622 | 0.209735 | 0.277210 |
von 4 | 0.164598 | 0.192842 | 0.155543 | 0.209664 | 0.277353 |
Frisbee-Simulation 1.4.63
Wir vergleichen die Ergebnisse der Simulation mit den exakten Ergebnissen:(10 Wurfe ergeben 510
“ 9765625 Wurffolgen beginnend bei 0.)
$ python3 frisbee-simulation.py 10 100000
Im Experiment kommt das Frisbee mit 10 Wurfen von 0 zu y mit folgenden Wahrscheinlichkeiten:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.163780 | 0.195780 | 0.155200 | 0.209890 | 0.275350 |
$ python3 frisbee-bruteforce.py 10
Die Wahrscheinlichkeiten, dass das Frisbee mit 10 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
------------------------------------------------------------------
von 0 | 0.164610 | 0.192827 | 0.155590 | 0.209706 | 0.277267 |
von 1 | 0.164609 | 0.192827 | 0.155587 | 0.209704 | 0.277272 |
von 2 | 0.164610 | 0.192827 | 0.155589 | 0.209706 | 0.277269 |
von 3 | 0.164610 | 0.192826 | 0.155591 | 0.209708 | 0.277265 |
von 4 | 0.164608 | 0.192829 | 0.155583 | 0.209700 | 0.277280 |
Frisbee-Simulation 1.4.63
Exakte Berechnung des Frisbee-Problems mit Dynamischem Programmieren
Mit welcher Wahrscheinlichkeit landet das Frisbee mit zwei Wurfen von Spieler 0 bei Spieler 2?
m zu 0 zu 1 zu 2 zu 3 zu 4
von 0 0.1 0.1 0.3 0.3 0.2
von 1 0.3 0.05 0.1 0.2 0.35
von 2 0.2 0.2 0.2 0.2 0.2
von 3 0.15 0.25 0.2 0.3 0.1
von 4 0.1 0.3 0.05 0.1 0.45
0
0 1 2 3 4
2
Die 2-Wurf-Wege von 0 nach 2,
Frisbee”
dynamisch programmiert“ 1.4.64
Exakte Berechnung des Frisbee-Problems mit Dynamischem Programmieren
Mit welcher Wahrscheinlichkeit landet das Frisbee mit zwei Wurfen von Spieler 0 bei Spieler 2?
m zu 0 zu 1 zu 2 zu 3 zu 4
von 0 0.1 0.1 0.3 0.3 0.2
von 1 0.3 0.05 0.1 0.2 0.35
von 2 0.2 0.2 0.2 0.2 0.2
von 3 0.15 0.25 0.2 0.3 0.1
von 4 0.1 0.3 0.05 0.1 0.45
0
0 1 2 3 4
2
0.1 0.1 0.3 0.3 0.2
Die 2-Wurf-Wege von 0 nach 2,
die Wahrscheinlichkeiten jedes einzelnen Wurfes,
Frisbee”
dynamisch programmiert“ 1.4.64
Exakte Berechnung des Frisbee-Problems mit Dynamischem Programmieren
Mit welcher Wahrscheinlichkeit landet das Frisbee mit zwei Wurfen von Spieler 0 bei Spieler 2?
m zu 0 zu 1 zu 2 zu 3 zu 4
von 0 0.1 0.1 0.3 0.3 0.2
von 1 0.3 0.05 0.1 0.2 0.35
von 2 0.2 0.2 0.2 0.2 0.2
von 3 0.15 0.25 0.2 0.3 0.1
von 4 0.1 0.3 0.05 0.1 0.45
0
0 1 2 3 4
2
0.1 0.1 0.3 0.3 0.2
0.3 0.1 0.2 0.3 0.05
Die 2-Wurf-Wege von 0 nach 2,
die Wahrscheinlichkeiten jedes einzelnen Wurfes,
Frisbee”
dynamisch programmiert“ 1.4.64
Exakte Berechnung des Frisbee-Problems mit Dynamischem Programmieren
Mit welcher Wahrscheinlichkeit landet das Frisbee mit zwei Wurfen von Spieler 0 bei Spieler 2?
m zu 0 zu 1 zu 2 zu 3 zu 4
von 0 0.1 0.1 0.3 0.3 0.2
von 1 0.3 0.05 0.1 0.2 0.35
von 2 0.2 0.2 0.2 0.2 0.2
von 3 0.15 0.25 0.2 0.3 0.1
von 4 0.1 0.3 0.05 0.1 0.45
0
0 1 2 3 4
2
0.1 0.1 0.3 0.3 0.2
0.3 0.1 0.2 0.3 0.05
0.03 0.01 0.06 0.09 0.01
Die 2-Wurf-Wege von 0 nach 2,
die Wahrscheinlichkeiten jedes einzelnen Wurfes,
und die Wahrscheinlichkeiten jeder 2-Wurf-Folge.
Frisbee”
dynamisch programmiert“ 1.4.64
Exakte Berechnung des Frisbee-Problems mit Dynamischem Programmieren
Mit welcher Wahrscheinlichkeit landet das Frisbee mit zwei Wurfen von Spieler 0 bei Spieler 2?
m zu 0 zu 1 zu 2 zu 3 zu 4
von 0 0.1 0.1 0.3 0.3 0.2
von 1 0.3 0.05 0.1 0.2 0.35
von 2 0.2 0.2 0.2 0.2 0.2
von 3 0.15 0.25 0.2 0.3 0.1
von 4 0.1 0.3 0.05 0.1 0.45
0
0 1 2 3 4
2
0.1 0.1 0.3 0.3 0.2
0.3 0.1 0.2 0.3 0.05
0.03 0.01 0.06 0.09 0.01
0.2
Die 2-Wurf-Wege von 0 nach 2,
die Wahrscheinlichkeiten jedes einzelnen Wurfes,
und die Wahrscheinlichkeiten jeder 2-Wurf-Folge.
Die Wahrscheinlichkeit,von 0 mit 2 Wurfen bei 2 zu landen, istm[0][0]*m[0][2]+
m[0][1]*m[1][2]+
m[0][2]*m[2][2]+
m[0][3]*m[3][2]+
m[0][4]*m[4][2]Frisbee
”dynamisch programmiert“ 1.4.64
Exakte Berechnung des Frisbee-Problems mit Dynamischem Programmieren
Mit welcher Wahrscheinlichkeit landet das Frisbee mit zwei Wurfen von Spieler 0 bei Spieler 2?
m zu 0 zu 1 zu 2 zu 3 zu 4
von 0 0.1 0.1 0.3 0.3 0.2
von 1 0.3 0.05 0.1 0.2 0.35
von 2 0.2 0.2 0.2 0.2 0.2
von 3 0.15 0.25 0.2 0.3 0.1
von 4 0.1 0.3 0.05 0.1 0.45
0
0 1 2 3 4
2
0.1 0.1 0.3 0.3 0.2
0.3 0.1 0.2 0.3 0.05
0.03 0.01 0.06 0.09 0.01
0.2
Die 2-Wurf-Wege von 0 nach 2,
die Wahrscheinlichkeiten jedes einzelnen Wurfes,
und die Wahrscheinlichkeiten jeder 2-Wurf-Folge.
Die Wahrscheinlichkeit,von z mit 2 Wurfen bei s zu landen, istm[z][0]*m[0][s]+
m[z][1]*m[1][s]+
m[z][2]*m[2][s]+
m[z][3]*m[3][s]+
m[z][4]*m[4][s]Frisbee
”dynamisch programmiert“ 1.4.64
Exakte Berechnung des Frisbee-Problems mit Dynamischem Programmieren
Mit welcher Wahrscheinlichkeit landet das Frisbee mit zwei Wurfen von Spieler 0 bei Spieler 2?
m zu 0 zu 1 zu 2 zu 3 zu 4
von 0 0.1 0.1 0.3 0.3 0.2
von 1 0.3 0.05 0.1 0.2 0.35
von 2 0.2 0.2 0.2 0.2 0.2
von 3 0.15 0.25 0.2 0.3 0.1
von 4 0.1 0.3 0.05 0.1 0.45
0
0 1 2 3 4
2
0.1 0.1 0.3 0.3 0.2
0.3 0.1 0.2 0.3 0.05
0.03 0.01 0.06 0.09 0.01
0.2
Ein Programm zum Erzeugen eines Arrays neu der Große von m,in dem neu[z][s] die Wahrscheinlichkeit ist,dass das Frisbee in 2 Wurfen von z zu s kommt.
# Erzeuge das Array neu und fulle es mit 0en.
neu = [0]*len(m)
for i in range(len(m)): neu[i] = [0]*len(m)
# Fulle das Array neu mit den Wahrscheinlichkeiten.
for z in range(len(m)):
for s in range(len(m)):
for i in range(len(m)):
neu[z][s] += m[z][i]*m[i][s]
Die Wahrscheinlichkeit,von z mit 2 Wurfen bei s zu landen, istm[z][0]*m[0][s]+
m[z][1]*m[1][s]+
m[z][2]*m[2][s]+
m[z][3]*m[3][s]+
m[z][4]*m[4][s]Frisbee
”dynamisch programmiert“ 1.4.64
Die Matrix (2d-Array) m ist quadratisch – sie hat gleichviele Zeilen und Spalten.
Der Prozess, durch den die Matrix neu aus der Matrix m entsteht,
heißt (mathematisch) Quadrieren von m (Multiplikation von m mit m).
Sei m1 die Matrix, die man beim Quadrieren von m erhalt.
Dann ist m1rzsrss die Wahrscheinlichkeit, dass das Frisbee von z in 2 Wurfen zu s kommt.
Sei m2 die Matrix, die man beim Quadrieren von m1 erhalt.
Dann ist m2rzsrss die Wahrscheinlichkeit, dass das Frisbee von z in 4 Wurfen zu s kommt.
Sei m3 die Matrix, die man beim Quadrieren von m2 erhalt.
Dann ist m3rzsrss die Wahrscheinlichkeit, dass das Frisbee von z in 8 Wurfen zu s kommt.
Sei mi die Matrix, die man beim i-maligen Quadrieren von m erhalt.
Dann ist mirzsrss die Wahrscheinlichkeit, dass das Frisbee von z in 2i Wurfen zu s kommt.
Frisbee”
dynamisch programmiert“ 1.4.65
Diese Losungsidee nennt man”Dynamisches Programmieren“.
Dabei zerlegt man ein Problem (hier: das Frisbee-Problem fur Wurffolgen aus 2n Wurfen)
in Teilprobleme (hier ist es nur ein Teilproblem: das Frisbee-Problem fur Wurffolgen aus 2n´1
Wurfen).
und baut aus den Losungen der Teilprobleme die Losung fur das ganze Problem zusammen
(hier: durch Quadrieren).
Die Teilprobleme lost man wieder durch Zerlegen in weitere Teilprobleme,
bis man bei den unzerlegbaren Grundproblemen angekommen ist
(hier: das Frisbee-Problem fur Wurffolgen aus 20 Wurfen – dessen Losung ist durch m gegeben).
Da wir wissen, dass die Gesamtheit der betrachteten Teilprobleme bei Wurffolgen aus 2n Wurfen
die Probleme fur Wurffolgen aus 20, 21, 22, 23, . . . , 2n´1 Wurfen sind,
haben wir gleich mit dem Grundproblem (Wurffolgen aus 20 Wurfen) begonnen,
den Zerlegungsschritt nicht explizit gemacht und nur die Losungen der Teilprobleme schrittweise
(durch Quadrieren) aus deren Teillosungen zusammengebaut,
bis das ganze Problem gelost war. Frisbee”
dynamisch programmiert“ 1.4.66
Wir wollen jetzt ein Programm schreiben,
das eine quadratische Matrix (z.B. m) n-mal quadriert und ausgibt.
Grobe Struktur des Programmes:
lies n von der Kommandozeile
die quadratische Matrix m wird im Programm angegeben
wiederhole n-mal:
quadriere m (das Ergebnis heißt dann wieder m)
Wie das Quadrieren einer (quadratischen) Matrix geht,
haben wir auf einer der vorigen Folien gesehen . . .
Frisbee”
dynamisch programmiert“ 1.4.67
# frisbee-quadrat.py
#------------------------------------------------------------------------------------------------------
# Eine Gruppe von Frisbee-Spielern wirft ein Frisbee mit bestimmten Wahrscheinlichkeiten herum.
# Finde heraus, mit welcher Wahrscheinlichkeit das Frisbee nach 2**n Wurfen bei den Mitspielern landet.
#------------------------------------------------------------------------------------------------------
import sys, random
#----- Die Vorbereitungen
# n wird von der Kommandozeile gelesen.
n = int(sys.argv[1])
# m ist die Matrix mit den Wahrscheinlichkeiten m[z][s],
# dass Spieler z zu Spieler s wirft.
m = [ [ 0.1, 0.1, 0.3, 0.3, 0.2 ], # Spieler 0 wirft mit Wkeit 0.1 zu Spieler 0 und 1,
[ 0.3, 0.05,0.1, 0.2, 0.35], # und mit Wkeit 0.2 zu anderen Spielern
[ 0.2, 0.2, 0.2, 0.2, 0.2 ],
[0.15, 0.25,0.3, 0.3, 0.0 ],
[ 0.1, 0.3,0.05, 0.1, 0.45] ]
#----- Das n-fache Quadrieren der Matrix
for q in range(n): # Es werden n Quadrierungen durchgefuhrt.
neu = [0]*len(m) # Das 2d-Array, das durch Quadrieren von m entsteht, heißt neu.
for i in range(len(m)): neu[i] = [0]*len(m) # Es wird zunachst mit lauter 0en gefullt.
# Nun wird an jede Stelle neu[z][s] die Summe der Produkte der j-ten Eintrage von Zeile z und Spalte s von m geschrieben.
for z in range(len(m)):
for s in range(len(m)):
for j in range(len(m[z])):
neu[z][s] += m[z][j]*m[j][s]
# Das Ergebnis des Quadrierens von m wird nun m genannt.
m = neu
Frisbee”
dynamisch programmiert“ 1.4.68
#----- Die Ausgabe des Ergebnisses.
# Es wird ausgegeben, mit welcher Wkeit das Frisbee bei welchem Spieler landet.
# Dazu wird die berechnete Matrix schon ausgegeben.
print('''
Die Wahrscheinlichkeiten, dass das Frisbee mit %d Wurfen von x zu y kommt,
sind wie folgt:
''' % 2**n)
# Die erste Zeile der Ausgabe
print(' '*8 + '|', end='')
for i in range(len(m)): print(' zu %2d |' % i, end='')
print()
# Die zweite Zeile der Ausgabe
print('-'*9*(len(m)+1))
# Die Zeilen der Matrix.
for z in range(len(m)):
print(' von %2d |' % z, end='')
for s in range(len(m[z])):
print( ' %.4f |' % m[z][s], end='')
print()
print()
#-----------------------------------------------------------------------------------------
Frisbee”
dynamisch programmiert“ 1.4.69
Bei einem Wurf kommen genau die in m eingetragenen Wahrscheinlichkeiten heraus.
$ python3 frisbee-quadrat.py 0
Die Wahrscheinlichkeiten, dass das Frisbee mit 1 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
----------------------------------------------------------------
von 0 | 0.100000 | 0.100000 | 0.300000 | 0.300000 | 0.200000 |
von 1 | 0.300000 | 0.050000 | 0.100000 | 0.200000 | 0.350000 |
von 2 | 0.200000 | 0.200000 | 0.200000 | 0.200000 | 0.200000 |
von 3 | 0.150000 | 0.250000 | 0.200000 | 0.300000 | 0.100000 |
von 4 | 0.100000 | 0.300000 | 0.050000 | 0.100000 | 0.450000 |
Frisbee”
dynamisch programmiert“ 1.4.70
Bei”vielen“ Wurfen sieht man,
dass die Wahrscheinlichkeiten nicht mehr von der Startperson abhangig sind
und sich bei mehr Wurfen auch nicht mehr andern.
Diese Eigenschaft folgt aus Eigenschaften der Ausgangsmatrix m.
$ python3 frisbee-quadrat.py 2
Die Wahrscheinlichkeiten, dass das Frisbee mit 4 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
----------------------------------------------------------------
von 0 | 0.164075 | 0.192600 | 0.158113 | 0.211675 | 0.273537 |
von 1 | 0.164275 | 0.192119 | 0.155781 | 0.209813 | 0.278013 |
von 2 | 0.165250 | 0.192300 | 0.156600 | 0.210700 | 0.275150 |
von 3 | 0.165700 | 0.192019 | 0.158238 | 0.212200 | 0.271844 |
von 4 | 0.163975 | 0.194363 | 0.151381 | 0.206013 | 0.284269 |
Frisbee”
dynamisch programmiert“ 1.4.71
Bei”vielen“ Wurfen sieht man,
dass die Wahrscheinlichkeiten nicht mehr von der Startperson abhangig sind
und sich bei mehr Wurfen auch nicht mehr andern.
Diese Eigenschaft folgt aus Eigenschaften der Ausgangsmatrix m.
$ python3 frisbee-quadrat.py 3
Die Wahrscheinlichkeiten, dass das Frisbee mit 8 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
----------------------------------------------------------------
von 0 | 0.164616 | 0.192819 | 0.155610 | 0.209724 | 0.277231 |
von 1 | 0.164610 | 0.192829 | 0.155584 | 0.209701 | 0.277276 |
von 2 | 0.164612 | 0.192823 | 0.155602 | 0.209717 | 0.277246 |
von 3 | 0.164617 | 0.192816 | 0.155622 | 0.209735 | 0.277210 |
von 4 | 0.164598 | 0.192842 | 0.155543 | 0.209664 | 0.277353 |
Frisbee”
dynamisch programmiert“ 1.4.71
Bei”vielen“ Wurfen sieht man,
dass die Wahrscheinlichkeiten nicht mehr von der Startperson abhangig sind
und sich bei mehr Wurfen auch nicht mehr andern.
Diese Eigenschaft folgt aus Eigenschaften der Ausgangsmatrix m.
$ python3 frisbee-quadrat.py 4
Die Wahrscheinlichkeiten, dass das Frisbee mit 16 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
----------------------------------------------------------------
von 0 | 0.164609 | 0.192827 | 0.155587 | 0.209704 | 0.277272 |
von 1 | 0.164609 | 0.192827 | 0.155587 | 0.209704 | 0.277272 |
von 2 | 0.164609 | 0.192827 | 0.155587 | 0.209704 | 0.277272 |
von 3 | 0.164609 | 0.192827 | 0.155587 | 0.209704 | 0.277272 |
von 4 | 0.164609 | 0.192827 | 0.155587 | 0.209704 | 0.277272 |
Frisbee”
dynamisch programmiert“ 1.4.71
Bei”vielen“ Wurfen sieht man,
dass die Wahrscheinlichkeiten nicht mehr von der Startperson abhangig sind
und sich bei mehr Wurfen auch nicht mehr andern.
Diese Eigenschaft folgt aus Eigenschaften der Ausgangsmatrix m.
$ python3 frisbee-quadrat.py 10
Die Wahrscheinlichkeiten, dass das Frisbee mit 1024 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
----------------------------------------------------------------
von 0 | 0.164609 | 0.192827 | 0.155587 | 0.209704 | 0.277272 |
von 1 | 0.164609 | 0.192827 | 0.155587 | 0.209704 | 0.277272 |
von 2 | 0.164609 | 0.192827 | 0.155587 | 0.209704 | 0.277272 |
von 3 | 0.164609 | 0.192827 | 0.155587 | 0.209704 | 0.277272 |
von 4 | 0.164609 | 0.192827 | 0.155587 | 0.209704 | 0.277272 |
Das”kostet“ 10 ¨ 53 Multiplikationen
(statt mehr als 51025 mit dem vorigen Programm).
Frisbee”
dynamisch programmiert“ 1.4.71
Noch ein paar Bemerkungen zum Auftreten von Rundungsfehlern
Im Array m mit den Wurffwahrscheinlichkeiten
haben alle Zeilen die Summe 1, da jeder Spieler garantiert wirft.
Entsprechend mussen in allen Arrays m, die im Laufe des Programmes durch wiederholtes
Quadrieren berechnet werden, auch in allen Zeilen die Summe 1 haben,
da das Frisbee nach beliebiger Anzahl von Wurfen immer irgendwo ist.
Leider ist das”in der Realitat“ nicht so: durch Rundungsfehler beim Rechnen mit float-Werten
entstehen sehr schnell Zeilensumme ungleich 1.
”Unglucklicherweise“ sind diese Zeilensumme alle großer als 1 (und nie kleiner als 1),
so dass sich die Fehler nicht gegenseitig wieder”ausgleichen“.
Sie schaukeln sich vielmehr hoch, so dass die Zeilensummen immer großer werden.
Auf der folgenden Seite sieht die Summen von m[0] am Ende der Quadrier-Schleife uber q.
Frisbee”
dynamisch programmiert“ 1.4.72
Die Summen von m[0] am Ende der Quadrier-Schleife uber q.
q | sum(m[0])
-------------------------
0 | 1.0000000000000000
1 | 1.0000000000000002
2 | 1.0000000000000002
3 | 1.0000000000000007
4 | 1.0000000000000016
5 | 1.0000000000000029
6 | 1.0000000000000060
7 | 1.0000000000000120
8 | 1.0000000000000240
9 | 1.0000000000000480
10 | 1.0000000000000964
11 | 1.0000000000001925
12 | 1.0000000000003855
13 | 1.0000000000007707
14 | 1.0000000000015414
15 | 1.0000000000030829
16 | 1.0000000000061655
17 | 1.0000000000123310
18 | 1.0000000000246621
19 | 1.0000000000493245
q | sum(m[0])
-------------------------
20 | 1.0000000000986489
...
40 | 1.0001034463544389
...
50 | 1.1117369235921244
51 | 1.2359589872780812
52 | 1.5275946182334601
53 | 2.3335453176558305
54 | 5.4454337495534517
55 | 29.6527487207757652
56 | 879.2855066974686906
57 | 773143.0022882241755724
58 | 597750101987.2491455078125000
59 | 357305184425766786433024.0000000000000000
60 | 127666994817531223687511336360086608555387387904.0000000000000000
61 | 16298861565739543179307449317066935184232434397238380172718357830145135373363194300023206576128.0000000000000000
62 | 26565288833914163663899252402006839285301226789647187468341106234994526369159899865489080320.0000000000000000
63 | inf
64 | inf
Frisbee”
dynamisch programmiert“ 1.4.73
Dadurch sind die Ergebnisse eigentlich von Anfang an falsch und werden immer falscher.
Irgendwann sieht man dann sogar sofort, dass die Ergebnisse nicht stimmen konnen.
In der”Numerischen Mathematik“ kummert man sich (u.a.) darum,
wie man Rundungsfehler vermeiden/klein halten/abschatzen kann.
$ python3 frisbee-quadrat.py 54
Die Wahrscheinlichkeiten, dass das Frisbee mit 18014398509481984 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
----------------------------------------------------------------
von 0 | 0.384124 | 0.449971 | 0.363070 | 0.489354 | 0.647026 |
von 1 | 0.384124 | 0.449971 | 0.363070 | 0.489354 | 0.647026 |
von 2 | 0.384124 | 0.449971 | 0.363070 | 0.489354 | 0.647026 |
von 3 | 0.384124 | 0.449971 | 0.363070 | 0.489354 | 0.647026 |
von 4 | 0.384124 | 0.449971 | 0.363070 | 0.489354 | 0.647026 |
Frisbee”
dynamisch programmiert“ 1.4.74
Dadurch sind die Ergebnisse eigentlich von Anfang an falsch und werden immer falscher.
Irgendwann sieht man dann sogar sofort, dass die Ergebnisse nicht stimmen konnen.
In der”Numerischen Mathematik“ kummert man sich (u.a.) darum,
wie man Rundungsfehler vermeiden/klein halten/abschatzen kann.
$ python3 frisbee-quadrat.py 58
Die Wahrscheinlichkeiten, dass das Frisbee mit 288230376151711744 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
----------------------------------------------------------------
von 0 | 127266.623445 | 149083.097887 | 120291.366770 | 162131.339229 | 214370.574957 |
von 1 | 127266.623445 | 149083.097887 | 120291.366770 | 162131.339229 | 214370.574957 |
von 2 | 127266.623445 | 149083.097887 | 120291.366770 | 162131.339229 | 214370.574957 |
von 3 | 127266.623445 | 149083.097887 | 120291.366770 | 162131.339229 | 214370.574957 |
von 4 | 127266.623445 | 149083.097887 | 120291.366770 | 162131.339229 | 214370.574957 |
Frisbee”
dynamisch programmiert“ 1.4.74
Dadurch sind die Ergebnisse eigentlich von Anfang an falsch und werden immer falscher.
Irgendwann sieht man dann sogar sofort, dass die Ergebnisse nicht stimmen konnen.
In der”Numerischen Mathematik“ kummert man sich (u.a.) darum,
wie man Rundungsfehler vermeiden/klein halten/abschatzen kann.
$ python3 frisbee-quadrat.py 70
Die Wahrscheinlichkeiten, dass das Frisbee mit 1180591620717411303424 Wurfen von x zu y kommt,
sind wie folgt:
| zu 0 | zu 1 | zu 2 | zu 3 | zu 4 |
----------------------------------------------------------------
von 0 | inf | inf | inf | inf | inf |
von 1 | inf | inf | inf | inf | inf |
von 2 | inf | inf | inf | inf | inf |
von 3 | inf | inf | inf | inf | inf |
von 4 | inf | inf | inf | inf | inf |
Frisbee”
dynamisch programmiert“ 1.4.74
Zusammenfassung
Wir kennen den Datentyp list (Array) jetzt genauer,
konnen 2-dimensionale Arrays erzeugen und auf ihre Elemente zugreifen,
haben gesehen,
wie man ein Netzwerk mit Ubergangswahrscheinlichkeiten durch 2d-Arrays modellieren kann,
haben verschiedene Algorithmen-Arten zur Losung eines Netzwerk-Problems gesehen,
und haben eine Vorstellung vom Sinn des Quadrierens von Matrizen.
1.4.75
Anhang: Ein Farbungsexperiment
Ein Feld wird in lauter kleine Quadrate aufgeteilt, die zufallig gefarbt werden. (Im Beispiel sind es 10ˆ10kleine Quadrate und 4 Farben.)
Die Farbung am Anfang Die Farbung nach einer Runde
Anschließend wird rundenweise eine neue Farbung bestimmt. Dazu wird fur jedes Quadrat zufallig einerseiner direkten Nachbarn (oder es selbst) ausgewahlt und die Farbe wechselt zur Farbe des ausgewahltenNachbarn. (Man stellt sich die Rander des Feldes an den gegenuberliegenden Seiten zusammengeklebt vor,damit jedes Quadrat 8 Nachbarn hat). Diese Runden sollen solange wiederholt werden, bis alle Quadratedie gleiche Farbe haben. Passiert das? 1.4.76
# faerbungsexperiment.py
import sys, stdarray, random
n = int(sys.argv[1]) # die Seitenlange des Feldes
farben = int(sys.argv[2]) # die Anzahl der Farben fur die Quadrate
# Initialisiere das Array feld und farbe die Quadrate zufallig.
feld = stdarray.create2D(n, n, 0)
for z in range(n):
for s in range(n): feld[z][s] = random.randrange(0,farben)
# Bereite die Wiederholungen des Experiments vor.
rundenzaehler = 0
alleGleich = False # Wir gehen davon aus, dass nicht alle Quadrate die gleiche Farbe haben.
# Das Experiment wird solange wiederholt, bis alle Quadrate die gleiche Farbe haben.
while not alleGleich:
neu = stdarray.create2D(n,n,0) # das Array brauchen wir fur die Farben nach einer Runde
rundenzaehler += 1
alleGleich = True
# Schaue jedes Quadrat an.
for z in range(n):
for s in range(n):
# Wahle zufallig einen Nachbarn aus der direkten Nachbarschaft (randubergreifend).
nachbar_zeile = random.randrange(z-1,z+2) % n
nachbar_spalte = random.randrange(s-1,s+2) % n
# Die neue Farbe des Quadrats wird bestimmt.
neu[z][s] = feld[nachbar_zeile][nachbar_spalte]
# Falls eine zweite Farbe gefunden wird, wird alleGleich False (und bleibt es bis Rundenende).
alleGleich = alleGleich and neu[z][s]==neu[0][0]
# feld wird zum neu-berechneten Feld neu
feld = neu
# Gib die Dauer des Experiments aus.
print('Nach ' + str(rundenzaehler) + ' Runden haben alle Quadrate im Feld die gleiche Farbe.')
#-----------------------------------------------------------------------
1.4.77
Vorlesung 05
1. Elemente des Programmierens
1.2 Grundlegende Daten-Typen
1.3 Verzweigungen und Schleifen
1.4 Arrays
1.5 Ein- und Ausgabestandard output
standard input
standard drawing
1.6 Dictionaries und Abschluss-Beispiel Page Rank
1.5.1
1.5 Ein- und Ausgabe
Die bisher benutzten Programme konnten Eingaben von der Kommandozeile lesen
und Text auf dem Bildschirm ausgeben.
Eingabe von der Kommandozeile
§ konnen uber das Array sys.argv[] benutzt werden
§ sind stets vom Typ string und mussen mittels Funktionen wie int() oder float() etc.
zum passenden Typ konvertiert werden.
Text-Ausgaben auf dem Bildschirm
§ konnen mit der Funktion print(x) ausgegeben werden
§ sind stets vom Typ string
§ bilden den Datenstrom standard output.
1.5.2
Schematische Darstellung einfacher Ein- und Ausgabemoglichkeiten
programm.py
standard input
standard output
Kommandozeile
standard drawing
Wir kennen:
§ Kommandozeile
§ standard output (print)
Diese Vorlesung:
§ mehr zu str fur print
§ standard input
§ Verbindung von standard outputund standard input
Nachste Vorlesung:
§ standard drawing(mit Modul stddraw.py)
1.5.3
Ausgabe mit print
standard output ist der ubliche Datenstrom fur die Ausgabe von Daten.
Zum Schreiben in den Datenstrom benutzt man die Funktion print(...).
Der Datenstrom wird auf dem Bildschirm angezeigt.
Man kann ihn außerhalb des Programms auch in eine Datei umlenken
oder zum Eingabe-Datenstrom fur ein anderes Programm machen.
print(x) schreibe String x gefolgt von einem Zeilenumbruch '\n' auf standard output
(Wenn x weggelassen wird, wird nur ein Zeilenumbruch geschrieben)
print(x, end='', flush=True) schreibe String x ohne Zeilenumbruch sofort auf standard output
(Wenn end='' bzw. flush=True weggelassen wird, dann
werden die Default-Argumente end='\n' bzw. flush=False eingesetzt .)
print(x, file=f) schreibe String x in die Datei mit Dateiobjekt fstandard output – print 1.5.4
Formatierte”
schone“ Ausgabe mit der %-Operation auf Strings
'Die Wurzel von %5d ist %7.4f.' % (n, r)
ergibt mit n=1000 und r=31.62276 den String
'Die Wurzel von 1000 ist 31.6228.'
standard output – print 1.5.5
Formatierte”
schone“ Ausgabe mit der %-Operation auf Strings
'Die Wurzel von %5d ist %7.4f.' % (n, r)
Tupel der einzusetzenden WerteFormat-String
ergibt mit n=1000 und r=31.62276 den String
'Die Wurzel von 1000 ist 31.6228.'
standard output – print 1.5.5
Formatierte”
schone“ Ausgabe mit der %-Operation auf Strings
'Die Wurzel von %5d ist %7.4f.' % (n, r)
Tupel der einzusetzenden WerteFormat-String
Konversion
ergibt mit n=1000 und r=31.62276 den String
'Die Wurzel von 1000 ist 31.6228.'
standard output – print 1.5.5
Formatierte”
schone“ Ausgabe mit der %-Operation auf Strings
'Die Wurzel von %5d ist %7.4f.' % (n, r)
Tupel der einzusetzenden WerteFormat-String
Konversion
Konversions-Code
ergibt mit n=1000 und r=31.62276 den String
'Die Wurzel von 1000 ist 31.6228.'
standard output – print 1.5.5
Formatierte”
schone“ Ausgabe mit der %-Operation auf Strings
'Die Wurzel von %5d ist %7.4f.' % (n, r)
Tupel der einzusetzenden WerteFormat-String
Konversion
Feldbreite
ergibt mit n=1000 und r=31.62276 den String
'Die Wurzel von 1000 ist 31.6228.'
standard output – print 1.5.5
Formatierte”
schone“ Ausgabe mit der %-Operation auf Strings
'Die Wurzel von %5d ist %7.4f.' % (n, r)
Tupel der einzusetzenden WerteFormat-String
Konversion
Genauigkeit
ergibt mit n=1000 und r=31.62276 den String
'Die Wurzel von 1000 ist 31.6228.'
standard output – print 1.5.5
Typ Konversions-Code Format-String Ergebnis
int d '%14d' % 1984 ergibt ' 1984'
'%-14d' % 1984 ergibt '1984 '
float f '%14.2f' % 1234.12345678 ergibt ' 1234.12'
'%.6f' % 1234.12345678 ergibt '1234.123457'
e '%14.4e' % 1234.12345678 ergibt ' 1.2341e+03'
string s '%14s' % 'Hello, World' ergibt ' Hello, World'
'%-14s' % 'Hello, World' ergibt 'Hello, World '
'%-14.5s' % 'Hello, World' ergibt 'Hello '
Statt eines Tupels aus einem Element kann man auch das Element ohne Klammern und Komma schreiben.
standard output – print 1.5.6
#-----------------------------------------------------------------------------------------
# formatierteAusgabe.py
#-----------------------------------------------------------------------------------------
# Beispiele fur die formatierte Ausgabe von int- und float-Werten.
#-----------------------------------------------------------------------------------------
import math
n = 1000
r = math.sqrt(n)
# Unformatierte Ausgabe:
# Gib int n und float r aus.
print('(1) Die Wurzel von ' + str(n) + ' ist ' + str(r) + '.')
# Formatierte Ausgaben:
# Gib int n und float r aus. Bei float werden standardmaßig 6 Nachkommastellen ausgegeben.
print( '(2) Die Wurzel von %d ist %f.' % (n, r) )
# Gib int n mit 5 Zeichen und float r mit 3 Nachkommastellen aus
# und fuge einen zusatzlichen Zeilenumbruch am Zeilenende ein.
print( '(3) Die Wurzel von %5d ist %.3f.' % (n, r) )
# Wenn Zeilenumbruche wie im Format-String gemacht werden sollen,
# dann muss man ihn in ''' einklammern.
print( '''(4) Die Wurzel von
%5d
ist %.3f.''' % (n, r) )
# (1) Die Wurzel von 1000 ist 31.622776601683793.
# (2) Die Wurzel von 1000 ist 31.622777.
# (3) Die Wurzel von 1000 ist 31.623.
# (4) Die Wurzel von
# 1000
# ist 31.623.
standard output – print 1.5.7
# Gib int n mit 5 Zeichen und float r mit 8 Zeichen und 3 Nachkommastellen aus.
print('(5) Die Wurzel von %5d ist %8.3f.' % (n, r))
# Gib int n mit 5 Zeichen und float r linksbundig mit 8 Zeichen und 3 Nachkommastellen aus
# und lasse den Zeilenumbruch am Ende der Ausgabe weg (geht nur in Python3).
print( '(6) Die Wurzel von %5d ist %-8.3f.' % (n, r) , end='' )
# Wenn die angegebene Zeichenzahl zu klein ist, wird sie ignoriert.
print( '(7) Die Wurzel von %2d ist %1.3f.' % (n, r) )
# (5) Die Wurzel von 1000 ist 31.623.
# (6) Die Wurzel von 1000 ist 31.623 .(7) Die Wurzel von 1000 ist 31.623.
standard output – print 1.5.8
Leite standard output in eine Datei um und nicht auf den Bildschirm
# wuerfele.py
#----------------------------------------------------------------------
# Lies n von der Kommandozeile und gib n Wurfe mit einem Wurfel aus.
#----------------------------------------------------------------------
import sys, random
n = int(sys.argv[1])
for i in range(n):
print(random.randrange(1,7))
#---------------------------------------------------------------------
# python3 wuerfele.py 4
# 4
# 4
# 1
# 2
Man kann das Programm beliebig viele Werte ausgeben lassen (Datenstrom).
Die Ausgabe erfolgt auf dem Bildschirm oder kann in eine Datei umgeleitet werden.
standard output – Ausgabeumleitung 1.5.9
Leite standard output in eine Datei um und nicht auf den Bildschirm
# wuerfele.py
#----------------------------------------------------------------------
# Lies n von der Kommandozeile und gib n Wurfe mit einem Wurfel aus.
#----------------------------------------------------------------------
import sys, random
n = int(sys.argv[1])
for i in range(n):
print(random.randrange(1,7))
#---------------------------------------------------------------------
# python3 wuerfele.py 100000 > wuerfelergebnisse.txt
# (...Die Ausgabe wird in Datei wuerfelergebnisse.txt geschrieben...)
#
#
#
Man kann das Programm beliebig viele Werte ausgeben lassen (Datenstrom).
Die Ausgabe erfolgt auf dem Bildschirm oder kann in eine Datei umgeleitet werden.
standard output – Ausgabeumleitung 1.5.9
Schreibe mit print in eine Datei
# wuerfele-datei.py
#-------------------------------------------------
# Gib 10 Wurfel-Wurfe in die Datei wuerfe.txt aus.
#-------------------------------------------------
import random
# Offne die Datei wuerfe.txt zum Schreiben.
# D.h. erzeuge ein Datei-Objekt dafur.
ausgabe = open('wuerfe.txt', 'w')
for i in range(n):
print(random.randrange(1,7), file=ausgabe)
# Schließe die Datei wuerfe.txt.
ausgabe.close()
#-------------------------------------------------
$ python3 wuerfele-datei.py
$ cat wuerfe.txt
6
3
4
6
3
5
6
1
5
3
standard output – Ausgabeumleitung 1.5.10
Standard input
Standard input ist ein Datenstrom, der von einem Programm als Eingabe gelesen werden.
Der Datenstrom kommt ublicherweise von der Tastatur,
kann aber auch aus einer Datei auf standard input umgeleitet werden
oder die Ausgabe eines”zuvor“ gestarteten Programms sein.
sys.stdin.readline(): gibt die nachste Zeile (Typ str) von standard input zuruck
sys.stdin.readlines(): gibt ein Array aus Strings zuruck
das aus allen Zeilen von standard input besteht
for z in sys.stdin: durchlauft alle Zeilen z (Typ str) von standard input,
bis zum Dateiende <Strg-d>.
standard input 1.5.11
#----------------------------------------------------------------------------------------------------------------------
# mittelwert4.py
#----------------------------------------------------------------------------------------------------------------------
# Von der Kommandozeile wird n eingelesen. Anschließend wird die Eingabe von n int-Werten von standard input erwartet.
# Sie werden mit sys.stdin.readline() gelesen. Der Mittelwert der Werte wird ausgegeben.
#----------------------------------------------------------------------------------------------------------------------
import sys
# Die Anzahl der zu lesenden Werte wird von der Kommandozeile gelesen.
n = int(sys.argv[1])
# Es werden n int-Werte von standard input gelesen und aufsummiert.
summe = 0
for i in range(n):
# Gib die Eingabeaufforderung aus (kein Zeilenwechsel, Ausgabe sofort).
print( 'Eingabe %d von %d: ' % (i+1,n), end='', flush=True )
# Die nachste Zeile wird von standard input gelesen (string s), und der eingelesene Wert wird aufsummiert.
zeile = sys.stdin.readline()
summe += int(zeile)
# Der Mittelwert wird ausgegeben.
print( '\nDer Mittelwert ist %.2f.' % (summe/n) )
#----------------------------------------------------------------------------------------------------------------------
# python3 mittelwert4.py 5
# Eingabe 1 von 5: 1
# Eingabe 2 von 5: 22
# Eingabe 3 von 5: 333
# Eingabe 4 von 5: 4444
# Eingabe 5 von 5: 55555
#
# Der Mittelwert ist 12071.00. standard input 1.5.12
#----------------------------------------------------------------------------------------------------------------------
# mittelwert4.py
#----------------------------------------------------------------------------------------------------------------------
# Von der Kommandozeile wird n eingelesen. Anschließend wird die Eingabe von n int-Werten von standard input erwartet.
# Sie werden mit sys.stdin.readline() gelesen. Der Mittelwert der Werte wird ausgegeben.
#----------------------------------------------------------------------------------------------------------------------
import sys
# Die Anzahl der zu lesenden Werte wird von der Kommandozeile gelesen.
n = int(sys.argv[1])
# Es werden n int-Werte von standard input gelesen und aufsummiert.
summe = 0
for i in range(n):
# Gib die Eingabeaufforderung aus (kein Zeilenwechsel, Ausgabe sofort).
print( 'Eingabe %d von %d: ' % (i+1,n), end='', flush=True )
# Die nachste Zeile wird von standard input gelesen (string s), und der eingelesene Wert wird aufsummiert.
zeile = sys.stdin.readline()
summe += int(zeile)
# Der Mittelwert wird ausgegeben.
print( '\nDer Mittelwert ist %.2f.' % (summe/n) )
#----------------------------------------------------------------------------------------------------------------------
# python3 mittelwert4.py 4
# Eingabe 1 von 4: 1 2 3 4
# Traceback (most recent call last):
# File "mittelwert4.py", line 17, in <module>
# summe += int(s)
# ValueError: invalid literal for int() with base 10: '1 2 3 4'
standard input 1.5.12
#----------------------------------------------------------------------------------------------------
# mittelwert5.py
#----------------------------------------------------------------------------------------------------
# Die Eingabe von int-Werten von standard input wird erwartet und mit sys.stdin.readlines() gelesen.
# Der Mittelwert der Werte wird ausgegeben.
#----------------------------------------------------------------------------------------------------
import sys
# Es werden int-Werte von standard input gelesen und aufsummiert.
# Die Anzahl der eingelesenen Werte wird gezahlt.
summe = 0
zaehler = 0
print('Bitte geben Sie int-Werte ein.')
# Lies alle Zeilen von standard input in das Array zeilen.
alleZeilen = sys.stdin.readlines()
# Gehe durch alle Zeilen, die von standard input stammen.
for zeile in alleZeilen:
# Wandele die Zeile in eine Zahl um und summiere sie auf.
summe += int(zeile)
zaehler += 1
# Der Mittelwert wird ausgegeben.
print( '\nEs wurden %d Werte eingegeben.' % zaehler )
print( 'Der Mittelwert ist %.2f.' % (summe/zaehler) )
$ python3 mittelwert5.py
Bitte geben Sie int-Werte ein.
1
2
3
4
<Strg-d>
Es wurden 4 Werte eingegeben.
Der Mittelwert ist 2.50.
standard input 1.5.13
#--------------------------------------------------------------------------------------------------------
# mittelwert6.py
#--------------------------------------------------------------------------------------------------------
# Die Eingabe von int-Werten von standard input wird erwartet.
# und mit for zeile in sys.stdin: gelesen.
# Der Mittelwert der Werte wird ausgegeben.
#--------------------------------------------------------------------------------------------------------
import sys
# Es sollen int-Werte von standard input gelesen und aufsummiert werden,
# und ihre Anzahl wird gezahlt.
summe = 0
zaehler = 0
print('Bitte geben Sie int-Werte ein.')
# Gehe durch alle Zeilen von standard input,
# summiere die eingegebenen Zahlen auf und zahle sie.
for zeile in sys.stdin:
summe += int(zeile)
zaehler += 1
# Der Mittelwert wird ausgegeben.
print( '\nEs wurden %d Werte eingegeben.' % zaehler )
print( 'Der Mittelwert ist %.2f.' % (summe/zaehler) )
#--------------------------------------------------------
# python3 mittelwert6.py
# Bitte geben Sie int-Werte ein.
# 1
# 2
# 3
# 4
# <Strg-d>
# Es wurden 4 Werte eingegeben.
# Der Mittelwert ist 2.50.
standard input 1.5.14
Direkt aus einer Datei lesen
Statt von standard input mittels sys.stdin
kann man auch direkt aus einer Datei lesen.
Die Datei muss zuerst zum Lesen geoffnet werden.
Das dazu erzeugte Datei-Objekt kann einer Variablen zugewiesen werden.
eingabedatei = open('dateiname', 'r')
Nun kann eingabedatei genau wie sys.stdin verwendet werden.
Wenn das Lesen beendet ist, muss die Datei wieder geschlossen werden.
eingabedatei.close()
standard input 1.5.15
Datei lesen mittels Umleitung auf standard input
Bisher haben wir den Eingabestrom standard input an der Tastatur erzeugt.
Die Umleitung der Eingabe erlaubt auch das Lesen einer Datei (ohne das Programm zu andern).Die Beispiele zeigen:– standard input ist die Tastatur– standard input ist eine Datei (Eingabeumleitung <)– standard input ist die Ausgabe eines Programms (Ausgabeweiterleitung |)
# python3 mittelwert5.py
# Bitte geben Sie int-Werte ein.
# 1
# 2
# 3
# 4
# <Strg-d>
# Es wurden 4 Werte eingegeben.
# Der Mittelwert ist 2.50.
standard input – Eingabeumleitung 1.5.16
Datei lesen mittels Umleitung auf standard input
Bisher haben wir den Eingabestrom standard input an der Tastatur erzeugt.
Die Umleitung der Eingabe erlaubt auch das Lesen einer Datei (ohne das Programm zu andern).Die Beispiele zeigen:– standard input ist die Tastatur– standard input ist eine Datei (Eingabeumleitung <)– standard input ist die Ausgabe eines Programms (Ausgabeweiterleitung |)
# python3 mittelwert5.py
# Bitte geben Sie int-Werte ein.
# 1
# 2
# 3
# 4
# <Strg-d>
# Es wurden 4 Werte eingegeben.
# Der Mittelwert ist 2.50.
# python3 mittelwert5.py < wuerfelergebnisse.txt
# Bitte geben Sie int-Werte ein.
#
# Es wurden 10000 Werte eingegeben.
# Der Mittelwert ist 3.50.
standard input – Eingabeumleitung 1.5.16
Datei lesen mittels Umleitung auf standard input
Bisher haben wir den Eingabestrom standard input an der Tastatur erzeugt.
Die Umleitung der Eingabe erlaubt auch das Lesen einer Datei (ohne das Programm zu andern).Die Beispiele zeigen:– standard input ist die Tastatur– standard input ist eine Datei (Eingabeumleitung <)– standard input ist die Ausgabe eines Programms (Ausgabeweiterleitung |)
# python3 mittelwert5.py
# Bitte geben Sie int-Werte ein.
# 1
# 2
# 3
# 4
# <Strg-d>
# Es wurden 4 Werte eingegeben.
# Der Mittelwert ist 2.50.
# python3 mittelwert5.py < wuerfelergebnisse.txt
# Bitte geben Sie int-Werte ein.
#
# Es wurden 10000 Werte eingegeben.
# Der Mittelwert ist 3.50.
# python3 wuerfele.py 2222 | python3 mittelwert5.py
# Bitte geben Sie int-Werte ein.
#
# Es wurden 2222 Werte eingegeben.
# Der Mittelwert ist 3.48.standard input – Eingabeumleitung 1.5.16
Abschlussbeispiel: Entwicklung der Tageshochsttemperaturen in Jena seit 1824
im Jahresdurchschnitt
Der Deutsche Wetterdienst (DWD) stellt Messwerte als csv-Dateien zur Verfugung.
csv . . . comma separated values (im Beispiel hier sind es Semikolons)
siehe ftp://ftp-cdc.dwd.de/pub/CDC/observations_germany/climate/daily/kl/historical/
Die erste Zeile der Datei enthalt eine Erklarung zu den Spalten der weiteren Zeilen,von denen jede einen Messwert etc. enthalt.
STATIONS_ID;MESS_DATUM;QN_3; FX; FM;QN_4; RSK;RSKF; SDK;SHK_TAG; NM; VPM; PM; TMK; UPM; TXK; TNK; TGK;eor
2444;18240101;-999;-999;-999; 2; -999;-999;-999;-999; -999; -999; 990.70; 4.5;-999; 5.5; 1.6;-999;eor
2444;18240102;-999;-999;-999; 2; -999;-999;-999;-999; -999; -999; 984.00; 5.0;-999; 6.5; 3.1;-999;eor
2444;18240103;-999;-999;-999; 2; -999;-999;-999;-999; -999; -999; 997.80; 3.5;-999; 5.0; 1.9;-999;eor
2444;18240104;-999;-999;-999; 2; -999;-999;-999;-999; -999; -999; 1019.50; 1.2;-999; 2.3; -2.9;-999;eor
2444;18240105;-999;-999;-999; 2; -999;-999;-999;-999; -999; -999; 1021.30; -0.8;-999; 3.0; -3.8;-999;eor
2444;18240106;-999;-999;-999; 2; -999;-999;-999;-999; -999; -999; 1013.80; -3.7;-999; 0.0; -10.4;-999;eor
...
2444;18241231;-999;-999;-999; 2; -999;-999;-999;-999; -999; -999; 1013.30; 6.6; 62.00; 7.0; 0.6;-999;eor
2444;18250101;-999;-999;-999; 2; -999;-999;-999;-999; -999; -999; 1008.00; 8.2; 54.00; 9.1; 2.1;-999;eor
...
2444;20181231;-999;-999;-999; 3; 0.5; 4;-999; 0; -999; 9.0; -999; 7.0; 89.83; 8.6; 6.4; 5.0;eor
Wetterdaten vom DWD 1.5.17
www.dwd.de
-1-
DATENSATZBESCHREIBUNG Historische tägliche Stationsbeobachtungen (Temperatur, Druck, Niederschlag,Sonnenscheindauer, etc.) für Deutschland Version v006 Zitieren mit: DWD Climate Data Center (CDC): Historische tägliche Stationsbeobachtungen (Temperatur, Druck,
Niederschlag, Sonnenscheindauer, etc.) für Deutschland, Version v006, 2018.
ZWECK Diese historischen Daten sind qualitätsgeprüfte Messwerte und Beobachtungen. Sie stammen aus Stationen des DWD und rechtlichund qualitativ gleichgestellten Partnernetzstationen. Umfangreiche Stationsmetadaten (Stationsverlegungen, Instrumentenwechsel,Wechsel der Bezugszeit, Änderungen in den Algorithmen) werden mitgeliefert.
KONTAKT Deutscher WetterdienstCDC - Vertrieb Klima und UmweltFrankfurter Straße 13563067 OffenbachTel.: + 49 (0) 69 8062-4400Fax.: + 49 (0) 69 8062-4499Mail: klima.vertrieb@dwd.de
DATENBESCHREIBUNG Räumliche Abdeckung Stationen in Deutschland
Zeitliche Abdeckung 01.01.1781 - 31.12.2017
Zeitliche Auflösung täglich
Format(e) Die Stationsbeobachtungen (produkt_*.txt) sind gemeinsam mit den Stationsmetadaten gezippt.
Die Stationsmetadaten werden sowohl als *.txt als auch als *.html bereitgestellt. Die DateiMetadaten_Parameter* enthält eine Liste der an dieser Station gemessenen Parameter (dasParameterportfolio), mit Beginn, Ende, dazugehörigen Einheiten, Messvorschriften, Formeln, Terminenund Zeiteinheiten (z.B. MOZ oder UTC) , die der Stations_Id und dem aktuellen Stationsnamen zugeordnetwerden. Die Gerätehistorie ist den meteorologischen Parametern entsprechend sortiert (siehe DateiMetadaten_Geraete*). Dort ist die zeitliche Geschichte der Sensor- bzw Geberhöhen, Gerätetypen undMessverfahren, gemeinsam mit der zeitlichen Geschichte der Stationsnamen enthalten. Die Stations_idist unveränderlich. Um erfolgte Änderung der Stationsnamen bei einzelnen Stationen zu dokumentierten,gibt es zur Übersicht zusätzlich die Datei Metadaten_Stationsname*. Die geographische Metadaten derStation (geografische Länge und Breite, Stationshöhe) sind in Metadaten_Geographie*.txt erfasst, undder Stations_id und dem aktuellem Stationsnamen zugeordnet. Alle Informationen sind für jede Station ineinem einzigen zip-File *_[Stations_id]_[von]_[bis]_hist.zip bereitgestellt. Eine Übersicht über alle Stationen,Startdatum und evtl. Enddatum der Station ist in der Stationsliste hinterlegt. Diese Liste umfasst derVollständigkeit halber nicht nur die hier abgegebenen Stationen, sondern auch jene, deren Urheberrechtenicht beim DWD liegen. Beim angegebenen Kontakt können für Stationen, die in dieser Liste auftreten, fürdie aber kein *.zip veröffentlicht ist, die Nutzungsbedingungen erfragt werden.
Parameter Die Parameterportfolios der einzelnen Stationen sind unterschiedlich umfangreich. Insgesamt stehen in
produkt*.txt folgende Parameter zur Verfügung:STATIONS_ID StationsidentifikationsnummerMESS_DATUM Datum yyyymmdd
www.dwd.de
-2-
QN_3 Qualitätsniveau der nachfolgendenSpalten
code siehe Absatz"Qualitätsinformation"
FX Tagesmaximum Windspitze m/sFM Tagesmittel Windgeschwindigkeit m/sQN_4 Qualitätsniveau der nachfolgenden
Spaltencode siehe Absatz"Qualitätsinformation"
RSK tägliche Niederschlagshöhe mmRSKF Niederschlagsform
0 kein Niederschlag (konventionelleoder automatische Messung),entspricht WMO Code-Zahl 10
1 nur Regen (in historischen Datenvor 1979)
4 Form nicht bekannt, obwohlNiederschlag gemeldet
6 nur Regen; flüssiger Niederschlagbei automatischen Stationen,entspricht WMO Code-Zahl 11
7 nur Schnee; fester Niederschlag beiautomatischen Stationen, entsprichtWMO Code-Zahl 12
8 Regen und Schnee (und/oderSchneeregen); flüssiger und festerNiederschlag bei automatischenStationen, entspricht WMO Code-Zahl 13
9 fehlender Wert oderNiederschlagsform nicht feststellbarbei automatischer Messung,entspricht WMO Code-Zahl 15
SDK tägliche Sonnenscheindauer hSHK_TAG Tageswert Schneehöhe cmNM Tagesmittel des Bedeckungsgrades 1/8VPM Tagesmittel des Dampfdruckes hPaPM Tagesmittel des Luftdrucks hPaTMK Tagesmittel der Temperatur °CUPM Tagesmittel der Relativen Feuchte %TXK Tagesmaximum der Lufttemperatur
in 2m Höhe°C
TNK Tagesminimum der Lufttemperaturin 2m Höhe
°C
TGK Minimum der Lufttemperatur amErdboden in 5cm Höhe
°C
eor Ende data recordFehlwerte sind mit -999 gekennzeichnet. Es ist zu beachten, dass sich innerhalb einer Zeitreihe derZeitbezug hh ändern kann, und zwar je nach Parameter, und je nach Station. Zum Beispiel ist dasZeitintervall der täglichen Niederschlagshöhe in modernerer Zeit als 6 Uhr bis 6 Uhr Folgetag definiert,dies war in früheren Jahren oft anders. Wann eine Zeitangabe in wahrer Ortszeit (WOZ), GesetzlicherZeit (GZ), Mittlerer Ortszeit (MOZ), Mitteleuropäischer Zeit (MEZ) oder Universal Time (UTC) vorliegt,ist in den Dateien Metadaten_Parameter* hinterlegt. Der Wert der Windgeschwindigkeit beruht vor derAutomatisierung z.T auf Schätzwerten der Beobachter (Beaufortskala), welche anschliessend in m/skonvertiert wurden, und ist hier nur als Hilfsgröße gegeben.
Unsicherheiten Heutzutage sind die Stationen nach den WMO-Vorschriften eingerichtet und betrieben. Somit werden
die lokalen Effekte besonders gering gehalten. Je weiter in die Geschichte zurückgegangen wird, destoweniger waren solche vereinheitlichten Vorschriften etabliert. Je nach Anwendung sollten mögliche lokale,regionale und zeitlich sich ändernde Einflüsse untersucht werden, die orts- und parameterspezifischsein können. Unsicherheitsfaktoren für die Langzeitstabilität sind (1) Änderungen in der Stationshöhebei Stationsverschiebungen (besonders für Wind und Temperatur), genaue Angaben dazu sind inden stationsweise gezippten Dateien Metadaten_Geographie* enthalten; (2) Änderungen in denBeobachtungszeiten ("Terminwerte"), aus denen das Tagesmittel berechnet wurde, und (3) Änderungenin der Rechenvorschrift. Genaue Angaben zu (2) und (3) sind in den stationsweise gezippten DateienMetadaten_Parameter* enthalten. Unsicherheiten sind auch zu erwarten von (4) Änderungen in denInstrumenten, siehe Dateien Metadaten_Geraete* und möglicherweise auch aus (5) unterschiedlichenQualitätsprüfverfahren (Behrendt et al., 2011), durch (6) Fehler in Übermittlung oder Software, (7)Beobachterwechsel, und (8) andere, siehe Freydank, 2014 .
Wetterdaten vom DWD 1.5.18
Wert Format SpalteStation 0Mess-Datum YYYYMMDD 1Tages-Niederschlagmenge 6Tages-Sonnenscheindauer 8Tagesmittel des Luftdrucks 12Tagesmittel der Temperatur 13Tagesmaximum der Lufttemperatur in 2m Hohe 15Tagesminimum der Lufttemperatur in 2m Hohe 16Tagesminimum der Lufttemperatur in 5cm Hohe 17
Wetterdaten vom DWD 1.5.19
Wir wollen
die Jahresdurchschnitte der Tageshochst- und -tiefsttemperaturen in Jena
fur jedes Jahr seit 1824 berechnen.
Daraus wollen wir”gleitende“ Durchschnitte uber k Jahre berechnen.
(Der gleitende Durchschnitt fur 1960 uber 5 Jahre ist der Durchschnitt von 1956,. . .,1960.)
(Die Aufgaben fur Hochst- und Tiefsttemperaturen werden getrennt gelost.)
Die Aufgabe teilen wir in drei Teile auf.
Teil 1: filtere aus der DWD-Datei die relevanten Daten heraus, filter-DWD.py
z.B. alle Tageshochsttemperaturen fur jedes Jahr
Teil 2: berechne daraus die Jahresdurchschnittstemperaturen jahres-mittel.py
Teil 3: berechne daraus die gleitenden Durchschnitte kjahres-mittel.py
Die Ausgabe eines Teils dient als Eingabe des nachsten Teils.
Diese”Schnittstelle“ (Form der ausgegebenen/zu lesenden Daten) muss vereinbart werden.
Durchschnittstemperaturen berechnen 1.5.20
DWD-Datei
python3 filter-DWD.py 15
python3 jahres-mittel.py
python3 kjahres-mittel.py 5
1832 11.35
1833 11.33
...
2017 15.43
2018 15.64
Durchschnittstemperaturen berechnen 1.5.21
Teil 1: Filterung der Eingabedatei mit filter-DWD.py
Das Programm erhalt ein int n und die DWD-Datei als Eingabe von standard input
STATIONS_ID;MESS_DATUM;QN_3;FX;FM;QN_4;RSK;RSKF;SDK;SHK_TAG;NM;VPM; PM;TMK;UPM;TXK;TNK; TGK;eor
2444;18240101;-999;-999;-999; 2;-999;-999;-999;-999;-999;-999; 990.70; 4.5;-999; 5.5; 1.6;-999;eor
2444;18240102;-999;-999;-999; 2;-999;-999;-999;-999;-999;-999; 984.00; 5.0;-999; 6.5; 3.1;-999;eor
2444;18240103;-999;-999;-999; 2;-999;-999;-999;-999;-999;-999; 997.80; 3.5;-999; 5.0; 1.9;-999;eor
...
2444;18241231;-999;-999;-999; 2;-999;-999;-999;-999;-999;-999;1013.30; 6.6;62.00;7.0; 0.6;-999;eor
2444;18250101;-999;-999;-999; 2;-999;-999;-999;-999;-999;-999;1008.00; 8.2;54.00;9.1; 2.1;-999;eor
...
2444;20181231;-999;-999;-999; 3; 0.5; 4;-999; 0; -999; 9.0; -999; 7.0; 89.83; 8.6; 6.4; 5.0;eor
und produziert fur n “ 15 die Ausgabe-Zeilen
1824 5.5 6.5 5.0 ... 7.0
1825 9.1 ... ...
...
2018 ... ... 8.6
In jeder Zeile steht zuerst das Jahr und darauf folgen die Werte in Spalte n fur das Jahr.Die Werte sind jeweils durch genau ein Leerzeichen getrennt.
Durchschnittstemperaturen berechnen – Teil 1 1.5.22
Funktionen aus dem Modul str, die wir brauchen werden
str.split(string, trenner) teilt einen String uberall dort,
wo das Zeichen trenner in ihm vorkommt, und gibt diese Teile als Array zuruck.
Beispiel: In
zeile = '2444;18240101; 5.5; 1.6;-999;eor'
felder = str.split(zeile, ';')
ist felder das Array
[ '2444', '18240101', ' 5.5', ' 1.6', '-999', 'eor' ]
str.strip(string) gibt einen String zuruck, der aus string entsteht, indem
alle Leerzeichen, Zeilenumbruche etc. am Anfang und am Ende entfernt werden.
Bsp.: str.strip(' ab c \n ') ergibt 'ab c'.
Durchschnittstemperaturen berechnen – Teil 1 1.5.23
In der DWD-Datei stehen die relevanten Informationen zum Berechnen der
Jahresdurchschnittshochsttemperaturen in Spalte 1 (Datum) und Spalte 15 (Tagesmaximum).
2444;18240101;-999;-999;-999; 2;-999;-999;-999;-999;-999;-999; 990.70; 4.5;-999; 5.5; 1.6;-999;eor
Sei zeile obiger String.
Dann ist str.split(zeile, ';') das Array
['2444', '18240101', '-999', '-999', '-999', ' 2', '-999', '-999', '-999', '-999', '-999', '-999',
' 990.70', ' 4.5', '-999', ' 5.5', ' 1.6', '-999', 'eor' ]
Sei felder = str.split(zeile, ';') obiges Array.
Das Jahr '1824' ist felder[1][0:4] (Typ str),
und der gesuchte Temperaturwert '5.5' ist str.strip(felder[15]) (Typ str).
Durchschnittstemperaturen berechnen – Teil 1 1.5.24
#-------------------------------------------------------------------------------------------------------------------------
# filter-DWD.py
#-------------------------------------------------------------------------------------------------------------------------
# Auf der Kommandozeile wird ein int n erwartet, auf standard input wird eine Wetterdatei vom DWD erwartet.
# Jede ihrer Zeilen enthalt die Messwerte einer Station von einem Tag. Die Eintrage in der Zeile sind durch ';' getrennt.
# Spalte 1 enthalt das Datum in der Form YYYYMMDD, Spalte 15 enthalt die Hochsttemperatur des Tages (z.B. 12.7)
# und Spalte 16 enthalt die Tiefsttemperatur des Tages (z.B. -2.3). Fehlt ein Messwert, so steht -999 an der Stelle.
# Die Ausgabe geht auf standard output. Sie enthalt fur jedes Jahr eine Zeile mit dem Jahr (z.B 1899)
# und den Werten von Spalte n fur dieses Jahr. Zwischen zwei Eintragen in einer Zeile steht ein ' '.
# Fehl-Eintrage (-999) werden nicht ausgegeben.
#-------------------------------------------------------------------------------------------------------------------------
import sys
n = int(sys.argv[1]) # n ist der Index der Spalte, die aus der Datei herausgefiltert werden soll.
sys.stdin.readline() # Lies die erste Zeile und ignoriere sie. Sie enthalt nur Informationen uber die Spalten.
jahr = '0' # Die Datei beginnt mit einem Eintrag fur einen Tag in einem Jahr>0.
for zeile in sys.stdin: # Gehe alle weiteren Zeilen von standard input durch.
felder = str.split(zeile, ';') # Trenne die Zeile in ihre Spalten auf.
j = felder[1][0:4] # Das Jahr des Messwerts steht in den ersten vier Zeichen von Spalte 1.
messwert = str.strip(felder[n]) # Der auszugebende Messwert steht in Spalte n. Wir entfernen storende Zeichen daraus.
if messwert=='-999': continue # Falls es ein Fehl-Eintrag ist, dann wird mit dem Eintrag nichts weiter gemacht.
if j != jahr: # Falls das Jahr des Messwerts nicht das Jahr des vorangegangenen Messwerts ist,
print('\n' + j, end='') # dann beginnen wir in der Ausgabe eine neue Zeile mit dem Jahr.
jahr = j
print(' ' + messwert, end='') # Schließlich wird ein Leerzeichen gefolgt vom Messwert ausgegeben (ohne Zeilenumbr.).
Durchschnittstemperaturen berechnen – Teil 1 1.5.25
Die Hochsttemperaturen der vergangenen Jahre . . .
python3 filter-DWD.py 15 < Jena-Wetterdaten.txt
1824 5.5 6.5 5.0 2.3 3.0 ... 6.3 10.1 8.8 3.4 7.0
1825 9.1 9.4 5.3 7.9 -0.3 ... -2.8 0.3 4.0 6.1 7.9
...
...
2018 11.5 7.4 10.3 9.4 9.4 ... 5.7 9.7 4.7 7.5 8.3 8.6
. . . und die Niederschlagmengen:
python3 filter-DWD.py 6 < Jena-Wetterdaten.txt
1826 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1827 0.1 0.5 0.1 0.0 1.4 0.8 0.0 1.6 0.6 1.6 1.5 9.8 ... 0.0 0.0 0.4 1.2 0.0 0.0
...
...
2018 1.2 6.4 2.5 1.2 0.2 6.4 1.0 0.0 0.1 0.0 0.2 1.1 ... 0.1 0.0 0.1 4.5 0.0 0.5
Durchschnittstemperaturen berechnen – Teil 1 1.5.26
Teil 2: Berechnung der Durchschnittswerte pro Jahres-Zeile jahres-mittel.py
Das Programm soll die Ausgabe von filter-DWD.py zeilenweise lesen.
Jede Zeile besteht aus dem Jahr gefolgt von den Messwerten,jeweils durch ein Leerzeichen getrennt.
zeile = '1825 2.1 4.4 0.0 1.6 -4.8 ... 1.3 -0.9 -3.1 -1.3 -10.6 -8.4'
Mit str.split(zeile, ' ') machen wir daraus ein Array felder:
[ '1825', '2.1', '4.4', ...'-3.1', '-1.3', '-10.6', '-8.4' ]
felder[0] ist dann das Jahr,und felder[1], felder[2], ... sind die Werte, deren Mittelwert berechnet wird.
Die Ausgabe soll dann aus Zeilen mit Jahr und Mittelwert bestehen:
1824 13.50
1825 13.38
1826 13.27
1827 12.92
1828 13.07
... Durchschnittstemperaturen berechnen – Teil 1 1.5.27
# jahres-mittel.py
#------------------------------------------------------------------------------------------------------------------------
# Es wird von standard input eine Datei aus Zeilen erwartet,
# die mit einer Jahreszahl beginnen, auf die die Messwerte des Jahres folgen.
# Die Eintrage in jeder Zeile sind durch ' ' getrennt. (Das ist das Format, das von filter-DWD.py erzeugt wird.)
# Die Ausgabe auf standard output besteht aus Zeilen mit # der Jahreszahl und dem Durchschnitt der Messwerte des Jahres.
#------------------------------------------------------------------------------------------------------------------------
import sys
# Lies alle Zeilen von standard input.
for zeile in sys.stdin:
# Ignoriere Leerzeilen (die Ausgabe von filter-DWD.py beginnt mit einer Leerzeile).
if zeile == '\n': continue
# Teile die Zeile am Trennzeichen ' ' in ein Array felder auf.
# Das Jahr steht dann in felder[0]; die Messwerte stehen in felder[1], ... , felder[len(felder)-1], d.h. in felder[1:]
felder = str.split(zeile, ' ')
# Jahre mit zuwenig Messwerten werden aussortiert.
if len(felder)<360: continue
# Die Durchschnittsberechnung der Messwerte des Jahres wird vorbereitet.
summe = 0.0
# Die Summe der Messwerte des Jahres wird berechnet.
for s in felder[1:]:
summe += float(s)
# Das Jahr und der Mittelwert der Messwerte des Jahres werden ausgegeben.
print( '%s %.2f' % (felder[0], summe/(len(felder)-1)) )
#------------------------------------------------------------------------------------------------------------------------
Durchschnittstemperaturen berechnen – Teil 1 1.5.28
Die durchschnittlichen Hochsttemperaturen:
python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | python3 jahres-mittel.py
1824 13.50
1825 13.38
1826 13.27
1827 12.92
...
2015 16.42
2016 15.60
2017 15.85
2018 16.94Die durchschnittlichen Tiefsttemperaturen:
python3 filter-DWD.py 16 < Jena-Wetterdaten.txt | python3 jahres-mittel.py
1824 3.59
1825 5.39
1826 5.19
...
2015 6.28
2016 6.23
2017 6.40
2018 6.53
Durchschnittstemperaturen berechnen – Teil 1 1.5.29
Die durchschnittlichen Hochsttemperaturen:
python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | python3 jahres-mittel.py
1824 13.50
1825 13.38
1826 13.27
1827 12.92
...
2015 16.42
2016 15.60
2017 15.85
2018 16.94Die durchschnittlichen Tiefsttemperaturen:
python3 filter-DWD.py 16 < Jena-Wetterdaten.txt | python3 jahres-mittel.py
1824 3.59
1825 5.39
1826 5.19
...
2015 6.28
2016 6.23
2017 6.40
2018 6.53
Durchschnittstemperaturen berechnen – Teil 1 1.5.29
Teil 3: Berechnung der k-Jahre Durchschnittswerte kjahres-mittel.py
Das Programm soll die Ausgabe von jahres-durchschnitte.py zeilenweise lesen.
Jede Zeile besteht aus dem Jahr gefolgt von dem Durchschnittswertdurch ein Leerzeichen getrennt.
1824 13.50
1825 13.38
1826 13.27
1827 12.92
1828 13.07
1829 13.23
1830 12.88
...
Durchschnittstemperaturen berechnen – Teil 1 1.5.30
Wir betrachten die Idee zur Berechnung von 4-Jahres-Durchschnitten.Wir benutzen 4-stellige Arrays werte und int-Variable letzter.werte enthalt die Daten der letzten 4 Jahre,und letzter ist der Index des letzten Jahres in den beiden Arrays.Am Anfang wird das Array mit den Werten der ersten 4 Jahren gefullt.
Index 0 1 2 3
Jahr 1824 1825 1826 1827
werte 13.50 13.38 13.27 12.92
letzter: 3
Daraus kann der 4-Jahres-Durchschnitt fur 1827 berechnet werden.
Durchschnittstemperaturen berechnen – Teil 1 1.5.31
Wir betrachten die Idee zur Berechnung von 4-Jahres-Durchschnitten.Wir benutzen 4-stellige Arrays werte und int-Variable letzter.werte enthalt die Daten der letzten 4 Jahre,und letzter ist der Index des letzten Jahres in den beiden Arrays.Am Anfang wird das Array mit den Werten der ersten 4 Jahren gefullt.
Index 0 1 2 3
Jahr 1824 1825 1826 1827
werte 13.50 13.38 13.27 12.92
letzter: 3
Daraus kann der 4-Jahres-Durchschnitt fur 1827 berechnet werden.
Fur 1828 braucht man den Wert von 1824 nicht mehr.Man setzt letzter eins hoher (modulo 4)und schreibt den Wert von 1828 an die Stelle mit Index letzter.Damit ist der Wert von 1824 uberschrieben.
Index 0 1 2 3
jahre 1828 1825 1826 1827
werte 13.07 13.38 13.27 12.92
letzter: 0
Daraus kann der 4-Jahres-Durchschnitt fur 1828 berechnet werden.
Durchschnittstemperaturen berechnen – Teil 1 1.5.31
Fur 1828 braucht man den Wert von 1824 nicht mehr.Man setzt letzter eins hoher (modulo 4)und schreibt den Wert von 1828 an die Stelle mit Index letzter.Damit ist der Wert von 1824 uberschrieben.
Index 0 1 2 3
jahre 1828 1825 1826 1827
werte 13.07 13.38 13.27 12.92letzter: 0
Daraus kann der 4-Jahres-Durchschnitt fur 1828 berechnet werden.
Fur 1829 braucht man den Wert von 1825 nicht mehr.Man setzt letzter eins hoher (modulo 4)und schreibt den Wert von 1829 an die Stelle mit Index letzter.Damit ist der Wert von 1825 uberschrieben.
Index 0 1 2 3
jahre 1828 1829 1826 1827
werte 13.07 10.47 13.27 12.92letzter: 1
Daraus kann der 4-Jahres-Durchschnitt fur 1829 berechnet werden.
Durchschnittstemperaturen berechnen – Teil 1 1.5.31
Fur 1829 braucht man den Wert von 1825 nicht mehr.Man setzt letzter eins hoher (modulo 4)und schreibt den Wert von 1829 an die Stelle mit Index letzter.Damit ist der Wert von 1825 uberschrieben.
Index 0 1 2 3
jahre 1828 1829 1826 1827
werte 13.07 10.47 13.27 12.92letzter: 1
Daraus kann der 4-Jahres-Durchschnitt fur 1829 berechnet werden.
Fur 1830 braucht man den Wert von 1826 nicht mehr.Man setzt letzter eins hoher (modulo 4)und schreibt den Wert von 1830 an die Stelle mit Index letzter.Damit ist der Wert von 1826 uberschrieben.
Index 0 1 2 3
jahre 1828 1829 1830 1827
werte 13.07 10.47 12.25 12.92letzter: 2
Daraus kann der 4-Jahres-Durchschnitt fur 1830 berechnet werden.
Durchschnittstemperaturen berechnen – Teil 1 1.5.31
Fur 1830 braucht man den Wert von 1826 nicht mehr.Man setzt letzter eins hoher (modulo 4)und schreibt den Wert von 1830 an die Stelle mit Index letzter.Damit ist der Wert von 1826 uberschrieben.
Index 0 1 2 3
jahre 1828 1829 1830 1827
werte 13.07 10.47 12.25 12.92letzter: 2
Daraus kann der 4-Jahres-Durchschnitt fur 1830 berechnet werden.
Fur 1831 braucht man den Wert von 1827 nicht mehr.Man setzt letzter eins hoher (modulo 4)und schreibt den Wert von 1831 an die Stelle mit Index letzter.Damit ist der Wert von 1827 uberschrieben.
Index 0 1 2 3
jahre 1828 1829 1830 1831
werte 13.07 10.47 12.25 13.37letzter: 3
Daraus kann der 4-Jahres-Durchschnitt fur 1830 berechnet werden.
Durchschnittstemperaturen berechnen – Teil 1 1.5.31
Fur 1831 braucht man den Wert von 1827 nicht mehr.Man setzt letzter eins hoher (modulo 4)und schreibt den Wert von 1831 an die Stelle mit Index letzter.Damit ist der Wert von 1827 uberschrieben.
Index 0 1 2 3
jahre 1828 1829 1830 1831
werte 13.07 10.47 12.25 13.37letzter: 3
Daraus kann der 4-Jahres-Durchschnitt fur 1830 berechnet werden.
Fur 1832 braucht man den Wert von 1828 nicht mehr.Man setzt letzter eins hoher (modulo 4)und schreibt den Wert von 1832 an die Stelle mit Index letzter.Damit ist der Wert von 1828 uberschrieben.
Index 0 1 2 3
jahre 1832 1829 1830 1831
werte 12.42 10.47 12.25 13.37letzter: 0
Daraus kann der 4-Jahres-Durchschnitt fur 1830 berechnet werden.
. . .Durchschnittstemperaturen berechnen – Teil 1 1.5.31
# kjahres-mittel.py
#------------------------------------------------------------------------------------------------------------------------
# Von der Kommandozeile wird int k eingelesen.
# Es wird von standard input eine Datei aus Zeilen erwartet, die aus einer Jahreszahl und einem float Messwert bestehen.
# Die Ausgabe auf standard output
# besteht aus Zeilen mit der Jahreszahl und dem Durchschnitt der Messwerte der k vorigen Jahre.
#------------------------------------------------------------------------------------------------------------------------
import sys
k = int(sys.argv[1])
# Wir benutzen werte als Ringpuffer fur die letzten k Jahres-Werte.
werte = [0]*k
# Am Anfang wird der Ringpuffer mit den ersten k-1 Werten gefullt.
for i in range(k-1):
zeile = sys.stdin.readline()
felder = str.split(zeile,' ')
werte[i] = float(felder[1])
# letzter speichert den Index des letzten Eintrages.
letzter = k-2
# Gehe durch alle Zeilen von standard input.
for zeile in sys.stdin:
# zeile wird fur den nachsten Eintrag in den Ringpuffern "auseinandergenommen".
felder = str.split(zeile,' ')
jahr = felder[0]
letzter = (letzter+1)%k
werte[letzter] = float(felder[1])
# Das Jahr und der Mittelwert der letzten k Jahre werden ausgegeben.
print( '%s %.2f' % (jahr, sum(werte)/k) )
Durchschnittstemperaturen berechnen – Teil 1 1.5.32
# python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | python3 jahres-mittel.py | python3 kjahres-mittel.py 9
1832 11.35
1833 11.33
1834 11.48
1835 11.48
1836 11.45
1837 11.56
1838 11.40
...
2011 15.29
2012 15.27
2013 15.22
2014 15.36
2015 15.45
2016 15.40
2017 15.43
2018 15.64
Durchschnittstemperaturen berechnen – Teil 1 1.5.33
Zusammenfassungstandard input und standard output
Wir haben gesehen, wie Daten
§ von der Tastatur eingelesen undauf dem Bildschirm ausgegeben werden konnen
§ aus Dateien eingelesen und in Dateien geschrieben werden konnen(Eingabeumleitung < bzw. open(dateiname, 'r'); Ausgabeumleitung > bzw. open(dateiname, 'w') etc.)
§ als Ausgabe eines Programms weitergereicht und als Eingabe eines anderen Programmsbenutzt werden konnen (Piping |).
Wir haben gesehen, wie eine großere Aufgabein kleinere und einfachere Aufgaben aufgeteilt werden kann.
Die kleineren Aufgaben sind unabhangig voneinander.Jede Aufgabe hat ein festes Format fur die Eingabe- und Ausgabe-Daten.
1.5.34
Vorlesung 06
1. Elemente des Programmierens
1.2 Grundlegende Daten-Typen
1.3 Verzweigungen und Schleifen
1.4 Arrays
1.5 Ein- und Ausgabestandard output
standard input
standard drawing
1.6 Dictionaries und Abschluss-Beispiel Page Rank
1.5.35
1.5.3 Graphische Ausgabe mit stddraw
Das Modul stddraw.py bietet einfache Mittel zur graphischen Ausgabe.
Damit konnen z.B. Graphiken gemalt oder bewegte Bilder dargestellt werden.
python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | \
python3 jahres-mittel.py | \
python3 kjahres-mittel.py 30 | \
python3 male-kurve-mit-achsen.py 1830 2022 0 20
python3 kugel-3.py 2 0.05 0.095
1.5.36
Graphische Ausgabe mit dem Modul stddraw (standard drawing)
Das Modul stddraw ermoglicht das Malen auf eine”abstrakte“ Leinwand aus Punkten
(Standardgroße 512ˆ 512 Pixel).
p0, 0q
p1, 1q
x-Achse
y-A
chse
‚
Jeder Punkt auf der Leinwand hat Koordinaten px , yq mit Standard 0 ď x , y ď 1.
Es konnen Punkte, Linien, Kreise, Rechtecke etc. gemalt werden.
Die Koordinaten der Eckpunkte der Leinwand konnen verandert werden . . .
stddraw – Einfuhrung 1.5.37
Graphische Ausgabe mit dem Modul stddraw (standard drawing)
Das Modul stddraw ermoglicht das Malen auf eine”abstrakte“ Leinwand aus Punkten
(Standardgroße 512ˆ 512 Pixel).
p0, 0q
p1, 1q
x-Achse
y-A
chse
‚
p0.5, 0.3q
Jeder Punkt auf der Leinwand hat Koordinaten px , yq mit Standard 0 ď x , y ď 1.
Es konnen Punkte, Linien, Kreise, Rechtecke etc. gemalt werden.
Die Koordinaten der Eckpunkte der Leinwand konnen verandert werden . . .
stddraw – Einfuhrung 1.5.37
Graphische Ausgabe mit dem Modul stddraw (standard drawing)
Das Modul stddraw ermoglicht das Malen auf eine”abstrakte“ Leinwand aus Punkten
(Standardgroße 512ˆ 512 Pixel).
p´2.5, 3.2q
p2, 5q
x-Achse
y-A
chse
‚
p0.25, 3.74q
Jeder Punkt auf der Leinwand hat Koordinaten px , yq mit Standard 0 ď x , y ď 1.
Es konnen Punkte, Linien, Kreise, Rechtecke etc. gemalt werden.Die Koordinaten der Eckpunkte der Leinwand konnen verandert werden . . .
stddraw – Einfuhrung 1.5.37
Zeichne ein Dreieck
Aufgabe:Zeichne ein Dreieck mit den Eckpunkten p0, 0q, p1, 0q, und p0.5,
?3.0{2q,
und zeichne einen Punkt in die Mitte des Dreiecks.
Wir mussen also die Linienvon p0, 0q nach p1, 0q,von p1, 0q nach p0.5,
?3.0{2q, und
von p0.5,?
3.0{2q nach p0, 0qund einen Punkt p0.5,
?3.0{6q zeichnen und das gemalte Bild anzeigen.
Das geht mit folgenden stddraw-Funktionen.
stddraw.line(x0, y0, x1, y1) male eine Linie von px0, y0q zu px1, y1q
stddraw.point(x, y) male einen Punkt an px , yq
stddraw.show(t) zeige das Bild im standard-drawing-Fenster und
warte t Millisekunden;
falls t weggelassen wird, dann
warte, bis das Fenster vom Nutzer geschlossen wirdstddraw – Einfuhrung 1.5.38
#--------------------------------------------------------------------
# dreieck.py
#--------------------------------------------------------------------
# Zeichne mit stddraw ein Dreieck mit den Eckpunkten (0,0), (1,0)
# und (0.5, sqrt(3.0)/2), und einen Punkt in die Mitte des Dreiecks.
#--------------------------------------------------------------------
import math
import stddraw
t = math.sqrt(3.0)/2
# Male eine Linie von (0,0) nach (1,0).
stddraw.line(0, 0, 1, 0)
# Male eine Linie von (0,0) nach (0.5,t).
stddraw.line(0.0, 0.0, 0.5, t)
# Male eine Linie von (0.5,t) nach (1,0).
stddraw.line(0.5, t, 1, 0)
# Male einen Punkt an (0.5, t/3).
stddraw.point(0.5, t/3)
# Zeige das Bild an.
stddraw.show()
#--------------------------------------------------------------------
# python3 dreieck.py
$ python3 dreieck.py
stddraw – Einfuhrung 1.5.39
#--------------------------------------------------------------------
# dreieck.py
#--------------------------------------------------------------------
# Zeichne mit stddraw ein Dreieck mit den Eckpunkten (0,0), (1,0)
# und (0.5, sqrt(3.0)/2), und einen Punkt in die Mitte des Dreiecks.
#--------------------------------------------------------------------
import math
import stddraw
t = math.sqrt(3.0)/2
# Male eine Linie von (0,0) nach (1,0).
stddraw.line(0, 0, 1, 0)
# Male eine Linie von (0,0) nach (0.5,t).
stddraw.line(0.0, 0.0, 0.5, t)
# Male eine Linie von (0.5,t) nach (1,0).
stddraw.line(0.5, t, 1, 0)
# Male einen Punkt an (0.5, t/3).
stddraw.point(0.5, t/3)
# Zeige das Bild an.
stddraw.show()
#--------------------------------------------------------------------
# python3 dreieck.py
$ python3 dreieck.py
stddraw – Einfuhrung 1.5.39
Anderung von StandardwertenLeinwandgroße, Skalierung der Achsen, Stiftdicke, Stiftfarbe
Leinwandgroße:
stddraw.setCanvasSize(w, h) setze die Leinwandgroße auf w -mal-h Pixel
(Default fur w (Breite) und h (Hohe) ist 512)
Skalierung der Achsen:
stddraw.setXscale(x0, x1) setze den Bereich der x-Koordinaten auf x0 ď x ď x1
(Default ist x0 “ 0 und x1 “ 1)
stddraw.setYscale(y0, y1) setze den Bereich der y -Koordinaten auf y0 ď y ď y1
(Default ist y0 “ 0 und y1 “ 1)
Stiftdicke und -farbe:
stddraw.setPenRadius(r) setze die Stiftdicke auf r
(Default-Wert von r ist 0.005)
stddraw.setPenColor(c) setzt die Farbe des Stiftes auf c; c kann z.B. stddraw.BLUE sein
mit Farben BLACK, BLUE, CYAN, DARK GRAY, GRAY, GREEN, LIGHT GRAY, MAGENTA, ORANGE, PINK, RED, WHITE, YELLOWstddraw – Einfuhrung 1.5.40
#--------------------------------------------------------------------------------------------------
# dreieck-bunt.py
#--------------------------------------------------------------------------------------------------
# Zeichne das Dreieck mit dem Punkt wie in dreieck.py.
# Verandere die Standardparameter Leinwandgroße, Skalierung der Achsen, Stiftdicke und Stiftfarbe.
#--------------------------------------------------------------------------------------------------
import math, stddraw
# Setze die Leinwandgroße und die Skalierung der Achsen.
stddraw.setCanvasSize(800,800) # Leinwandgroße
stddraw.setXscale(-0.3,1.3) # Skalierung der x-Achse
stddraw.setYscale(-0.3,1.3) # Skalierung der y-Achse
stddraw.setPenRadius(0.01) # andere die Stiftdicke
stddraw.line(0, 0, 1, 0) # male die Linie von (0,0) nach (1,0)
t = math.sqrt(3.0)/2
stddraw.setPenColor(stddraw.BLUE) # andere die Stiftfarbe
stddraw.line(0, 0, 0.5, t) # male die Linie von (0,0) nach (0.5,t)
stddraw.setPenRadius(0.05) # andere die Stiftdicke
stddraw.setPenColor(stddraw.RED) # andere die Stiftfarbe
stddraw.line(0.5, t, 1, 0) # male die Linie von (0.5,t) nach (1,0)
stddraw.setPenRadius(0.1) # andere die Stiftdicke
stddraw.setPenColor(stddraw.CYAN) # andere die Stiftfarbe
stddraw.point(0.5, t/3) # male einen Punkt an (0.5, t/3)
stddraw.show() # zeige das Bild an
$ python3 dreieck-bunt.py
stddraw – Einfuhrung 1.5.41
#--------------------------------------------------------------------------------------------------
# dreieck-bunt.py
#--------------------------------------------------------------------------------------------------
# Zeichne das Dreieck mit dem Punkt wie in dreieck.py.
# Verandere die Standardparameter Leinwandgroße, Skalierung der Achsen, Stiftdicke und Stiftfarbe.
#--------------------------------------------------------------------------------------------------
import math, stddraw
# Setze die Leinwandgroße und die Skalierung der Achsen.
stddraw.setCanvasSize(800,800) # Leinwandgroße
stddraw.setXscale(-0.3,1.3) # Skalierung der x-Achse
stddraw.setYscale(-0.3,1.3) # Skalierung der y-Achse
stddraw.setPenRadius(0.01) # andere die Stiftdicke
stddraw.line(0, 0, 1, 0) # male die Linie von (0,0) nach (1,0)
t = math.sqrt(3.0)/2
stddraw.setPenColor(stddraw.BLUE) # andere die Stiftfarbe
stddraw.line(0, 0, 0.5, t) # male die Linie von (0,0) nach (0.5,t)
stddraw.setPenRadius(0.05) # andere die Stiftdicke
stddraw.setPenColor(stddraw.RED) # andere die Stiftfarbe
stddraw.line(0.5, t, 1, 0) # male die Linie von (0.5,t) nach (1,0)
stddraw.setPenRadius(0.1) # andere die Stiftdicke
stddraw.setPenColor(stddraw.CYAN) # andere die Stiftfarbe
stddraw.point(0.5, t/3) # male einen Punkt an (0.5, t/3)
stddraw.show() # zeige das Bild an
$ python3 dreieck-bunt.py
stddraw – Einfuhrung 1.5.41
Graphische Darstellung der Jenaer Jahresdurchschnittstemperaturen (Teil 1)
python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | python3 jahres-mittel.py
liefert Ausgabe
1824 13.50
1825 13.38
1826 13.27
1827 12.92
1828 13.07
1829 10.47
...
stddraw – Messwerte als Punkte darstellen 1.5.42
Graphische Darstellung der Jenaer Jahresdurchschnittstemperaturen (Teil 1)
python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | python3 jahres-mittel.py
liefert Ausgabe
1824 13.50
1825 13.38
1826 13.27
1827 12.92
1828 13.07
1829 10.47
...
Aufgabe: Wir fassen jede Zeile als x- und y -Wert eines Punktes aufund wollen alle diese Punkte zeichnen.
Die x-Koordinaten sind im Bereich 1824 . . . 2018,
und die y -Koordinaten sind im Bereich 0 . . . 20.
stddraw – Messwerte als Punkte darstellen 1.5.42
Graphische Darstellung der Jenaer Jahresdurchschnittstemperaturen (Teil 1)
Aufgabe: Wir fassen jede Zeile als x- und y -Wert eines Punktes aufund wollen alle diese Punkte zeichnen.
Die x-Koordinaten sind im Bereich 1824 . . . 2018,und die y -Koordinaten sind im Bereich 0 . . . 20.
Das Programm soll fur unterschiedliche”Punktarten“ arbeiten (Hochst-, Tiefsttemperatur, . . . )
Ablauf des Programms:
Lies den Bereich der x- und y -Koordinaten von der Kommandozeile.Lies alle Punkte von standard input,
male sie auf die Leinwandund zeige die Leinwand an.
stddraw – Messwerte als Punkte darstellen 1.5.42
Grundsatzliche Alternativen fur”Lies alle Punkte von standard input,
und male sie auf die Leinwand“
(A) Male jeden Punkt direkt nach dem Einlesen.
fur jede Eingabezeile (Zeile “Punkt):bestimme den entsprechenden Punktmale ihn
(B) zuerst: lies alle Punkte einund speichere sie
danach: male jeden Punkt
fur jede Eingabezeile (Zeile “Punkt):speichere den entsprechenden Punkt
fur jeden gespeicherten Punkt:male ihn
stddraw – Messwerte als Punkte darstellen 1.5.43
Grundsatzliche Alternativen fur”Lies alle Punkte von standard input,
und male sie auf die Leinwand“
(A) Male jeden Punkt direkt nach dem Einlesen.
fur jede Eingabezeile (Zeile “Punkt):bestimme den entsprechenden Punktmale ihn
(B) zuerst: lies alle Punkte einund speichere sie
danach: male jeden Punkt
fur jede Eingabezeile (Zeile “Punkt):speichere den entsprechenden Punkt
fur jeden gespeicherten Punkt:male ihn
stddraw – Messwerte als Punkte darstellen 1.5.43
Grundsatzliche Alternativen fur”Lies alle Punkte von standard input,
und male sie auf die Leinwand“
(A) Male jeden Punkt direkt nach dem Einlesen.
fur jede Eingabezeile (Zeile “Punkt):bestimme den entsprechenden Punktmale ihn
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
x_wert = float(punkt[0])
y_wert = float(punkt[1])
stddraw.point(x_wert,y_wert)
(B) zuerst: lies alle Punkte einund speichere sie
danach: male jeden Punkt
fur jede Eingabezeile (Zeile “Punkt):speichere den entsprechenden Punkt
fur jeden gespeicherten Punkt:male ihn
stddraw – Messwerte als Punkte darstellen 1.5.43
Grundsatzliche Alternativen fur”Lies alle Punkte von standard input,
und male sie auf die Leinwand“
(A) Male jeden Punkt direkt nach dem Einlesen.
fur jede Eingabezeile (Zeile “Punkt):bestimme den entsprechenden Punktmale ihn
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
x_wert = float(punkt[0])
y_wert = float(punkt[1])
stddraw.point(x_wert,y_wert)
(B) zuerst: lies alle Punkte einund speichere sie
danach: male jeden Punkt
fur jede Eingabezeile (Zeile “Punkt):speichere den entsprechenden Punkt
fur jeden gespeicherten Punkt:male ihn
stddraw – Messwerte als Punkte darstellen 1.5.43
Grundsatzliche Alternativen fur”Lies alle Punkte von standard input,
und male sie auf die Leinwand“
(A) Male jeden Punkt direkt nach dem Einlesen.
fur jede Eingabezeile (Zeile “Punkt):bestimme den entsprechenden Punktmale ihn
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
x_wert = float(punkt[0])
y_wert = float(punkt[1])
stddraw.point(x_wert,y_wert)
(B) zuerst: lies alle Punkte einund speichere sie
danach: male jeden Punkt
fur jede Eingabezeile (Zeile “Punkt):speichere den entsprechenden Punkt
fur jeden gespeicherten Punkt:male ihn
xwerte = []
ywerte = []
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
xwerte += [ float(punkt[0]) ]
ywerte += [ float(punkt[1]) ]
# Der i-te Punkt ist (xwerte[i],ywerte[i]).
for i in range(len(xwerte)):
stddraw.point(xwerte[i],ywerte[i])stddraw – Messwerte als Punkte darstellen 1.5.43
#-----------------------------------------------------------------------------------------
# male-punkte.py
#-----------------------------------------------------------------------------------------
# Lies x0, x1, y0 und y1 von der Kommandozeile. Lies Wertepaare x,y von standard input
# und male sie als Punkte auf eine Leinwand mit x-Achse x0..x1 und y-Achse y0..y1.
#-----------------------------------------------------------------------------------------
import sys, stddraw
# Richte die Achsen der Leinwand ein und bereite den Stift vor.
stddraw.setXscale(float(sys.argv[1]), float(sys.argv[2]))
stddraw.setYscale(float(sys.argv[3]), float(sys.argv[4]))
stddraw.setPenRadius(0.01)
# Standard input liefert zeilenweise x- und y-Werte von Punkten.
# Jeder dieser Punkte wird gemalt, die Leinwand wird angezeigt,
# und anschließend wird ein bisschen gewartet.
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
x_wert = float(punkt[0])
y_wert = float(punkt[1])
stddraw.point(x_wert, y_wert)
stddraw.show(30)
stddraw.show()
#-----------------------------------------------------------------------------------------# python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | python3 jahres-mittel.py | python3 male-punkte.py 1820 2020 -1 20
#
# python3 filter-DWD.py 16 < Jena-Wetterdaten.txt | python3 jahres-mittel.py | python3 male-punkte.py 1820 2020 -8 12
stddraw – Messwerte als Punkte darstellen 1.5.44
#-----------------------------------------------------------------------------------------
# male-punkte.py
#-----------------------------------------------------------------------------------------
# Lies x0, x1, y0 und y1 von der Kommandozeile. Lies Wertepaare x,y von standard input
# und male sie als Punkte auf eine Leinwand mit x-Achse x0..x1 und y-Achse y0..y1.
#-----------------------------------------------------------------------------------------
import sys, stddraw
# Richte die Achsen der Leinwand ein und bereite den Stift vor.
stddraw.setXscale(float(sys.argv[1]), float(sys.argv[2]))
stddraw.setYscale(float(sys.argv[3]), float(sys.argv[4]))
stddraw.setPenRadius(0.01)
# Standard input liefert zeilenweise x- und y-Werte von Punkten.
# Jeder dieser Punkte wird gemalt, die Leinwand wird angezeigt,
# und anschließend wird ein bisschen gewartet.
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
x_wert = float(punkt[0])
y_wert = float(punkt[1])
stddraw.point(x_wert, y_wert)
stddraw.show(30)
stddraw.show()
#-----------------------------------------------------------------------------------------# python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | python3 jahres-mittel.py | python3 male-punkte.py 1820 2020 -1 20
#
# python3 filter-DWD.py 16 < Jena-Wetterdaten.txt | python3 jahres-mittel.py | python3 male-punkte.py 1820 2020 -8 12
stddraw – Messwerte als Punkte darstellen 1.5.44
#-----------------------------------------------------------------------------------------
# male-punkte.py
#-----------------------------------------------------------------------------------------
# Lies x0, x1, y0 und y1 von der Kommandozeile. Lies Wertepaare x,y von standard input
# und male sie als Punkte auf eine Leinwand mit x-Achse x0..x1 und y-Achse y0..y1.
#-----------------------------------------------------------------------------------------
import sys, stddraw
# Richte die Achsen der Leinwand ein und bereite den Stift vor.
stddraw.setXscale(float(sys.argv[1]), float(sys.argv[2]))
stddraw.setYscale(float(sys.argv[3]), float(sys.argv[4]))
stddraw.setPenRadius(0.01)
# Standard input liefert zeilenweise x- und y-Werte von Punkten.
# Jeder dieser Punkte wird gemalt, die Leinwand wird angezeigt,
# und anschließend wird ein bisschen gewartet.
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
x_wert = float(punkt[0])
y_wert = float(punkt[1])
stddraw.point(x_wert, y_wert)
stddraw.show(30)
stddraw.show()
#-----------------------------------------------------------------------------------------# python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | python3 jahres-mittel.py | \
# python3 kjahres-mittel.py 9 | python3 male-punkte.py 1820 2020 -1 20
#
# python3 filter-DWD.py 16 < Jena-Wetterdaten.txt | python3 jahres-mittel.py | \
# python3 kjahres-mittel.py 9 | python3 male-punkte.py 1820 2020 -8 12stddraw – Messwerte als Punkte darstellen 1.5.44
#-----------------------------------------------------------------------------------------
# male-punkte.py
#-----------------------------------------------------------------------------------------
# Lies x0, x1, y0 und y1 von der Kommandozeile. Lies Wertepaare x,y von standard input
# und male sie als Punkte auf eine Leinwand mit x-Achse x0..x1 und y-Achse y0..y1.
#-----------------------------------------------------------------------------------------
import sys, stddraw
# Richte die Achsen der Leinwand ein und bereite den Stift vor.
stddraw.setXscale(float(sys.argv[1]), float(sys.argv[2]))
stddraw.setYscale(float(sys.argv[3]), float(sys.argv[4]))
stddraw.setPenRadius(0.01)
# Standard input liefert zeilenweise x- und y-Werte von Punkten.
# Jeder dieser Punkte wird gemalt, die Leinwand wird angezeigt,
# und anschließend wird ein bisschen gewartet.
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
x_wert = float(punkt[0])
y_wert = float(punkt[1])
stddraw.point(x_wert, y_wert)
stddraw.show(30)
stddraw.show()
#-----------------------------------------------------------------------------------------# python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | python3 jahres-mittel.py | \
# python3 kjahres-mittel.py 9 | python3 male-punkte.py 1820 2020 -1 20
#
# python3 filter-DWD.py 16 < Jena-Wetterdaten.txt | python3 jahres-mittel.py | \
# python3 kjahres-mittel.py 9 | python3 male-punkte.py 1820 2020 -8 12stddraw – Messwerte als Punkte darstellen 1.5.44
Graphische Darstellung der Jenaer Jahresdurchschnittstemperaturen (Teil 2)
Nun wollen wir noch aufeinanderfolgende Punkte mit einem Strich verbinden,
damit es eine schone Kurve gibt,
Ablauf des Programms:
lies alle Punkte ein
fur alle aufeinanderfolgenden Punkte:
male einen Strich mit ihnen als Endpunkte
und danach werden wir noch Achsen mit Skalen malen.
stddraw – Messwerte als Kurve darstellen 1.5.45
#----------------------------------------------------------------------------------------------------------
# male-kurve.py
#----------------------------------------------------------------------------------------------------------
# Lies x0, x1, y0 und y1 von der Kommandozeile. Lies Wertepaare x,y von standard input und male sie
# als mit Strichen verbundene Punkte auf eine Leinwand mit x-Achse x0..x1 und y-Achse y0..y1.
#----------------------------------------------------------------------------------------------------------
import sys, stddraw
# Bereite die Leinwand und den Stift vor.
# Die Skalenbereiche der Achsen werden von der Kommandozeile gelesen.
stddraw.setXscale(float(sys.argv[1]), float(sys.argv[2]))
stddraw.setYscale(float(sys.argv[3]), float(sys.argv[4]))
stddraw.setPenRadius(0.04)
# Wir lesen zuerst alle Punkte von standard input und schreiben
# alle x-Werte in ein Array x[], und alle y-Werte in ein Array y[].
# Dann ist (x[i],y[i]) jeweils ein Punkt.
xwerte = []
ywerte = []
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
xwerte += [ float(punkt[0]) ]
ywerte += [ float(punkt[1]) ]
# Wir zeichnen jeweils eine Linie zwischen zwei aufeinanderfolgenden Punkten.
# Da der letzte Punkt keinen "Nachfolger" hat, ist er kein Startpunkt einer Linie.
for i in range(len(xwerte)-1):
stddraw.line( xwerte[i], ywerte[i], xwerte[i+1], ywerte[i+1] )
stddraw.show() # Zeige das Bild an.stddraw – Messwerte als Kurve darstellen 1.5.46
#----------------------------------------------------------------------------------------------------------
# male-kurve.py
#----------------------------------------------------------------------------------------------------------
# Lies x0, x1, y0 und y1 von der Kommandozeile. Lies Wertepaare x,y von standard input und male sie
# als mit Strichen verbundene Punkte auf eine Leinwand mit x-Achse x0..x1 und y-Achse y0..y1.
#----------------------------------------------------------------------------------------------------------
import sys, stddraw
# Bereite die Leinwand und den Stift vor.
# Die Skalenbereiche der Achsen werden von der Kommandozeile gelesen.
stddraw.setXscale(float(sys.argv[1]), float(sys.argv[2]))
stddraw.setYscale(float(sys.argv[3]), float(sys.argv[4]))
stddraw.setPenRadius(0.04)
# Wir lesen zuerst alle Punkte von standard input und schreiben
# alle x-Werte in ein Array x[], und alle y-Werte in ein Array y[].
# Dann ist (x[i],y[i]) jeweils ein Punkt.
xwerte = []
ywerte = []
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
xwerte += [ float(punkt[0]) ]
ywerte += [ float(punkt[1]) ]
# Wir zeichnen jeweils eine Linie zwischen zwei aufeinanderfolgenden Punkten.
# Da der letzte Punkt keinen "Nachfolger" hat, ist er kein Startpunkt einer Linie.
for i in range(len(xwerte)-1):
stddraw.line( xwerte[i], ywerte[i], xwerte[i+1], ywerte[i+1] )
stddraw.show() # Zeige das Bild an.
python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | \
python3 jahres-mittel.py | \
python3 male-kurve.py 1820 2020 -1 20
stddraw – Messwerte als Kurve darstellen 1.5.46
#----------------------------------------------------------------------------------------------------------
# male-kurve.py
#----------------------------------------------------------------------------------------------------------
# Lies x0, x1, y0 und y1 von der Kommandozeile. Lies Wertepaare x,y von standard input und male sie
# als mit Strichen verbundene Punkte auf eine Leinwand mit x-Achse x0..x1 und y-Achse y0..y1.
#----------------------------------------------------------------------------------------------------------
import sys, stddraw
# Bereite die Leinwand und den Stift vor.
# Die Skalenbereiche der Achsen werden von der Kommandozeile gelesen.
stddraw.setXscale(float(sys.argv[1]), float(sys.argv[2]))
stddraw.setYscale(float(sys.argv[3]), float(sys.argv[4]))
stddraw.setPenRadius(0.04)
# Wir lesen zuerst alle Punkte von standard input und schreiben
# alle x-Werte in ein Array x[], und alle y-Werte in ein Array y[].
# Dann ist (x[i],y[i]) jeweils ein Punkt.
xwerte = []
ywerte = []
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
xwerte += [ float(punkt[0]) ]
ywerte += [ float(punkt[1]) ]
# Wir zeichnen jeweils eine Linie zwischen zwei aufeinanderfolgenden Punkten.
# Da der letzte Punkt keinen "Nachfolger" hat, ist er kein Startpunkt einer Linie.
for i in range(len(xwerte)-1):
stddraw.line( xwerte[i], ywerte[i], xwerte[i+1], ywerte[i+1] )
stddraw.show() # Zeige das Bild an.
python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | \
python3 jahres-mittel.py | \
python3 kjahres-durchschnitte.py 9 | \
python3 male-kurve.py 1820 2020 -1 20
stddraw – Messwerte als Kurve darstellen 1.5.46
Und abschließend zeichnen wir noch beschriftete Achsen dazu.
stddraw – Messwerte als Kurve darstellen 1.5.47
#-----------------------------------------------------------------------------------------
# male-kurve-mit-achsen.py
#-----------------------------------------------------------------------------------------
# Lies xmin, xmax, ymin und ymax von der Kommandozeile.
# Lies Wertepaare x,y von standard input
# und male sie als mit Strichen verbundene Punkte auf eine Leinwand
# mit x-Achse xmin..xmax und y-Achse ymin..ymax.
#-----------------------------------------------------------------------------------------
import sys, stddraw
# Wir lesen die Punkte von standard input.
# Wir schreiben alle x-Werte in ein Array x[], und alle y-Werte in ein Array y[].
# Dann ist (x[i],y[i]) jeweils ein Punkt.
xwerte = []
ywerte = []
for zeile in sys.stdin:
punkt = str.split(zeile, ' ')
xwerte += [ float(punkt[0]) ]
ywerte += [ float(punkt[1]) ]
# Um die Leinwand vorzubereiten,
# lesen wir von der Kommandozeile die Langen der x- und der y-Achse.
xmin = float(sys.argv[1])
xmax = float(sys.argv[2])
ymin = float(sys.argv[3])
ymax = float(sys.argv[4])
# Zum Malen der Achsen und deren Beschriftung brauchen wir an jeder Seite etwas Rand.
stddraw.setXscale(xmin-10, xmax+10)
stddraw.setYscale(ymin-2, ymax+2)
stddraw.setPenRadius(0.04)
# Male die x-Achse und die y-Achse des Koordinatensystems (in blau).
stddraw.setPenColor(stddraw.BLUE)
stddraw.line(xmin,ymin, xmax,ymin)
stddraw.line(xmin,ymin, xmin,ymax)
stddraw – Messwerte als Kurve darstellen 1.5.48
# Male die x-Achse und die y-Achse des Koordinatensystems (in blau).
stddraw.setPenColor(stddraw.BLUE)
stddraw.line(xmin,ymin, xmax,ymin)
stddraw.line(xmin,ymin, xmin,ymax)
# Beschrifte die Achsen des Koordinatensystems.
for i in range(int(ymin), int(ymax+1), int(ymax-ymin)//10): # beschrifte die y-Achse
stddraw.line(xmin-2,i, xmin+2,i) # male einen kleinen waagerechten Strich uber die y-Achse in Hohe i
stddraw.text(xmin-5, i, str(i)) # schreibe i links neben die y-Achse in Hohe i
for i in range(int(xmin), int(xmax+1), int(xmax-xmin)//10): # beschrifte die x-Achse
stddraw.line(i,ymin-0.2, i, ymin+0.2) # male einen kleinen senkrechten Strich an Stelle i der x-Achse
stddraw.text(i, ymin-1, str(i)) # schreibe i etwas unter die x-Achse an Stelle i
# Die Linien zwischen aufeinanderfolgenden (x,y)-Paaren werden gemalt.
stddraw.setPenColor(stddraw.BLACK)
stddraw.setPenRadius(0.06)
for i in range(len(xwerte)-1):
stddraw.line( xwerte[i], ywerte[i], xwerte[i+1], ywerte[i+1] )
stddraw.show(20)
stddraw.show()
#----------------------------------------------------------------------------------
stddraw – Messwerte als Kurve darstellen 1.5.49
# Male die x-Achse und die y-Achse des Koordinatensystems (in blau).
stddraw.setPenColor(stddraw.BLUE)
stddraw.line(xmin,ymin, xmax,ymin)
stddraw.line(xmin,ymin, xmin,ymax)
# Beschrifte die Achsen des Koordinatensystems.
for i in range(int(ymin), int(ymax+1), int(ymax-ymin)//10): # beschrifte die y-Achse
stddraw.line(xmin-2,i, xmin+2,i) # male einen kleinen waagerechten Strich uber die y-Achse in Hohe i
stddraw.text(xmin-5, i, str(i)) # schreibe i links neben die y-Achse in Hohe i
for i in range(int(xmin), int(xmax+1), int(xmax-xmin)//10): # beschrifte die x-Achse
stddraw.line(i,ymin-0.2, i, ymin+0.2) # male einen kleinen senkrechten Strich an Stelle i der x-Achse
stddraw.text(i, ymin-1, str(i)) # schreibe i etwas unter die x-Achse an Stelle i
# Die Linien zwischen aufeinanderfolgenden (x,y)-Paaren werden gemalt.
stddraw.setPenColor(stddraw.BLACK)
stddraw.setPenRadius(0.06)
for i in range(len(xwerte)-1):
stddraw.line( xwerte[i], ywerte[i], xwerte[i+1], ywerte[i+1] )
stddraw.show(20)
stddraw.show()
#----------------------------------------------------------------------------------
# python3 filter-DWD.py 15 < Jena-Wetterdaten.txt | python3 jahres-mittel.py | \
# python3 kjahres-mittel.py 9 | python3 male-kurve-mit-achsen.py 1831 2018 -1 20
#stddraw – Messwerte als Kurve darstellen 1.5.49
# Male die x-Achse und die y-Achse des Koordinatensystems (in blau).
stddraw.setPenColor(stddraw.BLUE)
stddraw.line(xmin,ymin, xmax,ymin)
stddraw.line(xmin,ymin, xmin,ymax)
# Beschrifte die Achsen des Koordinatensystems.
for i in range(int(ymin), int(ymax+1), int(ymax-ymin)//10): # beschrifte die y-Achse
stddraw.line(xmin-2,i, xmin+2,i) # male einen kleinen waagerechten Strich uber die y-Achse in Hohe i
stddraw.text(xmin-5, i, str(i)) # schreibe i links neben die y-Achse in Hohe i
for i in range(int(xmin), int(xmax+1), int(xmax-xmin)//10): # beschrifte die x-Achse
stddraw.line(i,ymin-0.2, i, ymin+0.2) # male einen kleinen senkrechten Strich an Stelle i der x-Achse
stddraw.text(i, ymin-1, str(i)) # schreibe i etwas unter die x-Achse an Stelle i
# Die Linien zwischen aufeinanderfolgenden (x,y)-Paaren werden gemalt.
stddraw.setPenColor(stddraw.BLACK)
stddraw.setPenRadius(0.06)
for i in range(len(xwerte)-1):
stddraw.line( xwerte[i], ywerte[i], xwerte[i+1], ywerte[i+1] )
stddraw.show(20)
stddraw.show()
#----------------------------------------------------------------------------------
# python3 filter-DWD.py 16 < Jena-Wetterdaten.txt | python3 jahres-mittel.py | \
# python3 kjahres-mittel.py 9 | python3 male-kurve-mit-achsen.py 1831 2018 -5 12
#stddraw – Messwerte als Kurve darstellen 1.5.49
Zeichnen des Graphs einer Funktion
Zum Zeichnen des Graphs einer Funktion muss das Programm die Argument-/Wert-Paare,die male-kurve.py von standard input einliest, selbst erzeugen.
Wenn der Graph der Funktion f pxq im Bereich l ď x ď r gezeichnet werden soll,
§ muss man festlegen, wieviele Funktionswerte man im Bereich l ď x ď r berechnen will(das Intervall l . . . r wird in gleichmaßige Abschnitte unterteilt),
Wenn Funktionswerte fur n Argumente im Intervall l ď x ď r berechnet werden sollen,
haben die Argumente Abstand l´rn´1 und sind l , l `1 ¨ r´l
n´1 , l `2 ¨ r´ln´1 , . . . , l ` pn ´ 1q ¨
r ´ l
n ´ 1loooooooooomoooooooooon
“r
.
§ die Argument-Wert-Paare px , f pxqq berechnen und
§ die Funktionswerte aufeinanderfolgender Argumente durch eine Linie verbinden.
Man beachte, dass stets nur eine Naherung berechnet wird,deren Qualitat von der Anzahl der berechneten Funktionswerte abhangt.
stddraw – Graph einer Funktion darstellen 1.5.50
Zeichnen des Graphs einer Funktion
Zum Zeichnen des Graphs einer Funktion muss das Programm die Argument-/Wert-Paare,die male-kurve.py von standard input einliest, selbst erzeugen.
Wenn der Graph der Funktion f pxq im Bereich l ď x ď r gezeichnet werden soll,
§ muss man festlegen, wieviele Funktionswerte man im Bereich l ď x ď r berechnen will(das Intervall l . . . r wird in gleichmaßige Abschnitte unterteilt),
Wenn Funktionswerte fur n Argumente im Intervall l ď x ď r berechnet werden sollen,
haben die Argumente Abstand l´rn´1 und sind l , l `1 ¨ r´l
n´1 , l `2 ¨ r´ln´1 , . . . , l ` pn ´ 1q ¨
r ´ l
n ´ 1loooooooooomoooooooooon
“r
.
§ die Argument-Wert-Paare px , f pxqq berechnen und
§ die Funktionswerte aufeinanderfolgender Argumente durch eine Linie verbinden.
Man beachte, dass stets nur eine Naherung berechnet wird,deren Qualitat von der Anzahl der berechneten Funktionswerte abhangt.
stddraw – Graph einer Funktion darstellen 1.5.50
#-----------------------------------------------------------------------------------------------------------
# functiongraph.py (so ahnlich wie im Buch)
#-----------------------------------------------------------------------------------------------------------
# Der Graph der Funktion f(x) = sin(4x)+sin(20x) wird im Intervall -pi/2..pi/2 gezeichnet.
# Von der Kommandozeile wird die Sampling-Dichte n (d.h. die Anzahl der zu berechnenden Punkte) eingelesen.
#-----------------------------------------------------------------------------------------------------------
import math, sys, stddraw
# Lies n von der Kommandozeile
# und erzeuge Arrays fur die x-Werte und die y-Werte des Graph der Funktion f.
n = int(sys.argv[1])
x_werte = []
y_werte = []
# Berechne fur n x-Werte, die gleichmaßig uber das Intervall -pi/2..pi/2 verteilt sind,
# jeweils den zugehorigen y-Wert f(x)=sin(4x)+sin(20x).
# Die x_werte sind -pi/2, -pi/2+1*pi/(n-1), -pi/2+2*pi/(n-1),..., -pi/2+(n-1)*pi/(n-1) .
# Speichere den x-Wert in x_werte[] und den zugehorigen y-Wert in y_werte.
# Am Ende gilt f(x_werte[i])==y_werte[i] fur i in range(n).
for i in range(n):
x_werte += [ -math.pi/2 + i * math.pi/(n-1) ]
y_werte += [ math.sin(4*x_werte[i]) + math.sin(20*x_werte[i]) ]
# Richte die Leinwand ein.
stddraw.setXscale(-math.pi/2, math.pi/2)
stddraw.setYscale(-2, 2)
# Male die Punkte und verbinde sie mit Strichen.
for i in range(n-1):
stddraw.line(x_werte[i], y_werte[i], x_werte[i+1], y_werte[i+1])
# Zeige das Bild an.
stddraw.show()stddraw – Graph einer Funktion darstellen 1.5.51
#-----------------------------------------------------------------------------------------------------------
# functiongraph.py (so ahnlich wie im Buch)
#-----------------------------------------------------------------------------------------------------------
# Der Graph der Funktion f(x) = sin(4x)+sin(20x) wird im Intervall -pi/2..pi/2 gezeichnet.
# Von der Kommandozeile wird die Sampling-Dichte n (d.h. die Anzahl der zu berechnenden Punkte) eingelesen.
#-----------------------------------------------------------------------------------------------------------
import math, sys, stddraw
# Lies n von der Kommandozeile
# und erzeuge Arrays fur die x-Werte und die y-Werte des Graph der Funktion f.
n = int(sys.argv[1])
x_werte = []
y_werte = []
# Berechne fur n x-Werte, die gleichmaßig uber das Intervall -pi/2..pi/2 verteilt sind,
# jeweils den zugehorigen y-Wert f(x)=sin(4x)+sin(20x).
# Die x_werte sind -pi/2, -pi/2+1*pi/(n-1), -pi/2+2*pi/(n-1),..., -pi/2+(n-1)*pi/(n-1) .
# Speichere den x-Wert in x_werte[] und den zugehorigen y-Wert in y_werte.
# Am Ende gilt f(x_werte[i])==y_werte[i] fur i in range(n).
for i in range(n):
x_werte += [ -math.pi/2 + i * math.pi/(n-1) ]
y_werte += [ math.sin(4*x_werte[i]) + math.sin(20*x_werte[i]) ]
# Richte die Leinwand ein.
stddraw.setXscale(-math.pi/2, math.pi/2)
stddraw.setYscale(-2, 2)
# Male die Punkte und verbinde sie mit Strichen.
for i in range(n-1):
stddraw.line(x_werte[i], y_werte[i], x_werte[i+1], y_werte[i+1])
# Zeige das Bild an.
stddraw.show()
python3 functiongraph.py 21
python3 functiongraph.py 20
stddraw – Graph einer Funktion darstellen 1.5.51
#-----------------------------------------------------------------------------------------------------------
# functiongraph.py (so ahnlich wie im Buch)
#-----------------------------------------------------------------------------------------------------------
# Der Graph der Funktion f(x) = sin(4x)+sin(20x) wird im Intervall -pi/2..pi/2 gezeichnet.
# Von der Kommandozeile wird die Sampling-Dichte n (d.h. die Anzahl der zu berechnenden Punkte) eingelesen.
#-----------------------------------------------------------------------------------------------------------
import math, sys, stddraw
# Lies n von der Kommandozeile
# und erzeuge Arrays fur die x-Werte und die y-Werte des Graph der Funktion f.
n = int(sys.argv[1])
x_werte = []
y_werte = []
# Berechne fur n x-Werte, die gleichmaßig uber das Intervall -pi/2..pi/2 verteilt sind,
# jeweils den zugehorigen y-Wert f(x)=sin(4x)+sin(20x).
# Die x_werte sind -pi/2, -pi/2+1*pi/(n-1), -pi/2+2*pi/(n-1),..., -pi/2+(n-1)*pi/(n-1) .
# Speichere den x-Wert in x_werte[] und den zugehorigen y-Wert in y_werte.
# Am Ende gilt f(x_werte[i])==y_werte[i] fur i in range(n).
for i in range(n):
x_werte += [ -math.pi/2 + i * math.pi/(n-1) ]
y_werte += [ math.sin(4*x_werte[i]) + math.sin(20*x_werte[i]) ]
# Richte die Leinwand ein.
stddraw.setXscale(-math.pi/2, math.pi/2)
stddraw.setYscale(-2, 2)
# Male die Punkte und verbinde sie mit Strichen.
for i in range(n-1):
stddraw.line(x_werte[i], y_werte[i], x_werte[i+1], y_werte[i+1])
# Zeige das Bild an.
stddraw.show()
python3 functiongraph.py 21
python3 functiongraph.py 200
stddraw – Graph einer Funktion darstellen 1.5.51
#-----------------------------------------------------------------------------------------------------------
# functiongraph.py (so ahnlich wie im Buch)
#-----------------------------------------------------------------------------------------------------------
# Der Graph der Funktion f(x) = sin(4x)+sin(20x) wird im Intervall -pi/2..pi/2 gezeichnet.
# Von der Kommandozeile wird die Sampling-Dichte n (d.h. die Anzahl der zu berechnenden Punkte) eingelesen.
#-----------------------------------------------------------------------------------------------------------
import math, sys, stddraw
# Lies n von der Kommandozeile
# und erzeuge Arrays fur die x-Werte und die y-Werte des Graph der Funktion f.
n = int(sys.argv[1])
x_werte = []
y_werte = []
# Berechne fur n x-Werte, die gleichmaßig uber das Intervall -pi/2..pi/2 verteilt sind,
# jeweils den zugehorigen y-Wert f(x)=sin(4x)+sin(20x).
# Die x_werte sind -pi/2, -pi/2+1*pi/(n-1), -pi/2+2*pi/(n-1),..., -pi/2+(n-1)*pi/(n-1) .
# Speichere den x-Wert in x_werte[] und den zugehorigen y-Wert in y_werte.
# Am Ende gilt f(x_werte[i])==y_werte[i] fur i in range(n).
for i in range(n):
x_werte += [ -math.pi/2 + i * math.pi/(n-1) ]
y_werte += [ math.sin(4*x_werte[i]) + math.sin(20*x_werte[i]) ]
# Richte die Leinwand ein.
stddraw.setXscale(-math.pi/2, math.pi/2)
stddraw.setYscale(-2, 2)
# Male die Punkte und verbinde sie mit Strichen.
for i in range(n-1):
stddraw.line(x_werte[i], y_werte[i], x_werte[i+1], y_werte[i+1])
# Zeige das Bild an.
stddraw.show()
python3 functiongraph.py 21
python3 functiongraph.py 512
stddraw – Graph einer Funktion darstellen 1.5.51
Weitere stddraw-Funktionen: (1) Kreise malen
stddraw.circle(x, y, r) male einen Kreis
mit Mittelpunkt px , yq und Radius r
import stddraw
x = 2
y = 3
r = 4
stddraw.setXscale(0, 6)
stddraw.setYscale(0, 6)
stddraw.circle(x, y, r)
stddraw.show()
p2, 3q
4
stddraw – weitere Funktionen 1.5.52
Weitere stddraw-Funktionen: (1) Kreise malen
stddraw.circle(x, y, r) male einen Kreis
mit Mittelpunkt px , yq und Radius r
import stddraw
x = 2
y = 3
r = 4
stddraw.setXscale(0, 6)
stddraw.setYscale(0, 6)
stddraw.circle(x, y, r)
stddraw.show()
p2, 3q
4
stddraw – weitere Funktionen 1.5.52
(2) Quadrate malen
stddraw.square(x, y, r) male ein Quadrat
mit Mittelpunkt px , yq und Radius r
import stddraw
x = 2
y = 3
r = 4
stddraw.setXscale(0, 6)
stddraw.setYscale(0, 6)
stddraw.square(x, y, r)
stddraw.show()
p2, 3q
4
4
stddraw – weitere Funktionen 1.5.53
(2) Quadrate malen
stddraw.square(x, y, r) male ein Quadrat
mit Mittelpunkt px , yq und Radius r
import stddraw
x = 2
y = 3
r = 4
stddraw.setXscale(0, 6)
stddraw.setYscale(0, 6)
stddraw.square(x, y, r)
stddraw.show()
p2, 3q
4
4
stddraw – weitere Funktionen 1.5.53
(3) Vielecke malen
stddraw.polygon(x, y) male ein Vieleck mit den Ecken
px[0], y[0]q, px[1], y[1]q, . . .
(x und y sind Arrays)
import stddraw
x = [1,0,3,4,5]
y = [2,3,4,6,1]
stddraw.setXscale(0, 6)
stddraw.setYscale(0, 6)
stddraw.polygon(x,y)
stddraw.show()
p1, 2q
p0, 3q
p3, 4q
p4, 6q
p5, 1q
stddraw – weitere Funktionen 1.5.54
(3) Vielecke malen
stddraw.polygon(x, y) male ein Vieleck mit den Ecken
px[0], y[0]q, px[1], y[1]q, . . .
(x und y sind Arrays)
import stddraw
x = [1,0,3,4,5]
y = [2,3,4,6,1]
stddraw.setXscale(0, 6)
stddraw.setYscale(0, 6)
stddraw.polygon(x,y)
stddraw.show() p1, 2q
p0, 3q
p3, 4q
p4, 6q
p5, 1q
stddraw – weitere Funktionen 1.5.54
Alle Formen konnen auch gefullt gemalt werden mittelsstddraw.filledCircle(x,y,r), stddraw.filledSquare(x,y,r),
stddraw.filledPolygon(x,y).
stddraw.filledPolygon(x, y) male ein ausgefulltes Vieleck mit den Ecken
px[0], y[0]q, px[1], y[1]q, . . . (x und y sind Arrays)
import stddraw
x = [1,0,3,4,5]
y = [2,3,4,6,1]
stddraw.setXscale(0, 6)
stddraw.setYscale(0, 6)
stddraw.setPenColor(stddraw.RED)
stddraw.filledPolygon(x,y)
stddraw.show()
stddraw – weitere Funktionen 1.5.55
Sonstige stddraw-Funktionen
Male ein Rechteck:
stddraw.rectangle(x,y, w,h) male ein Rechteck mit Punkt (x,y) unten links,
Breite w und Hohe h
stddraw.filledRectangle(x,y, w,h) male ein gefulltes Rechteck . . .
Schreibe Text:
stddraw.text(x,y, s) schreibe String s zentriert an Punkt (x,y)
stddraw.setFontSize(n) setze die Buchstabengroße auf n (Standard 12)
stddraw.setFontFamily(f) setze den Zeichensatz auf f (Standard helvetica)
Losche die Leinwand:
stddraw.clear(c) losche die Leinwand und farbe jedes Pixel mit Farbe c
stddraw – weitere Funktionen 1.5.56
import stddraw
stddraw.clear(stddraw.YELLOW)
stddraw.square(0.2, 0.8, 0.1)
stddraw.filledSquare(0.8, 0.8, 0.2)
stddraw.setPenColor(stddraw.GREEN)
xd = [0.1, 0.2, 0.3, 0.2]
yd = [0.2, 0.3, 0.2, 0.1]
stddraw.filledPolygon(xd, yd)
stddraw.setPenColor(stddraw.RED)
stddraw.filledCircle(0.8, 0.2, 0.2)
stddraw.setFontSize(20)
stddraw.text(0.8,0.8, 'großer roter Text')
stddraw.show()
Bilder konnen mittels Klick auf die rechte Maustasteoder mit stddraw.save(dateiname) gespeichert werden.
Die Dateinamenendung muss .jpg oder .png sein.
stddraw – weitere Funktionen 1.5.57
Bewegte Bilder
Zeigt man schnell hintereinander ahnliche Bilder, so sieht es aus, als ob sich etwas bewegt.
stddraw – bewegte Bilder 1.5.58
Aufgabe: Lasse eine Kugel quer uber die Leinwand rollen
Die Kugel soll von der unteren linken Ecke der Leinwand (Punkt p0, 0q)
auf der Diagonalen in die obere rechte Ecke der Leinwand rollen (Punkt p1, 1q).
Die Punkte auf der Diagonalen haben die gleiche x- und y -Koordinate.
Wir erhalten die Punkte der rollenden Kugel, indem wir einen Abstand wahlen,
den wir immer wieder zur x- und y -Koordinate der Kugel addieren,
bis die beiden Koordinaten 1 (oder großer) geworden sind.
Die Leinwand mit der Kugel an ihrer aktuellen Position wird jedesmal fur eine kleine Zeitspanne
angezeigt, wenn die Kugel ihre neue Position erhalten hat.
stddraw – bewegte Bilder 1.5.59
# kugel-1.py
#--------------------------------------------------------------------------------
# Eine Kugel rollt auf der Diagonalen von links nach rechts durch das Bild.
# Das wird als "Film" durch aufeinanderfolgende Bilder angezeigt.
# Von der Kommandozeile wird ein int zeitspanne (Anzeigezeit jedes Bildes in ms)
# und ein float abstand (beeinflusst den Abstand der Kugel von Bild zu Bild) gelesen.
#--------------------------------------------------------------------------------
import sys, stddraw
zeitspanne = int(sys.argv[1])
abstand = float(sys.argv[2])
RADIUS = 0.05 # Der Radius der Kugel.
# Die Kugel wird auf der Diagonalen uber die Leinwand bewegt.
# Der Startpunkt der Kugel ist (0,0) -- d.h. die untere linke Ecke der Leinwand.
# Der Punkt (x_pos,y_pos) ist die aktuelle Position der Kugel.
x_pos = 0.0
y_pos = 0.0
# Die Bewegung entsteht, indem aufeinanderfolgende Bilder gezeigt werden,
# bei denen die Kugel jedesmal ein kleines Stuck weitergerollt ist.
# Das wird erreicht, indem abstand zu x_pos und y_pos addiert wird.
while x_pos<1.0 and y_pos<1.0:
# Bestimme die nachste Position der Kugel.
x_pos = x_pos + abstand
y_pos = y_pos + abstand
# Losche die Leinwand, male die Kugel auf ihrer neuen Position und zeige die Leinwand an.
stddraw.filledCircle(x_pos, y_pos, RADIUS)
stddraw.show(zeitspanne)
stddraw.show()stddraw – bewegte Bilder 1.5.60
python3 kugel-1.py 20 0.13
python3 kugel-1.py 20 0.18
(Wir konnen jetzt nicht mehr richtig darstellen, was passiert . . . )
stddraw – bewegte Bilder 1.5.61
Aufgabe: lasse die Kugel hin- und herprallen
Die Kugel soll von der unteren linken Ecke der Leinwand (Punkt p0, 0q)uber die Diagonale in die obere rechte Ecke der Leinwand rollen (Punkt p1, 1q).
Von dort soll sie wieder zuruckrollen usw.
Das erreicht man wie folgt:Wenn die Kugel in einer Ecke ankommt,
dann wird das Vorzeichen von abstand verandert.Wenn abstand positiv ist, dann rollt die Kugel von links unten nach rechts oben.Wenn abstand negativ ist, dann rollt die Kugel von rechts oben nach links unten.
stddraw – bewegte Bilder 1.5.62
# kugel-2.py
#--------------------------------------------------------------------------------------
# Eine Kugel rollt auf der Diagonalen von links nach rechts hin und her durch das Bild.
# Von der Kommandozeile wird ein int zeitspanne (Anzeigezeit jedes Bildes in ms)
# und ein float abstand (beeinflusst den Abstand der Kugel von Bild zu Bild) gelesen.
#-------------------------------------------------------------------------------------
import sys, stddraw
zeitspanne = int(sys.argv[1])
abstand = float(sys.argv[2])
RADIUS = 0.05 # Der Radius der Kugel.
# Der Startpunkt der Kugel ist (0,0) -- d.h. die untere linke Ecke der Leinwand.
# Der Punkt (x_pos,y_pos) ist die aktuelle Position der Kugel.
x_pos = 0.0
y_pos = 0.0
# Die Bewegung entsteht, indem aufeinanderfolgende Bilder gezeigt werden,
# bei denen die Kugel jedesmal ein kleines Stuck weitergerollt ist.
# Das wird erreicht, indem abstand zu x_pos und y_pos addiert wird.
while True:
# Falls die Kugel in einer Ecke ist, dann andere ihre Richtung (um 180 Grad).
if x_pos>=1.0 or x_pos<0.0: abstand = -abstand
# Bestimme die nachste Position der Kugel.
x_pos += abstand
y_pos += abstand
# Losche die Leinwand, male die Kugel auf ihrer neuen Position und zeige die Leinwand an.
stddraw.filledCircle(x_pos, y_pos, RADIUS)
stddraw.show(zeitspanne)
stddraw.show()
#-------------------------------------------------------------------------------
# python kugel-2.py 25 0.005 stddraw – bewegte Bilder 1.5.63
Aufgabe: lasse die Kugel an den Seiten der Leinwand abprallen
Die Kugel rollt uber die Leinwand.Wenn sie an eine Seite stoßt, dann prallt sie ab (
”Einfallswinkel“Ausfallswinkel“) und rollt weiter.
Wir mussen jetzt die Anderung der x-Koordinate und die Anderung der y -Koordinate der Kugeltrennen.
Wenn die Kugel an den linken oder rechten Rand stoßt,dann andert sich das Vorzeichen der Anderung der x-Koordinate.
Wenn die Kugel an den unteren oder oberen Rand stoßt,
dann andert sich das Vorzeichen der Anderung der y -Koordinate.
stddraw – bewegte Bilder 1.5.64
# kugel-3.py, Beispielaufruf: python3 kugel-3.py 25 0.005 0.008
#-------------------------------------------------------------------------------------------------
# Eine Kugel rollt auf der Leinwand. Wenn sie an eine Seite stoßt, prallt sie ab und rollt weiter.
# Das wird als "Film" durch aufeinanderfolgende Bilder angezeigt. Von der Kommandozeile werden
# ein int zeitspanne (Anzeigezeit jedes Bildes in ms) und zwei floats x_abstand und y_abstand
# (beeinflussen den Abstand der Kugel von Bild zu Bild) gelesen.
#-------------------------------------------------------------------------------------------------
import sys, stddraw
zeitspanne = int(sys.argv[1])
x_abstand = float(sys.argv[2])
y_abstand = float(sys.argv[3])
# Die Kugel liegt in der Mitte der Leinwand. Punkt (x_pos,y_pos) ist ihre aktuelle Position.
(x_pos, y_pos) = (0.5, 0.5)
# Die Bewegung entsteht, indem x_abstand zu x_pos und y_abstand zu y_pos addiert wird.
# Wenn die Kugel an eine Seite prallt, wird das Vorzeichen des entsprechenden Abstands geandert.
while True:
# Falls die Kugel an die rechte oder linke Seite prallt, dann andere ihre x-Richtung.
if x_pos>=1.0 or x_pos<=0.0: x_abstand = -x_abstand
# Falls die Kugel an die untere oder obere Seite prallt, dann andere ihre y-Richtung.
if y_pos>=1.0 or y_pos<=0.0: y_abstand = -y_abstand
# Bestimme die nachste Position der Kugel.
x_pos = x_pos + x_abstand
y_pos = y_pos + y_abstand
# Losche die Leinwand, male die Kugel auf ihrer neuen Position und zeige die Leinwand an.
stddraw.clear(stddraw.GRAY)
stddraw.filledCircle(x_pos, y_pos, 0.05)
stddraw.show(zeitspanne)
stddraw.show()stddraw – bewegte Bilder 1.5.65
Zusammenfassungstandard draw
Wir haben gesehen, wie Bilder aus einfachen Elementen
(Punkte, Striche, Kreise, Rechtecke, Schrift)
gestaltet und angezeigt werden konnen.
Mit diesen Mitteln lassen sich z.B. Messwerte
und einfache Animationen graphisch ansprechend darstellen.
1.5.66
Weitere Beispiele
Eine csv-Datei (comma separated values) enthalt in Zeilen zusammengehorige Daten, die als Stringsdargestellt und durch Kommas (o.a.) getrennt sind.
Bsp.: Datei airports.csv mit Namen, Breiten- und Langengrad etc. von Flughafen.
1,"Goroka","Goroka","Papua New Guinea","GKA","AYGA",-6.081689,145.391881,5282,10,"U","Pacific/Port_Moresby"
2,"Madang","Madang","Papua New Guinea","MAG","AYMD",-5.207083,145.7887,20,10,"U","Pacific/Port_Moresby"
3,"Mount Hagen","Mount Hagen","Papua New Guinea","HGU","AYMH",-5.826789,144.295861,5388,10,"U","Pacific/Port_Moresby"
4,"Nadzab","Nadzab","Papua New Guinea","LAE","AYNZ",-6.569828,146.726242,239,10,"U","Pacific/Port_Moresby"
5,"Port Moresby Jacksons Intl","Port Moresby","Papua New Guinea","POM","AYPY",-9.443383,147.22005,146,10,"U","Pacific/Port_Moresby"
6,"Wewak Intl","Wewak","Papua New Guinea","WWK","AYWK",-3.583828,143.669186,19,10,"U","Pacific/Port_Moresby"
Wir wollen nun die Koordinaten jedes Flughafens ausgeben.Dazu konnen wir jede Zeile in ein Array aufteilen, dessen Elemente die durch Kommas getrennten Stellender Zeile sind.
zeile = '1,"Goroka","Goroka","Papua New Guinea","GKA","AYGA",' +
'-6.081689,145.391881,5282,10,"U","Pacific/Port_Moresby"'
array = string.split( zeile, ',' )
stdio.writeln(array)
liefert['1', '"Goroka"', '"Goroka"', '"Papua New Guinea"', '"GKA"', '"AYGA"', '-6.081689', '145.391881',
'5282', '10', '"U"', '"Pacific/Port_Moresby"']Anhang mit alten Programmen 1.5.67
# coords-aus-csv.py
# Es werden die Zeilen einer csv-Datei eingelesen.
# Die Eintrage an Stelle 6 und 7 werden ausgegeben.
import stdio, string
while stdio.hasNextLine():
line = stdio.readLine()
breitengrad = string.split(line,',')[6]
laengengrad = string.split(line,',')[7]
stdio.writef('%8s %8s\n', breitengrad, laengengrad)
#---------------------------------------------------------
# python coords-aus-csv.py < airports.csv
# -6.081689 145.391881
# -5.207083 145.7887
# -5.826789 144.295861
# -6.569828 146.726242
# -9.443383 147.22005
# -3.583828 143.669186
# ...
Anhang mit alten Programmen 1.5.68
#-----------------------------------------------------------------------
# plotfilter.py (aus dem Buch)
#-----------------------------------------------------------------------
import stdio
import stddraw
# Read x and y scales from standard input, and configure standard
# draw accordingly. Then read points from standard input until
# end-of-file, and plot them on standard draw.
x0 = stdio.readFloat()
y0 = stdio.readFloat()
x1 = stdio.readFloat()
y1 = stdio.readFloat()
stddraw.setXscale(x0, x1)
stddraw.setYscale(y0, y1)
# Read and plot the points.
stddraw.setPenRadius(0.002)
while not stdio.isEmpty():
x = stdio.readFloat()
y = stdio.readFloat()
stddraw.point(x, y)
stddraw.show()
#----------------------------------------
# python plotfilter.py < usa.txt
Datei usa.txt:
669905.0 247205.0 1244962.0 700000.0
1097038.8890 245552.7780
1103961.1110 247133.3330
1104677.7780 247205.5560
1108586.1110 249238.8890
1109713.8890 250111.1110
...Anhang mit alten Programmen 1.5.69
Wir wollen plotfilter.py benutzen, um eine Karte mit den Flughafen zu malen.
Deren Koordinaten haben wir ja bereits.
Dazu mussen wir coords-aus-csv.py so modifizieren,dass es zu plotfiler.py passt:
§ In der ersten Zeile der Ausgabe mussen die Werte x0, y0, x1, y1 fur die Bereiche der x-Werte(x0 ď x ď x1) und die Bereiche der y -Werte (y0 ď y ď y1) stehen.
§ In den darauffolgenden Zeilen folgen x-Koordinate (Langengrad) und y -Koordinate (Breitengrad) jedesFlughafens.
Anhang mit alten Programmen 1.5.70
#-----------------------------------------------------------------------
# airports-to-plotfilter.py
#-----------------------------------------------------------------------
# Es werden die Zeilen einer csv-Datei eingelesen.
# Die Ausgabe passt als Eingabe fur plotfilter.py .
# Zuerst werden die Bereiche fur die x- und y-Koordinaten ausgegeben.
# Die x-Koordinaten sind die Langengrade (-180 ... 180) und
# die y-Koordinaten sind die Breitengrade (-90 .. 90).
# Der Eintrag an Stelle 6 der csv-Datei ist der Breitengrad,
# und der Eintrag an Stelle 7 ist der Langengrad.
import stdio, string
# Ausgabe der Bereiche fur die x- und y-Koordinaten
stdio.writeln('-180.0 -90.0 180.0 90.0')
while stdio.hasNextLine():
zeile = stdio.readLine()
xkoordinate = string.split(zeile,',')[7]
ykoordinate = string.split(zeile,',')[6]
stdio.writef('%8s %8s\n', xkoordinate, ykoordinate)
#--------------------------------------------------------------------------
# ( python airports-to-plotfilter.py < airports.csv ) | python plotfilter.py
#Anhang mit alten Programmen 1.5.71
Vorlesung 07
1. Elemente des Programmierens
1.2 Grundlegende Daten-Typen
1.3 Verzweigungen und Schleifen
1.4 Arrays
1.5 Ein- und Ausgabe
1.6 Dictionaries und Abschluss-Beispiel Page Rank
Anhang mit alten Programmen 1.6.1
Dictionaries
Bei Arrays hat man eine Zuordnung von Indizes zu Werten.
Bei Dictionaries hat man eine Zuordnung von Schlusseln zu Werten.
Die Werte konnen uber die Schlussel”angesprochen“ werden.
Die Schlussel konnen vom Typ string, int etc. sein.
Worterbuch:
Adler eagle
Buch book
Dienst service
Efeu ivy
funkeln sparkle...
...
Python:
d = dict() # d ist ein leeres Dictionary
d['Adler'] = 'eagle'
d['Buch'] = 'book'
d['Dienst'] = 'service'
d['Efeu'] = 'ivy'
d['funkeln'] = 'sparkle'
...
Datentyp dict – Dictionary 1.6.2
Benutzung des Datentyps dict
Erzeugen eines Dictionary:
ts1 : w1, s2 : w2, ..., sn : wnu ein Dictionary der Lange n mit den Zuordnungen
Schlussel s0 zu Wert w0, . . . , Schlussel sn´1 zu Wert wn´1
dict() oder t u ein leeres Dictionary (ohne Zuordnungen)
Zugriff auf ein Dictionary d:
d[s] der Wert, der Schlussel s in d zugeordnet ist (indizierter Zugriff)
d[s] = x ersetze den Wert, der Schlussel s zugeordnet ist, durch x (indizierte Zuweisung)
s in d ergibt True, falls Schlussel s im Dictionary d vorkommt, sonst False
len(d) die Anzahl der Schlussel von d
for s in d: iteriere uber alle Schlussel s von d (Durchlaufen)
list(d) ein Array aus allen Schlusseln von d
del(d[s]) losche Schlussel s (und den zugeordneten Wert) aus d
Datentyp dict – Dictionary 1.6.3
Wir wollen ein Programm schreiben,
das ein Eingabewort in das Morsealphabet kodiert
oder aus dem Morsealphabet dekodiert.
Das Morsealphabet ordnet jedem Großbuchstaben eine Zeichenfolge aus Punkten und Strichen zu,
z.B.
A .-
B -...
C -.-.
D -..
E .
F ..-.
G --.
H ....
I ..
J .---
K -.-
L .-..
Das Wort KABEL wird zu -.- .- -... . .-.. kodiert
und das Wort -... . .. ..-. .- .-.. .-.. wird zu BEIFALL dekodiert.
Unser Programm soll
(1) das Morsealphabet aus einer Datei (wie oben) lesen
und daraus ein Dictionary zum Kodieren (Schlussel: Buchstabe, Wert: Morsecode)
sowie ein Dictionary zum Dekodieren (Schlussel: Morsecode, Wert: Buchstabe) erzeugen, und
(2) den String von der Kommandozeile damit kodieren bzw. dekodieren.Beispielprogramm morsen.py 1.6.4
Wir wollen ein Programm schreiben,
das ein Eingabewort in das Morsealphabet kodiert
oder aus dem Morsealphabet dekodiert.
Das Morsealphabet ordnet jedem Großbuchstaben eine Zeichenfolge aus Punkten und Strichen zu,
z.B.
A .-
B -...
C -.-.
D -..
E .
F ..-.
G --.
H ....
I ..
J .---
K -.-
L .-..
Das Wort KABEL wird zu -.- .- -... . .-.. kodiert
und das Wort -... . .. ..-. .- .-.. .-.. wird zu BEIFALL dekodiert.
Unser Programm soll
(1) das Morsealphabet aus einer Datei (wie oben) lesen
und daraus ein Dictionary zum Kodieren (Schlussel: Buchstabe, Wert: Morsecode)
sowie ein Dictionary zum Dekodieren (Schlussel: Morsecode, Wert: Buchstabe) erzeugen, und
(2) den String von der Kommandozeile damit kodieren bzw. dekodieren.Beispielprogramm morsen.py 1.6.4
Teil 1: Morsealphabet einlesen und in Dictionaries eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in morsecode und morsedecode
A .-
B -...
C -.-.
D -..
...
morsecode ist ein Dictionary furdie Zuordnung von Buchstaben zu Morsezeichen.
morsedecode ist ein Dictionary furdie Zuordnung von Morsezeichen zu Buchstaben.
Dictionary morsecode
Schlussel Wert
Dictionary morsedecode
Schlussel Wert
Beispielprogramm morsen.py 1.6.5
Teil 1: Morsealphabet einlesen und in Dictionaries eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in morsecode und morsedecode
A .- 'A .-'
B -...
C -.-.
D -..
...
morsecode ist ein Dictionary furdie Zuordnung von Buchstaben zu Morsezeichen.
morsedecode ist ein Dictionary furdie Zuordnung von Morsezeichen zu Buchstaben.
Dictionary morsecode
Schlussel Wert
Dictionary morsedecode
Schlussel Wert
Beispielprogramm morsen.py 1.6.5
Teil 1: Morsealphabet einlesen und in Dictionaries eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in morsecode und morsedecode
A .- 'A .-' ['A', '.-']
B -...
C -.-.
D -..
...
morsecode ist ein Dictionary furdie Zuordnung von Buchstaben zu Morsezeichen.
morsedecode ist ein Dictionary furdie Zuordnung von Morsezeichen zu Buchstaben.
Dictionary morsecode
Schlussel Wert
Dictionary morsedecode
Schlussel Wert
Beispielprogramm morsen.py 1.6.5
Teil 1: Morsealphabet einlesen und in Dictionaries eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in morsecode und morsedecode
A .- 'A .-' ['A', '.-'] morsecode['A'] = '.-'
morsedecode['.-'] = 'A'
B -...
C -.-.
D -..
...
morsecode ist ein Dictionary furdie Zuordnung von Buchstaben zu Morsezeichen.
morsedecode ist ein Dictionary furdie Zuordnung von Morsezeichen zu Buchstaben.
Dictionary morsecode
Schlussel Wert
'A' '.-'
Dictionary morsedecode
Schlussel Wert
'.-' 'A'
Beispielprogramm morsen.py 1.6.5
Teil 1: Morsealphabet einlesen und in Dictionaries eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in morsecode und morsedecode
A .- 'A .-' ['A', '.-'] morsecode[z[0]] = z[1]
morsedecode[z[1]] = z[0]
B -...
C -.-.
D -..
...
morsecode ist ein Dictionary furdie Zuordnung von Buchstaben zu Morsezeichen.
morsedecode ist ein Dictionary furdie Zuordnung von Morsezeichen zu Buchstaben.
Dictionary morsecode
Schlussel Wert
'A' '.-'
Dictionary morsedecode
Schlussel Wert
'.-' 'A'
Beispielprogramm morsen.py 1.6.5
Teil 1: Morsealphabet einlesen und in Dictionaries eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in morsecode und morsedecode
A .- 'A .-' ['A', '.-'] morsecode[z[0]] = z[1]
morsedecode[z[1]] = z[0]
B -... 'B -...'
C -.-.
D -..
...
morsecode ist ein Dictionary furdie Zuordnung von Buchstaben zu Morsezeichen.
morsedecode ist ein Dictionary furdie Zuordnung von Morsezeichen zu Buchstaben.
Dictionary morsecode
Schlussel Wert
'A' '.-'
Dictionary morsedecode
Schlussel Wert
'.-' 'A'
Beispielprogramm morsen.py 1.6.5
Teil 1: Morsealphabet einlesen und in Dictionaries eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in morsecode und morsedecode
A .- 'A .-' ['A', '.-'] morsecode[z[0]] = z[1]
morsedecode[z[1]] = z[0]
B -... 'B -...' ['B', '-...']
C -.-.
D -..
...
morsecode ist ein Dictionary furdie Zuordnung von Buchstaben zu Morsezeichen.
morsedecode ist ein Dictionary furdie Zuordnung von Morsezeichen zu Buchstaben.
Dictionary morsecode
Schlussel Wert
'A' '.-'
Dictionary morsedecode
Schlussel Wert
'.-' 'A'
Beispielprogramm morsen.py 1.6.5
Teil 1: Morsealphabet einlesen und in Dictionaries eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in morsecode und morsedecode
A .- 'A .-' ['A', '.-'] morsecode[z[0]] = z[1]
morsedecode[z[1]] = z[0]
B -... 'B -...' ['B', '-...'] morsecode[z[0]] = z[1]
morsedecode[z[1]] = z[0]
C -.-.
D -..
...
morsecode ist ein Dictionary furdie Zuordnung von Buchstaben zu Morsezeichen.
morsedecode ist ein Dictionary furdie Zuordnung von Morsezeichen zu Buchstaben.
Dictionary morsecode
Schlussel Wert
'A' '.-'
'B' '-...'
Dictionary morsedecode
Schlussel Wert
'.-' 'A'
'-...' 'B'
Beispielprogramm morsen.py 1.6.5
Teil 2: Eingabe kodieren bzw. dekodieren
Grundidee beim Kodieren eines Buchstabens:
lies den Buchstaben x und gib morsecode[x] aus
Grundidee beim Kodieren eines Morsezeichens:
lies die Zeichenfolge x und gib morsedecode[x] aus
Das muss dann fur alle Buchstaben/Morsezeichen gemacht werden.
Ob man kodieren oder dekodieren soll,
erkennt man am erste Zeichen der Eingabe.
Wenn sie . oder - ist, dann muss dekodiert werden,
und sonst muss kodiert werden.
Beispielprogramm morsen.py 1.6.6
# morsen.py
#--------------------------------------------------------------------------------------------------------
import sys
# Teil 1: Einlesen des Morsealphabets von standard input ------------------------------------------------
morsecode = dict() # Das Dictionary fur die Kodierung in den Morsecode.
morsedecode = dict() # Das Dictionary fur die Dekodierung aus dem Morsecode.
for zeile in sys.stdin: # Gehe durch alle Zeilen der Eingabedatei.
z = str.split(zeile) # Teile die Zeile an Folgen von Leerzeichen.
if len(z)<2: continue # Falls dabei nicht mindestens 2 Teile herauskommen: ignoriere es.
morsecode[z[0]] = z[1] # Trage die Zuordnung Zeichen->Morsezeichen in morsecode ein.
morsedecode[z[1]] = z[0] # Trage die Zuordung Morsezeichen->Zeichen in morsedecode ein.
# Teil 2: Kodieren bzw. Dekodieren der Eingabe ----------------------------------------------------------
eingabe = sys.argv[1]
ergebnis = ''
if eingabe[0] in '.-': # Falls die Eingabe mit . oder - anfangt, ist sie im Morsecode und wird dekodiert.
for c in str.split(eingabe):
ergebnis += morsedecode[c]
else: # Sonst wird die Eingabe in den Morsecode kodiert.
for zeichen in eingabe:
ergebnis += morsecode[zeichen] + ' '
# Gib das Ergebnis aus.
print(ergebnis)Beispielprogramm morsen.py 1.6.7
#------------------------------------------------------------------------------------------------
# python3 morsen.py INFORMATIK < morsealphabet.txt
# .. -. ..-. --- .-. -- .- - .. -.-
#
# python3 morsen.py '.. -. ..-. --- .-. -- .- - .. -.-' < morsealphabet.txt
# INFORMATIK
Beispielprogramm morsen.py 1.6.8
1.6 PageRank
Bei Anfragen an Suchmaschinen im Internet werden haufig Millionen von Webseiten zu einemSuchwort gefunden.
Wie kommt es zu der Reihenfolge, in der die Seiten als Suchergebnis angezeigt werden?Es scheint ja so zu sein, dass die
”besten“ Seiten am Anfang angezeigt werden . . .
Die Vermutung ist, dassauf
”wichtige“ Webseiten haufiger direkt oder indirekt von anderen Webseiten verwiesen wird.
Das wird im PageRank quantifiziert – das ist die Wahrscheinlichkeit, mit der ein Websurfer, dernach bestimmten Zufalls-Regeln (s.u.) von einer Webseite zur nachsten surft, die Seite erreicht.
Bei der Anzeige des Suchergebnisses einer Suchmaschine werden die Seiten mit absteigendemPageRank angezeigt (neben moglichen anderen Kriterien).
Das hat sich als nutzlich erwiesen.Wir wollen Programme schreiben, die fur kleine Beispiele den PageRank ausrechnen konnen.
Berechnung des PageRank 1.6.9
Webseiten mit Links zu anderen Seiten (Graph)
bbb.com
ddd.org
aaa.de
aaa.de
ddd.org
ccc.edu
aaa.de
bbb.com
eee.eu
ccc.edu
ccc.eduddd.org
bbb.com
aaa.deeee.eu
Berechnung des PageRank 1.6.10
Webseiten mit Links zu anderen Seiten (Graph)
bbb.com
ddd.org
aaa.de
aaa.de
ddd.org
ccc.edu
aaa.de
bbb.com
eee.eu
ccc.edu
ccc.eduddd.org
bbb.com
aaa.deeee.eu
Berechnung des PageRank 1.6.10
Die Reise eines Random Surfers (auf jeder Seite wird gezahlt, wie oft sie erreicht wird).
bbb.com
ddd.org
aaa.de
1
aaa.de
ddd.org
ccc.edu
aaa.de
bbb.com
eee.eu
ccc.edu
ccc.eduddd.org
bbb.com
aaa.deeee.eu
Berechnung des PageRank 1.6.10
Die Reise eines Random Surfers (auf jeder Seite wird gezahlt, wie oft sie erreicht wird).
bbb.com
ddd.org
aaa.de
1
aaa.de
ddd.org
ccc.edu
aaa.de
bbb.com
1eee.eu
ccc.edu
ccc.eduddd.org
bbb.com
aaa.deeee.eu
Berechnung des PageRank 1.6.10
Die Reise eines Random Surfers (auf jeder Seite wird gezahlt, wie oft sie erreicht wird).
bbb.com
ddd.org
aaa.de
2
aaa.de
ddd.org
ccc.edu
aaa.de
bbb.com
1eee.eu
ccc.edu
ccc.eduddd.org
bbb.com
aaa.deeee.eu
Berechnung des PageRank 1.6.10
Die Reise eines Random Surfers (auf jeder Seite wird gezahlt, wie oft sie erreicht wird).
bbb.com
ddd.org
aaa.de
2
aaa.de
ddd.org
ccc.edu
aaa.de
bbb.com
1eee.eu
ccc.edu
ccc.eduddd.org
1
bbb.com
aaa.deeee.eu
Berechnung des PageRank 1.6.10
Die Reise eines Random Surfers (auf jeder Seite wird gezahlt, wie oft sie erreicht wird).
bbb.com
ddd.org
aaa.de
2
aaa.de
ddd.org
ccc.edu
aaa.de
bbb.com
1eee.eu
ccc.edu
ccc.eduddd.org
1
bbb.com
aaa.deeee.eu
1Berechnung des PageRank 1.6.10
Die Reise eines Random Surfers (auf jeder Seite wird gezahlt, wie oft sie erreicht wird).
bbb.com
ddd.org
aaa.de
3
aaa.de
ddd.org
ccc.edu
aaa.de
bbb.com
1eee.eu
ccc.edu
ccc.eduddd.org
1
bbb.com
aaa.deeee.eu
1Berechnung des PageRank 1.6.10
Die Reise eines Random Surfers mit der Wahrscheinlichkeit, auf einer Seite zu sein.
bbb.com
ddd.org
aaa.de
aaa.de
ddd.org
ccc.edu
aaa.de
bbb.com
eee.eu
ccc.edu
ccc.eduddd.org
bbb.com
aaa.deeee.eu
12
16
0
16 1
6 Berechnung des PageRank 1.6.10
Die Reise eines Random Surfers mit der Wahrscheinlichkeit, auf einer Seite zu sein.
bbb.com
ddd.org
aaa.de
aaa.de
ddd.org
ccc.edu
aaa.de
bbb.com
eee.eu
ccc.edu
ccc.eduddd.org
bbb.com
aaa.deeee.eu
0.2083
0.2082
0.2116
0.1612 0.2106Berechnung des PageRank 1.6.10
Darstellung des Netzwerks aus Webseiten und Links
Das Netzwerk liegt in einer Datei mit derAngabe seiner Links vor.
Datei NetzwerkVL07.txt:
aaa.de bbb.com
aaa.de ddd.org
bbb.com aaa.de
eee.eu aaa.de
bbb.com ccc.edu
bbb.com aaa.de
bbb.com ddd.com
ccc.edu eee.eu
ddd.com ccc.edu
eee.eu bbb.com
Im Programm kann es als Dictionary dargestelltwerden. Jede Webseite ist ein Schlussel.Der Wert zu jedem Schlussel ist ein Array aus denSeiten, zu denen ein Link geht.
Schlussel Wert
'aaa.de' [ 'bbb.com', 'ddd.org' ]
'eee.eu' [ 'aaa.de', 'bbb.com' ]
'bbb.com' [ 'aaa.de','ccc.edu','aaa.de','ddd.org']
'ddd.org' [ 'ccc.edu' ]
'ccc.edu' [ 'eee.eu' ]
Die Webseiten nennt man auch Knoten.Die Links nennt man auch Kanten.Ein Graph besteht aus Knoten und Kanten.
Berechnung des PageRank 1.6.11
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com
aaa.de ddd.org
bbb.com aaa.de
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com'
aaa.de ddd.org
bbb.com aaa.de
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com' ['aaa.de', 'bbb.com']
aaa.de ddd.org
bbb.com aaa.de
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com' ['aaa.de', 'bbb.com'] nachfolger['aaa.de'] = []
nachfolger['aaa.de'] += ['bbb.com]'
aaa.de ddd.org
bbb.com aaa.de
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
'aaa.de' []
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com' ['aaa.de', 'bbb.com'] nachfolger['aaa.de'] = []
nachfolger['aaa.de'] += ['bbb.com]'
aaa.de ddd.org
bbb.com aaa.de
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
'aaa.de' ['bbb.com']
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com' ['aaa.de', 'bbb.com'] nachfolger[z[0]] = []
nachfolger[z[0]] += z[1]
aaa.de ddd.org
bbb.com aaa.de
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
'aaa.de' ['bbb.com']
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com' ['aaa.de', 'bbb.com'] nachfolger[z[0]] = []
nachfolger[z[0]] += z[1]
aaa.de ddd.org 'aaa.de ddd.org'
bbb.com aaa.de
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
'aaa.de' ['bbb.com']
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com' ['aaa.de', 'bbb.com'] nachfolger[z[0]] = []
nachfolger[z[0]] += z[1]
aaa.de ddd.org 'aaa.de ddd.org' ['aaa.de', 'ddd.org']
bbb.com aaa.de
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
'aaa.de' ['bbb.com']
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com' ['aaa.de', 'bbb.com'] nachfolger[z[0]] = []
nachfolger[z[0]] += z[1]
aaa.de ddd.org 'aaa.de ddd.org' ['aaa.de', 'ddd.org'] nachfolger[z[0]] += z[1]
bbb.com aaa.de
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
'aaa.de' ['bbb.com', 'ddd.org']
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com' ['aaa.de', 'bbb.com'] nachfolger[z[0]] = []
nachfolger[z[0]] += z[1]
aaa.de ddd.org 'aaa.de ddd.org' ['aaa.de', 'ddd.org'] nachfolger[z[0]] += z[1]
bbb.com aaa.de 'bbb.com aaa.de'
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
'aaa.de' ['bbb.com', 'ddd.org']
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com' ['aaa.de', 'bbb.com'] nachfolger[z[0]] = []
nachfolger[z[0]] += z[1]
aaa.de ddd.org 'aaa.de ddd.org' ['aaa.de', 'ddd.org'] nachfolger[z[0]] += z[1]
bbb.com aaa.de 'bbb.com aaa.de' ['bbb.com', 'aaa.de']
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
'aaa.de' ['bbb.com', 'ddd.org']
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com' ['aaa.de', 'bbb.com'] nachfolger[z[0]] = []
nachfolger[z[0]] += z[1]
aaa.de ddd.org 'aaa.de ddd.org' ['aaa.de', 'ddd.org'] nachfolger[z[0]] += z[1]
bbb.com aaa.de 'bbb.com aaa.de' ['bbb.com', 'aaa.de'] nachfolger[z[0]] = []
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
'aaa.de' ['bbb.com', 'ddd.org']
'bbb.com' []
Berechnung des PageRank 1.6.12
Das Netzwerk einlesen und in Dictionary nachfolger eintragen
Datei zeile in sys.stdin z = str.split(zeile) Eintrag in nachfolger
aaa.de bbb.com 'aaa.de bbb.com' ['aaa.de', 'bbb.com'] nachfolger[z[0]] = []
nachfolger[z[0]] += z[1]
aaa.de ddd.org 'aaa.de ddd.org' ['aaa.de', 'ddd.org'] nachfolger[z[0]] += z[1]
bbb.com aaa.de 'bbb.com aaa.de' ['bbb.com', 'aaa.de'] nachfolger[z[0]] = []
nachfolger[z[0]] += z[1]
...
nachfolger ist ein Dictionary furdie Zuordnung von Seiten zu ihren Folgeseiten.
Dictionary nachfolger
Schlussel Wert
'aaa.de' ['bbb.com', 'ddd.org']
'bbb.com' ['aaa.de']
Berechnung des PageRank 1.6.12
Der Random Surfer
§ startet auf einer zufallig gewahlten Seite
§ mit Wahrscheinlichkeit 0.9: wahlt zufallig einen Link auf der Seiteund folgt ihm zu einer Nachbarseite
mit Wahrscheinlichkeit 0.1: geht zufallig zu irgendeiner Seite
§ wiederholt den letzten Schritt sehr oft
§ zahlt dabei, wie haufig welche Seite besucht wurde
das Ergebnis wird in einem Dictionary gespeichert: Schlussel Wert'aaa.de' 20846
'eee.eu' 21029
'bbb.com' 20862
'ddd.org' 16104
'ccc.edu' 21160
Berechnung des PageRank 1.6.13
Ablauf des Programms in der Ubersicht
Die Programmteile und die Daten,
die im einen Programmteil produziert und im anderen benutzt werden:
lies ein Netzwerk von standard input
simuliere den Random Surfer in dem Netzwerk
gib die 10 Seiten mit dem hochsten PageRank aus
Netzwerk als Dictionary nachfolger
Haufigkeit der Seitenbesuche als Dictionary zaehler
Berechnung des PageRank 1.6.14
Teil 1: Einlesen des Graphen
import sys, random
# Teil 1: Einlesen des Netzwerks von standard input---------------------------------------
# Lies das Netzwerk von standard input (z.B. aus Datei routes-graph.txt).
# Jede Zeile ist ein Link und besteht aus 2 Strings, die durch Leerzeichen getrennt sind.
# Der erste String ist die Startseite und der zweite die Zielseite des Links.
# nachfolger ist ein Dictionary, dessen Schlussel alle Seiten sind.
# Der Wert eines Schlussels/Seite ist ein Array mit allen Zielseiten der Seite.
# In der Eingabe mehrfach vorgekommene Zielseiten einer Seite
# kommen auch in dem Array mehrfach vor.
nachfolger = dict()
for zeile in sys.stdin:
z = str.split(zeile)
if len(z)!=2: continue
startseite = str.strip(z[0])
zielseite = str.strip(z[1])
# Falls eine Seite noch nicht im Dictionary ist, wird sie dort eingetragen.
if startseite not in nachfolger: nachfolger[startseite] = []
if zielseite not in nachfolger: nachfolger[zielseite] = []
# Die zielseite wird als Nachfolger der startseite in das Werte-Array eingetragen.
nachfolger[startseite] += [zielseite]
Berechnung des PageRank 1.6.15
Teil 2: Simulation des Random Surfers
# Teil 2: Simulation des Random Surfers --------------------------------------------------------------------
# Der Random Surfer surft nach bestimmten Zufallsregeln durch das Netzwerk und besucht seine Seiten.
# Fur jede Seite wird gezahlt, wie oft er sie besucht. Dafur benutzen wir das Dictionary zaehler.
# Wieviele "Schritte" der Random Surfer insgesamt machen soll, wird von der Kommandozeile gelesen.
#-----------------------------------------------------------------------------------------------------------
# Erzeuge das Dictionary zaehler mit den Besuchszahlern fur jede Seite.
# Die Schlussel sind die Seiten, die Werte sind am Anfang alle 0.
zaehler = dict()
for schluessel in nachfolger:
zaehler[schluessel] = 0
# Wir brauchen noch ein Array mit allen Seiten, damit wir spater zufallig eine Seite wahlen konnen.
alleSeiten = list(nachfolger)
# Die Simulation des Random Surfers beginnt auf einer zufallig gewahlten Seite.
# Anschließend geht er so oft zu einer neuen Seite, wie auf der Kommandozeile angegeben ist.
aktuelleSeite = random.choice(alleSeiten)
zaehler[aktuelleSeite] += 1
for i in range(int(sys.argv[1])):
# Falls die aktuelle Seite keinen Link hat oder mit Wahrscheinlichkeit 0.1: gehe zu einer zufallig gewahlten Seite.
if len(nachfolger[aktuelleSeite])==0 or random.randrange(10)==0 :
aktuelleSeite = random.choice(alleSeiten)
# Mit Wahrscheinlichkeit 0.9: wahle zufallig einen der Links von der aktuellen Seite und benutze ihn.
else:
aktuelleSeite = random.choice(nachfolger[aktuelleSeite])
zaehler[aktuelleSeite] += 1Berechnung des PageRank 1.6.16
Teil 3: Ausgabe des Ergebnisses
Es sollen die 10 Seiten mit den hochsten PageRanks ausgegeben werden.
# Teil 3: Ausgabe der Ergebnisse -------------------------------------------------------------------------
# Die Top Ten werden ausgegeben.
print( 'Das Netzwerk hat %d Knoten/Seiten.' % len(zaehler) )
print( 'Die Seiten mit den hochsten PageRanks sind:' )
for j in range(min(10,len(zaehler))):
# Beginne mit der Seite, deren Schlussel als erster in zaehler vorkommt.
m = list(zaehler)[0]
# Suche die am haufigsten besuchte Seite.
# Gehe dazu durch alle Seiten und merke dir die mit dem bisher großten Zahlerwert.
for k in zaehler:
if zaehler[k] > zaehler[m]: m = k
# Gib die Seite aus und losche ihren Zahlerwert
# (damit in der nachsten Runde die nachstbeste Seite ausgegeben wird.)
print( ' %s %f' % (m, zaehler[m]/int(sys.argv[1])) )
zaehler[m] = 0
Berechnung des PageRank 1.6.17
Benutzung des Programms
$ python3 random_surfer.py 1000000 < GraphVL05.txt
Der Graph hat 5 Knoten/Seiten.
Die Seiten mit den hochsten PageRanks sind:
ccc.edu 0.211445
eee.eu 0.210078
aaa.de 0.208870
bbb.com 0.208570
ddd.org 0.161038
$ python3 random_surfer.py 10000000 < routes-graph.txt
Der Graph hat 3189 Knoten/Seiten.
Die Seiten mit den hochsten PageRanks sind:
DFW 0.005612
PEK 0.005186
IST 0.005094
CDG 0.004993
DME 0.004844
SIN 0.004727
JFK 0.004698
ATL 0.004663
MIA 0.004661
LAX 0.004630Berechnung des PageRank 1.6.18
Selbst beim kleinen Netzwerk GraphVL05.txt mit 5 Knoten und 10 Kanten gibt es nach 100000 Rundendes Random Surfers recht unterschiedliche Ergebnisse.
# python3 random_surfer.py 100000 < GraphVL05.txt
Das Netzwerk hat 5 Knoten/Seiten.
Die Seiten mit den hochsten PageRanks sind:
ccc.edu 0.210810
eee.eu 0.209920
aaa.de 0.209660
bbb.com 0.207620
ddd.org 0.161990
ccc.edu 0.211200
bbb.com 0.210670
eee.eu 0.210380
aaa.de 0.207840
ddd.org 0.159910
ccc.edu 0.212120
eee.eu 0.210000
bbb.com 0.209340
aaa.de 0.208050
ddd.org 0.160490
Es mussten also noch viel mehr Runden durchlaufen werden, bis das Ergebnis”zuverlassig“ ist.
Wie bei der Frisbee-Simulation (Vorlesung 04) erreicht man schnell gut Ergebnisse mittels wiederholtemQuadrieren der Matrix mit den Ubergangswahrscheinlichkeiten des Random Surfers zwischen den Seiten . . .
Berechnung des PageRank 1.6.19
Wiederverwendung von Programmteilen
Um die Ubungen zu losen, muss man ein Netzwerk aus einer Datei einlesen konnen – das macht
der Programmabschnitt auf Seite 15 dieser Vorlesung.
Dazu kann man diesen Programmabschnitt in einer eigenen Datei speichern.
Wir machen das in der Datei netzwerkEinlesen.py
Dort steht jetzt also ein Programm,
das ein Netzwerk von standard input liest und im Dictionary nachfolger speichert.
1.6.20
# netzwerkEinlesen.py
#----------------------------------------------------------------------------------------
# Lies das Netzwerk von standard input (z.B. aus Datei routes-graph.txt).
# Jede Zeile ist ein Link und besteht aus 2 Strings, die durch Leerzeichen getrennt sind.
# Der erste String ist die Startseite und der zweite die Zielseite.
# nachfolger ist ein Dictionary, dessen Schlussel alle Seiten sind.
# Der Wert eines Schlussels/Seite ist ein Array mit allen Zielseiten der Seite.
# In der Eingabe mehrfach vorgekommene Zielseiten einer Seite
# kommen auch in dem Array mehrfach vor.
#----------------------------------------------------------------------------------------
import sys
nachfolger = dict()
for zeile in sys.stdin:
startUndZiel = str.split(zeile)
if len(startUndZiel)!=2: continue
startseite = str.strip(startUndZiel[0])
zielseite = str.strip(startUndZiel[1])
# Falls eine Seite noch nicht im Dictionary ist, wird sie dort eingetragen.
if startseite not in nachfolger: nachfolger[startseite] = []
if zielseite not in nachfolger: nachfolger[zielseite] = []
# Die zielseite wird als Nachfolger der startseite in das Werte-Array eingetragen.
nachfolger[startseite] += [zielseite]
1.6.21
Wir schreiben jetzt ein Programm netzwerkZaehlen.py,
das zahlt, wieviele Seiten und Links in dem Netzwerk sind.
Die Seitenzahl ist die Lange von nachfolger,
und die Linkzahl ist die Summe der Langen der Werte in nachfolger.
Dabei soll das Netzwerk von netzwerkEinlesen.py eingelesen werden.
Zuerst importiert das Programm netzwerkEinlesen.py.
Dadurch wird netzwerkEinlesen.py ausgefuhrt und dort das Dictionary nachfolger erzeugt.
Anschließend benutzt das Programm die Variable nachfolger aus netzwerkEinlesen.py
als netzwerkEinlesen.nachfolger.
Diese Losung ist nur ein”Krucke“ – wie es schoner geht, kommt in der nachsten Vorlesung.
1.6.22
import netzwerkEinlesen
anzahlLinks = 0
for s in netzwerkEinlesen.nachfolger:
anzahlLinks += len(netzwerkEinlesen.nachfolger[s])
print( 'Das Netzwerk hat %d Seiten und %d Links.' % (len(netzwerkEinlesen.nachfolger), anzahlLinks) )
#------------------------------------------------------------------------------------------------------
# python3 netzwerkZaehlen.py < NetzwerkVL07.txt
# Das Netzwerk hat 5 Seiten und 10 Links.
#
# python3 netzwerkZaehlen.py < routes-graph.txt
# Das Netzwerk hat 3189 Seiten und 53066 Links.
#-------------------------------------------------------------------------------------------------------
1.6.23
import netzwerkEinlesen
anzahlLinks = 0
for s in netzwerkEinlesen.nachfolger:
anzahlLinks += len(netzwerkEinlesen.nachfolger[s])
print( 'Das Netzwerk hat %d Seiten und %d Links.' % (len(netzwerkEinlesen.nachfolger), anzahlLinks) )
#------------------------------------------------------------------------------------------------------
# python3 netzwerkZaehlen.py < NetzwerkVL07.txt
# Das Netzwerk hat 5 Seiten und 10 Links.
#
# python3 netzwerkZaehlen.py < routes-graph.txt
# Das Netzwerk hat 3189 Seiten und 53066 Links.
#-------------------------------------------------------------------------------------------------------
Man kann die Variable nachfolger auch direkt benutzen, wenn man das erlaubt.
from netzwerkEinlesen import nachfolger
anzahlLinks = 0
for s in nachfolger:
anzahlLinks += len(nachfolger[s])
print( 'Das Netzwerk hat %d Seiten und %d Links.' % (len(nachfolger), anzahlLinks) )
1.6.23
import netzwerkEinlesen
anzahlLinks = 0
for s in netzwerkEinlesen.nachfolger:
anzahlLinks += len(netzwerkEinlesen.nachfolger[s])
print( 'Das Netzwerk hat %d Seiten und %d Links.' % (len(netzwerkEinlesen.nachfolger), anzahlLinks) )
#------------------------------------------------------------------------------------------------------
# python3 netzwerkZaehlen.py < NetzwerkVL07.txt
# Das Netzwerk hat 5 Seiten und 10 Links.
#
# python3 netzwerkZaehlen.py < routes-graph.txt
# Das Netzwerk hat 3189 Seiten und 53066 Links.
#-------------------------------------------------------------------------------------------------------
Man kann die Variable nachfolger auch umbenennen.
from netzwerkEinlesen import nachfolger as graph
anzahlLinks = 0
for s in graph:
anzahlLinks += len(graph[s])
print( 'Das Netzwerk hat %d Seiten und %d Links.' % (len(graph), anzahlLinks) )
1.6.23
Zusammenfassung
§ Wir haben gesehen, dass man mit den bisher erlernten Mitteln bereits Programme fur
interessante Probleme schreiben kann.
§ Das Programm ist ein Beispiel fur ein datengetriebenes Programm.
Solche Programme werden haufig verwendet.
Wir konnen verschiedene Arten, Graphen zu speichern, in die von unseren Programmen
benutzte Art uberfuhren.
§ Es ist nicht immer leicht, ein fehlerfreies Programm zu schreiben.
Die Uberprufung, dass ein Programm fehlerfrei ist, erfordert grundliche Arbeit.
§ Es ist nicht immer leicht, ein schnelles Programm zu schreiben.
Die schnelle Berechnung von PageRanks großer Graphen erfordert spezielle Kenntnisse in Linearer Algebra und
Numerik.
1.6.24
2 Funktionen und Module
Funktionen erlauben (mehr als Verzweigungen und Schleifen) den Programmfluss zwischen
verschiedenen Stellen des Programmcodes hin und her springen zu lassen. Sie machen es auch
moglich, den gleichen Programmcode an verschiedenen Stellen des Programms wiederzubenutzen.
Schließlich kann man Funktionen in Module auslagern, so dass der gleiche Programmcode in
verschiedenen Programmen (Klienten) benutzt werden kann.
Die Moglichkeit, Funktionen rekursiv zu definieren, liefert eine neue Sicht auf Strukturen in
Problemen, die man mit Programmen losen will.
1. Elemente des Programmierens
2. Funktionen und Module
2.1 Definition von Funktionen
2.2 Module und Klienten
2.3 Rekursion
3. Objekt-orientierte Programmierung (erste Schritte)
4. Algorithmen
2.0.1
Vorlesung 08
2. Funktionen und Module
2.1 Definition von FunktionenDefinition von Funktionen und Gultigkeitsbereiche von Variablen
Wirkung von Funktionsaufrufen auf Argument-Variablen
Abschlussbeispiel: Bilder mit einem Stift malen
Anhang: Sortieren durch Minimum-Suche
2.2 Module und Klienten
2.3 Rekursion
2.1.1
2.1 Wie man Funktionen definiert
Wir haben bereits verschiedene Funktionen benutzt:
int(sys.argv[1])
print( '%d %.2f' % (jahr, t) )
math.sqrt(5)
random.randrange(1,7)
random.random()
stddraw.line(1,2, 0.1,0.2)
Aufgaben eines Programms, die klar abgegrenzt sind,
sollte man auch abgrenzen und z.B. als Funktion aufschreiben.
Dadurch bekommt der Programmcode eine bessere Struktur.
Entwicklung, Fehlersuche, Wartung und Wiederbenutzung werden einfacher.
2.1.2
1 Definition von Funktionen und Gultigkeitsbereiche von VariablenBeispiel: Der ganzzahlige 2er-Logarithmus
Der ganzzahlige 2er-Logarithmus einer ganzen Zahl ist die Anzahl,
wie oft man die Zahl ganzzahlig durch 2 teilen kann, bis 1 herauskommt.
345 hat den ganzzahligen 2er-Logarithmus 8.
28loomoon
256
ď 345 ă 29loomoon
512
Der ganzzahlige 2er-Logarithmus ist also eine Funktion,
die ein Argument auf einen Wert abbildet.
n n//2 Anzahl
345 172 1
172 86 2
86 43 3
43 21 4
21 10 5
10 5 6
5 2 7
2 1 8
Aufgabe:
schreibe ein Programm,
das den ganzzahligen 2er-Logarithmus jeder uber die Kommandozeile eingegebenen Zahl ausgibt.Eine Funktion zur Berechnung des ganzzahligen 2er-Logarithmus 2.1.3
#--------------------------------------------------------------
# logarithmen.py
#--------------------------------------------------------------
# Liest die Argumente (int) von der Kommandozeile
# und gibt jeweils den ganzzahligen 2er-Logarithmus dazu aus.
#--------------------------------------------------------------
import sys
# Die Funktion logd(n) wird definiert.
# logd(n) gibt den ganzzahligen 2er-Logarithmus von n zuruck.
# Der ganzzahlige 2er-Logarithmus einer Zahl ist die
# Anzahl, wie oft man die Zahl ganzzahlig durch 2 teilen kann,
# bis 1 erreicht wird.
def logd(n):
anzahl = 0
while n>1:
n = n//2
anzahl += 1
return anzahl
# -------- Hauptprogramm ------------------------------------
# Es werden die Eingaben von der Kommandozeile gelesen
# und fur jede Eingabe wird der Logarithmus ausgegeben.
for i in range (1,len(sys.argv)):
argument = int(sys.argv[i])
wert = logd(argument)
print( 'logd(%d) = %d' % (argument, wert) )
#--------------------------------------------------------------
Eine Funktion zur Berechnung des ganzzahligen 2er-Logarithmus 2.1.4
#--------------------------------------------------------------
# logarithmen.py
#--------------------------------------------------------------
# Liest die Argumente (int) von der Kommandozeile
# und gibt jeweils den ganzzahligen 2er-Logarithmus dazu aus.
#--------------------------------------------------------------
import sys
# Die Funktion logd(n) wird definiert.
# logd(n) gibt den ganzzahligen 2er-Logarithmus von n zuruck.
# Der ganzzahlige 2er-Logarithmus einer Zahl ist die
# Anzahl, wie oft man die Zahl ganzzahlig durch 2 teilen kann,
# bis 1 erreicht wird.
def logd(n):
anzahl = 0
while n>1:
n = n//2
anzahl += 1
return anzahl
# -------- Hauptprogramm ------------------------------------
# Es werden die Eingaben von der Kommandozeile gelesen
# und fur jede Eingabe wird der Logarithmus ausgegeben.
for i in range (1,len(sys.argv)):
argument = int(sys.argv[i])
wert = logd(argument)
print( 'logd(%d) = %d' % (argument, wert) )
#--------------------------------------------------------------
Was bei der Ausfuhrung von
python logarithmen.py 60 23
(informell) passiert:
i = 1argument = 60
Eine Funktion zur Berechnung des ganzzahligen 2er-Logarithmus 2.1.4
#--------------------------------------------------------------
# logarithmen.py
#--------------------------------------------------------------
# Liest die Argumente (int) von der Kommandozeile
# und gibt jeweils den ganzzahligen 2er-Logarithmus dazu aus.
#--------------------------------------------------------------
import sys
# Die Funktion logd(n) wird definiert.
# logd(n) gibt den ganzzahligen 2er-Logarithmus von n zuruck.
# Der ganzzahlige 2er-Logarithmus einer Zahl ist die
# Anzahl, wie oft man die Zahl ganzzahlig durch 2 teilen kann,
# bis 1 erreicht wird.
def logd(n):
anzahl = 0
while n>1:
n = n//2
anzahl += 1
return anzahl
# -------- Hauptprogramm ------------------------------------
# Es werden die Eingaben von der Kommandozeile gelesen
# und fur jede Eingabe wird der Logarithmus ausgegeben.
for i in range (1,len(sys.argv)):
argument = int(sys.argv[i])
wert = logd(argument)
print( 'logd(%d) = %d' % (argument, wert) )
#--------------------------------------------------------------
Was bei der Ausfuhrung von
python logarithmen.py 60 23
(informell) passiert:
i = 1argument = 60
logd(argument)
n = 60
anzahl = 0
n = 30
anzahl = 1
n = 15
anzahl = 2
n = 7
anzahl = 3
n = 3
anzahl = 4
n = 1
anzahl = 5
return 5
Eine Funktion zur Berechnung des ganzzahligen 2er-Logarithmus 2.1.4
#--------------------------------------------------------------
# logarithmen.py
#--------------------------------------------------------------
# Liest die Argumente (int) von der Kommandozeile
# und gibt jeweils den ganzzahligen 2er-Logarithmus dazu aus.
#--------------------------------------------------------------
import sys
# Die Funktion logd(n) wird definiert.
# logd(n) gibt den ganzzahligen 2er-Logarithmus von n zuruck.
# Der ganzzahlige 2er-Logarithmus einer Zahl ist die
# Anzahl, wie oft man die Zahl ganzzahlig durch 2 teilen kann,
# bis 1 erreicht wird.
def logd(n):
anzahl = 0
while n>1:
n = n//2
anzahl += 1
return anzahl
# -------- Hauptprogramm ------------------------------------
# Es werden die Eingaben von der Kommandozeile gelesen
# und fur jede Eingabe wird der Logarithmus ausgegeben.
for i in range (1,len(sys.argv)):
argument = int(sys.argv[i])
wert = logd(argument)
print( 'logd(%d) = %d' % (argument, wert) )
#--------------------------------------------------------------
Was bei der Ausfuhrung von
python logarithmen.py 60 23
(informell) passiert:
i = 1argument = 60
logd(argument)
n = 60
anzahl = 0
n = 30
anzahl = 1
n = 15
anzahl = 2
n = 7
anzahl = 3
n = 3
anzahl = 4
n = 1
anzahl = 5
return 5
wert = 5
print('logd(60) = 5')
Eine Funktion zur Berechnung des ganzzahligen 2er-Logarithmus 2.1.4
#--------------------------------------------------------------
# logarithmen.py
#--------------------------------------------------------------
# Liest die Argumente (int) von der Kommandozeile
# und gibt jeweils den ganzzahligen 2er-Logarithmus dazu aus.
#--------------------------------------------------------------
import sys
# Die Funktion logd(n) wird definiert.
# logd(n) gibt den ganzzahligen 2er-Logarithmus von n zuruck.
# Der ganzzahlige 2er-Logarithmus einer Zahl ist die
# Anzahl, wie oft man die Zahl ganzzahlig durch 2 teilen kann,
# bis 1 erreicht wird.
def logd(n):
anzahl = 0
while n>1:
n = n//2
anzahl += 1
return anzahl
# -------- Hauptprogramm ------------------------------------
# Es werden die Eingaben von der Kommandozeile gelesen
# und fur jede Eingabe wird der Logarithmus ausgegeben.
for i in range (1,len(sys.argv)):
argument = int(sys.argv[i])
wert = logd(argument)
print( 'logd(%d) = %d' % (argument, wert) )
#--------------------------------------------------------------
Was bei der Ausfuhrung von
python logarithmen.py 60 23
(informell) passiert:
i = 1argument = 60
logd(argument)
...
return 5
wert = 5
print('logd(60) = 5')
Eine Funktion zur Berechnung des ganzzahligen 2er-Logarithmus 2.1.4
#--------------------------------------------------------------
# logarithmen.py
#--------------------------------------------------------------
# Liest die Argumente (int) von der Kommandozeile
# und gibt jeweils den ganzzahligen 2er-Logarithmus dazu aus.
#--------------------------------------------------------------
import sys
# Die Funktion logd(n) wird definiert.
# logd(n) gibt den ganzzahligen 2er-Logarithmus von n zuruck.
# Der ganzzahlige 2er-Logarithmus einer Zahl ist die
# Anzahl, wie oft man die Zahl ganzzahlig durch 2 teilen kann,
# bis 1 erreicht wird.
def logd(n):
anzahl = 0
while n>1:
n = n//2
anzahl += 1
return anzahl
# -------- Hauptprogramm ------------------------------------
# Es werden die Eingaben von der Kommandozeile gelesen
# und fur jede Eingabe wird der Logarithmus ausgegeben.
for i in range (1,len(sys.argv)):
argument = int(sys.argv[i])
wert = logd(argument)
print( 'logd(%d) = %d' % (argument, wert) )
#--------------------------------------------------------------
Was bei der Ausfuhrung von
python logarithmen.py 60 23
(informell) passiert:
i = 1argument = 60
logd(argument)
...
return 5
wert = 5
print('logd(60) = 5')
i = 2
argument = 23
Eine Funktion zur Berechnung des ganzzahligen 2er-Logarithmus 2.1.4
#--------------------------------------------------------------
# logarithmen.py
#--------------------------------------------------------------
# Liest die Argumente (int) von der Kommandozeile
# und gibt jeweils den ganzzahligen 2er-Logarithmus dazu aus.
#--------------------------------------------------------------
import sys
# Die Funktion logd(n) wird definiert.
# logd(n) gibt den ganzzahligen 2er-Logarithmus von n zuruck.
# Der ganzzahlige 2er-Logarithmus einer Zahl ist die
# Anzahl, wie oft man die Zahl ganzzahlig durch 2 teilen kann,
# bis 1 erreicht wird.
def logd(n):
anzahl = 0
while n>1:
n = n//2
anzahl += 1
return anzahl
# -------- Hauptprogramm ------------------------------------
# Es werden die Eingaben von der Kommandozeile gelesen
# und fur jede Eingabe wird der Logarithmus ausgegeben.
for i in range (1,len(sys.argv)):
argument = int(sys.argv[i])
wert = logd(argument)
print( 'logd(%d) = %d' % (argument, wert) )
#--------------------------------------------------------------
Was bei der Ausfuhrung von
python logarithmen.py 60 23
(informell) passiert:
i = 1argument = 60
logd(argument)
...
return 5
wert = 5
print('logd(60) = 5')
i = 2
argument = 23
logd(argument)
n = 23
anzahl = 0
n = 11
anzahl = 1
n = 5
anzahl = 2
n = 2
anzahl = 3
n = 1
anzahl = 4
return 4
Eine Funktion zur Berechnung des ganzzahligen 2er-Logarithmus 2.1.4
#--------------------------------------------------------------
# logarithmen.py
#--------------------------------------------------------------
# Liest die Argumente (int) von der Kommandozeile
# und gibt jeweils den ganzzahligen 2er-Logarithmus dazu aus.
#--------------------------------------------------------------
import sys
# Die Funktion logd(n) wird definiert.
# logd(n) gibt den ganzzahligen 2er-Logarithmus von n zuruck.
# Der ganzzahlige 2er-Logarithmus einer Zahl ist die
# Anzahl, wie oft man die Zahl ganzzahlig durch 2 teilen kann,
# bis 1 erreicht wird.
def logd(n):
anzahl = 0
while n>1:
n = n//2
anzahl += 1
return anzahl
# -------- Hauptprogramm ------------------------------------
# Es werden die Eingaben von der Kommandozeile gelesen
# und fur jede Eingabe wird der Logarithmus ausgegeben.
for i in range (1,len(sys.argv)):
argument = int(sys.argv[i])
wert = logd(argument)
print( 'logd(%d) = %d' % (argument, wert) )
#--------------------------------------------------------------
Was bei der Ausfuhrung von
python logarithmen.py 60 23
(informell) passiert:
i = 1argument = 60
logd(argument)
...
return 5
wert = 5
print('logd(60) = 5')
i = 2
argument = 23
logd(argument)
n = 23
anzahl = 0
n = 11
anzahl = 1
n = 5
anzahl = 2
n = 2
anzahl = 3
n = 1
anzahl = 4
return 4
wert = 4
print('logd(23) = 4')
Eine Funktion zur Berechnung des ganzzahligen 2er-Logarithmus 2.1.4
Definition von Funktionen
def logd( n ):
anzahl = 0
while n>1:
n = n//2
anzahl += 1
return anzahl
Signatur Funktionsname
Parameter-Variable
Funktions-Rumpf
lokale Variable
return-Anweisung
RuckgabewertProgrammcode zur Definition und zum Aufruf von Funktionen 2.1.5
Aufruf von Funktionen
for i in range(1, len(sys.argv)):
argument = int(sys.argv[i])
wert = logd( argument )
print('logd(%d)=%d' % (argument,wert))
Funktions-Aufruf
Funktionsname Argument
Programmcode zur Definition und zum Aufruf von Funktionen 2.1.6
Gultigkeitsbereich (scope) von Variablen (1)
def logd(n):
anzahl = 0
while n>1:
n = n//2
anzahl += 1
return anzahl
for i in range(1,len(sys.argv)):
argument = int(sys.argv[i])
wert = logd(argument)
print('logd(%d)=%d' % (argument,wert))
Gultigkeitsbereich der Variablen
i, argument und wert
Gultigkeitsbereich der lokalen Variablen
n und anzahl
n und anzahl sind hier unbekannt
i und argument konnen hier nicht verandert werden, wert ist unbekannt
Gultigkeitsbereiche von Variablen 2.1.7
Gultigkeitsbereich (scope) von Variablen (2)
def logd(n):
i = 0
while n>1:
n = n//2
i += 1
return i
for i in range(1,len(sys.argv)):
argument = int(sys.argv[i])
wert = logd(argument)
print('logd(%d)=%d' % (argument,wert))
Gultigkeitsbereich von i,
argument und wert
Gultigkeitsbereich der lokalen Variablen
n und i
zwei verschiedene
Variablen
n ist hier unbekannt
argument kann nicht verandert werden, wert ist unbekannt
Gultigkeitsbereiche von Variablen 2.1.8
Beispiel: PrimzahlenFunktion mit mehreren return-Anweisungen
Aufgabe: schreibe ein Programm, das Zahlen von der Kommandozeile einliest
und ausgibt, ob sie Primzahlen sind.
Eine Zahl n ą 1 ist eine Primzahl,
wenn sie keinen Teiler außer 1 und n hat.
Es reicht, fur n ą 1 zu testen,
ob eine der Zahlen 2, 3, 4, . . . , n ´ 1 Teiler von n ist.
Wenn man eine solche Zahl findet, dann ist n keine Primzahl.
Wenn man keine solche Zahl findet, dann ist n eine Primzahl.
Wenn n einen Teiler im Bereich 2, 3, . . . , n ´ 1 hat,
dann ist n “ a ¨ b fur a und b aus dem Bereich 2, 3, 4, . . . , n ´ 1.
Fur a ď b gilt: a ď?n.
Also reicht es, einen Teiler von n im Bereich 2, 3, . . . ,?n zu suchen. Eine Funktion zum Primzahltest 2.1.9
Beispiel: PrimzahlenFunktion mit mehreren return-Anweisungen
Aufgabe: schreibe ein Programm, das Zahlen von der Kommandozeile einliest
und ausgibt, ob sie Primzahlen sind.
Eine Zahl n ą 1 ist eine Primzahl,
wenn sie keinen Teiler außer 1 und n hat.
Es reicht, fur n ą 1 zu testen,
ob eine der Zahlen 2, 3, 4, . . . , n ´ 1 Teiler von n ist.
Wenn man eine solche Zahl findet, dann ist n keine Primzahl.
Wenn man keine solche Zahl findet, dann ist n eine Primzahl.
Wenn n einen Teiler im Bereich 2, 3, . . . , n ´ 1 hat,
dann ist n “ a ¨ b fur a und b aus dem Bereich 2, 3, 4, . . . , n ´ 1.
Fur a ď b gilt: a ď?n.
Also reicht es, einen Teiler von n im Bereich 2, 3, . . . ,?n zu suchen. Eine Funktion zum Primzahltest 2.1.9
Beispiel: PrimzahlenFunktion mit mehreren return-Anweisungen
Aufgabe: schreibe ein Programm, das Zahlen von der Kommandozeile einliest
und ausgibt, ob sie Primzahlen sind.
Eine Zahl n ą 1 ist eine Primzahl,
wenn sie keinen Teiler außer 1 und n hat.
Es reicht, fur n ą 1 zu testen,
ob eine der Zahlen 2, 3, 4, . . . , n ´ 1 Teiler von n ist.
Wenn man eine solche Zahl findet, dann ist n keine Primzahl.
Wenn man keine solche Zahl findet, dann ist n eine Primzahl.
Wenn n einen Teiler im Bereich 2, 3, . . . , n ´ 1 hat,
dann ist n “ a ¨ b fur a und b aus dem Bereich 2, 3, 4, . . . , n ´ 1.
Fur a ď b gilt: a ď?n.
Also reicht es, einen Teiler von n im Bereich 2, 3, . . . ,?n zu suchen. Eine Funktion zum Primzahltest 2.1.9
# primzahlen.py
#------------------------------------------------------------
# Liest Argumente von der Kommandozeile
# und gibt aus, ob sie Primzahlen sind.
#------------------------------------------------------------
import sys
# Funktion istPrimzahl(n) erhalt als Argument int n
# und hat Ruckgabewert True, falls n eine Primzahl ist,
# sowie Ruckgabewert False, falls n keine Primzahl ist.
def istPrimzahl( n ):
# Jede Primzahl ist >= 2.
if n<2: return False
# Teste mogliche Teiler t = 2, ... , sqrt(n).
t = 2
while t*t<=n:
# Falls t Teiler von n ist, dann ist n keine Primzahl.
if n%t==0: return False
# Sonst: nimm das nachste t.
t += 1
# Es wurde kein Teiler gefunden: also ist n Primzahl.
return True
Eine Funktion zum Primzahltest 2.1.10
# primzahlen.py
#------------------------------------------------------------
# Liest Argumente von der Kommandozeile
# und gibt aus, ob sie Primzahlen sind.
#------------------------------------------------------------
import sys
# Funktion istPrimzahl(n) erhalt als Argument int n
# und hat Ruckgabewert True, falls n eine Primzahl ist,
# sowie Ruckgabewert False, falls n keine Primzahl ist.
def istPrimzahl( n ):
# Jede Primzahl ist >= 2.
if n<2: return False
# Teste mogliche Teiler t = 2, ... , sqrt(n).
t = 2
while t*t<=n:
# Falls t Teiler von n ist, dann ist n keine Primzahl.
if n%t==0: return False
# Sonst: nimm das nachste t.
t += 1
# Es wurde kein Teiler gefunden: also ist n Primzahl.
return True
Was bei der Ausfuhrung von
istPrimzahl(15)
(informell) passiert:
istPrimzahl(15)
n = 15
t = 2
"2*2<=15 ist True"
"15%2==0 ist False"
t = 3
"3*3<=15 ist True"
"15%3==0 ist True"
return False
Eine Funktion zum Primzahltest 2.1.10
# primzahlen.py
#------------------------------------------------------------
# Liest Argumente von der Kommandozeile
# und gibt aus, ob sie Primzahlen sind.
#------------------------------------------------------------
import sys
# Funktion istPrimzahl(n) erhalt als Argument int n
# und hat Ruckgabewert True, falls n eine Primzahl ist,
# sowie Ruckgabewert False, falls n keine Primzahl ist.
def istPrimzahl( n ):
# Jede Primzahl ist >= 2.
if n<2: return False
# Teste mogliche Teiler t = 2, ... , sqrt(n).
t = 2
while t*t<=n:
# Falls t Teiler von n ist, dann ist n keine Primzahl.
if n%t==0: return False
# Sonst: nimm das nachste t.
t += 1
# Es wurde kein Teiler gefunden: also ist n Primzahl.
return True
Was bei der Ausfuhrung von
istPrimzahl(13)
(informell) passiert:
istPrimzahl(13)
n = 13
t = 2
"2*2<=13 ist True"
"13%2==0 ist False"
t = 3
"3*3<=13 ist True"
"13%3==0 ist False"
t = 4
"4*4<=13 ist False"
return True
Eine Funktion zum Primzahltest 2.1.10
# -------- Hauptprogramm --------------------------------
# Lies die Zahlen von der Kommandozeile
# und gib aus, ob sie Primzahlen sind.
for i in range(1,len(sys.argv)):
argument = int(sys.argv[i])
if istPrimzahl(argument):
print( '%d ist Primzahl.' % (argument) )
else:
print( '%d ist keine Primzahl.' % (argument) )
#-----------------------------------------------------------
# python primzahlen.py 0 1 2 3 4 5 12 13 14 15 16 17
# 0 ist keine Primzahl.
# 1 ist keine Primzahl.
# 2 ist Primzahl.
# 3 ist Primzahl.
# 4 ist keine Primzahl.
# 5 ist Primzahl.
# 12 ist keine Primzahl.
# 13 ist Primzahl.
# 14 ist keine Primzahl.
# 15 ist keine Primzahl.
# 16 ist keine Primzahl.
# 17 ist Primzahl.
Eine Funktion zum Primzahltest 2.1.11
2 Wirkung von Funktionsaufrufen auf Argument-Variablen
Beispielprogramm:
def inc(j):
j += 1
i = 99
inc(i)
Informeller Programmablauf:
i = 99
inc(i)
j = 99
j = 100
Argumente sind Objekt-Referenzen.
Programmablauf auf dem Objekt-Level:
i = 99 99i
Aufruf inc(i) 99i
j
j += 1 99
1
100
i
j
Nach der Ausfuhrung 99
1
100
i
Wirkung von Fuktionsaufrufen auf Variablen 2.1.12
2 Wirkung von Funktionsaufrufen auf Argument-Variablen
Beispielprogramm:
def inc(j):
j += 1
i = 99
inc(i)
Informeller Programmablauf:
i = 99
inc(i)
j = 99
j = 100
Argumente sind Objekt-Referenzen.
Programmablauf auf dem Objekt-Level:
i = 99 99i
Aufruf inc(i) 99i
j
j += 1 99
1
100
i
j
Nach der Ausfuhrung 99
1
100
i
Wirkung von Fuktionsaufrufen auf Variablen 2.1.12
2 Wirkung von Funktionsaufrufen auf Argument-Variablen
Beispielprogramm:
def inc(j):
j += 1
i = 99
inc(i)
Informeller Programmablauf:
i = 99
inc(i)
j = 99
j = 100
Argumente sind Objekt-Referenzen.
Programmablauf auf dem Objekt-Level:
i = 99 99i
Aufruf inc(i) 99i
j
j += 1 99
1
100
i
j
Nach der Ausfuhrung 99
1
100
i
Wirkung von Fuktionsaufrufen auf Variablen 2.1.12
2 Wirkung von Funktionsaufrufen auf Argument-Variablen
Beispielprogramm:
def inc(j):
j += 1
i = 99
inc(i)
Informeller Programmablauf:
i = 99
inc(i)
j = 99
j = 100
Argumente sind Objekt-Referenzen.
Programmablauf auf dem Objekt-Level:
i = 99 99i
Aufruf inc(i) 99i
j
j += 1 99
1
100
i
j
Nach der Ausfuhrung 99
1
100
i
Wirkung von Fuktionsaufrufen auf Variablen 2.1.12
Ubergabe des Ergebnisses nach Funktionsausfuhrung
Beispielprogramm:
def inc(j):
j += 1
return j
i = 99
i = inc(i)
Informeller Programmablauf:
i = 99
inc(i)
j = 99
j = 100
i = 100
Ruckgabewerte sind Objekt-Referenzen.
Programmablauf auf dem Objekt-Level:
i = 99 99i
Aufruf inc(i) 99i
j
j += 1 99
1
100
i
j
Nach der Ausfuhrung 99
1
100
i
Wirkung von Fuktionsaufrufen auf Variablen 2.1.13
Ubergabe des Ergebnisses nach Funktionsausfuhrung
Beispielprogramm:
def inc(j):
j += 1
return j
i = 99
i = inc(i)
Informeller Programmablauf:
i = 99
inc(i)
j = 99
j = 100
i = 100
Ruckgabewerte sind Objekt-Referenzen.
Programmablauf auf dem Objekt-Level:
i = 99 99i
Aufruf inc(i) 99i
j
j += 1 99
1
100
i
j
Nach der Ausfuhrung 99
1
100
i
Wirkung von Fuktionsaufrufen auf Variablen 2.1.13
Ubergabe des Ergebnisses nach Funktionsausfuhrung
Beispielprogramm:
def inc(j):
j += 1
return j
i = 99
i = inc(i)
Informeller Programmablauf:
i = 99
inc(i)
j = 99
j = 100
i = 100
Ruckgabewerte sind Objekt-Referenzen.
Programmablauf auf dem Objekt-Level:
i = 99 99i
Aufruf inc(i) 99i
j
j += 1 99
1
100
i
j
Nach der Ausfuhrung 99
1
100
i
Wirkung von Fuktionsaufrufen auf Variablen 2.1.13
Ubergabe des Ergebnisses nach Funktionsausfuhrung
Beispielprogramm:
def inc(j):
j += 1
return j
i = 99
i = inc(i)
Informeller Programmablauf:
i = 99
inc(i)
j = 99
j = 100
i = 100
Ruckgabewerte sind Objekt-Referenzen.
Programmablauf auf dem Objekt-Level:
i = 99 99i
Aufruf inc(i) 99i
j
j += 1 99
1
100
i
j
Nach der Ausfuhrung 99
1
100
i
Wirkung von Fuktionsaufrufen auf Variablen 2.1.13
Seiteneffekte bei Argumenten eines veranderbaren Datentyps
def tausche(b, i, j):
temp = b[i]
b[i] = b[j]
b[j] = temp
a = [ 17, 4, 21 ]
tausche(a, 0, 1)
a = [17, 4, 21]
17 4 21
0 1 2
3a
Wirkung von Fuktionsaufrufen auf Variablen 2.1.14
Seiteneffekte bei Argumenten eines veranderbaren Datentyps
def tausche(b, i, j):
temp = b[i]
b[i] = b[j]
b[j] = temp
a = [ 17, 4, 21 ]
tausche(a, 0, 1)
a = [17, 4, 21]
17 4 21
0 1 2
3a
Aufruf von tausche(a,0,1)
17 4 21
0 1 2
3a
b
0 1i j
Wirkung von Fuktionsaufrufen auf Variablen 2.1.14
Seiteneffekte bei Argumenten eines veranderbaren Datentyps
def tausche(b, i, j):
temp = b[i]
b[i] = b[j]
b[j] = temp
a = [ 17, 4, 21 ]
tausche(a, 0, 1)
a = [17, 4, 21]
17 4 21
0 1 2
3a
Aufruf von tausche(a,0,1)
17 4 21
0 1 2
3a
b
0 1i j
temp = b[i]
17 4 21
0 1 2
3a
b
temp
0 1i j
Wirkung von Fuktionsaufrufen auf Variablen 2.1.14
Seiteneffekte bei Argumenten eines veranderbaren Datentyps
def tausche(b, i, j):
temp = b[i]
b[i] = b[j]
b[j] = temp
a = [ 17, 4, 21 ]
tausche(a, 0, 1)
Aufruf von tausche(a,0,1)
17 4 21
0 1 2
3a
b
0 1i j
temp = b[i]
17 4 21
0 1 2
3a
b
temp
0 1i j
b[i] = b[j]
17 4 21
0 1 2
3a
b
temp
0
1
i
j
Wirkung von Fuktionsaufrufen auf Variablen 2.1.14
Seiteneffekte bei Argumenten eines veranderbaren Datentyps
def tausche(b, i, j):
temp = b[i]
b[i] = b[j]
b[j] = temp
a = [ 17, 4, 21 ]
tausche(a, 0, 1)
temp = b[i]
17 4 21
0 1 2
3a
b
temp
0 1i j
b[i] = b[j]
17 4 21
0 1 2
3a
b
temp
0
1
i
j
b[j] = temp
17 4 21
0 1 2
3a
b
temp
0
1
i
j
Wirkung von Fuktionsaufrufen auf Variablen 2.1.14
Seiteneffekte bei Argumenten eines veranderbaren Datentyps
def tausche(b, i, j):
temp = b[i]
b[i] = b[j]
b[j] = temp
a = [ 17, 4, 21 ]
tausche(a, 0, 1)
b[i] = b[j]
17 4 21
0 1 2
3a
b
temp
0
1
i
j
b[j] = temp
17 4 21
0 1 2
3a
b
temp
0
1
i
j
Nach der Ausfuhrung
17 4 21
0 1 2
3a
Wirkung von Fuktionsaufrufen auf Variablen 2.1.14
Ein Funktionsaufruf mit einer Variablen als Argument,
die eine Referenz auf ein Objekt eines unveranderbaren Datentyps ist,
andert das Objekt (und damit den Wert der Variablen) nicht.
Ein Funktionsaufruf mit einer Variablen als Argument,
die eine Referenz auf ein Objekt eines veranderbaren Datentyps ist,
kann das Objekt (und damit den Wert der Variablen) andern.
Wirkung von Fuktionsaufrufen auf Variablen 2.1.15
3 Abschlussbeispiel: Bilder mit einem Stift malen
Idee: Bilder lassen sich mit einem Bleistift malen, indem man wiederholt
§ eine Richtung von 0˝ bis 360˝ einnimmt§ in diese Richtung einen geraden Strich einer bestimmten Lange zeichnet
Bsp.: ein gleichseitiges Dreieck malt man durch:
nimm Richtung 0˝ ein
male einen 10cm langen Strich
drehe die Richtung 120˝ nach links
male einen 10cm langen Strich
drehe die Richtung 120˝ nach links
male einen 10cm langen Strich
n-Ecke mit einem Stift malen 2.1.16
Was ist ein Stift?
Die Daten-Frage
Er hat
§ eine Position auf der Leinwand
§ eine Richtung im Bereich 0˝ . . . 360˝
§ eine Farbe
Um diese Werte zu speichern,
benutzen wir fur jeden Stift ein Dictionary mit den Schlusseln
§ 'position'
§ 'richtung'
§ 'farbe'
n-Ecke mit einem Stift malen 2.1.17
Die Funktionen zum Malen mit einem Stift
Die Funktionen sollen§ einen Stift erzeugen konnen,§ einen Strich mit einem Stift auf die Leinwand von stddraw malen, und§ die Richtung des Stiftes andern konnen.
Operation Beschreibung
neuerStift(p, r, c=stddraw.BLACK)
gibt einen Stift an Position p mit Richtung r˝
und Farbe c (default stddraw.BLACK) zuruck
male(s, laenge, sichtbar=True) Stift s malt einen Strich der Lange
laenge auf die Leinwand; die Position von Stift s wird entsprechend
geandert; falls sichtbar Wert False hat, wird nur die Position des
Stiftes verandert
drehe(s, winkel) Stift s dreht seine Richtung winkel Gradn-Ecke mit einem Stift malen 2.1.18
Was brauchen wir noch?
stddraw.line(a,b, x,y) malt einen Strich von Punkt pa, bq nach Punkt px , yq.
Wir mussen also aus Punkt pa, bq, Winkel α und Strichlange ` den vom Stift beim Malen
erreichten Punkt ausrechnen, um den Strich mit stddraw malen zu konnen.
` ¨ cosα
`` ¨ sinα
pa, bq
α
pa` ` ¨ cosα, b ` ` ¨ sinαq
n-Ecke mit einem Stift malen 2.1.19
nEck.py . . . die Funktionen fur den Stift
# nEck.py
#----------------------------------------------------------------------------------------
# Liest n von der Kommandozeile und malt ein n-Eck mit einem simulierten Stift
# in den Einheitskreis (Kreis mit Radius 1 und Mittelpunkt (0,0)).
#----------------------------------------------------------------------------------------
import sys, stddraw, math
# Zuerst werden Funktionen zum Malen mit einem Stift definiert.
# Ein Stift ist ein Dictionary mit den Attributen 'position', 'richtung' und 'farbe'.
# - position ist ein Koordinaten-Paar (x,y) fur die Position des Stiftes auf der Leinwand
# - richtung ist die Richtung (Winkel 0..360), in die der Stift malt
# - farbe ist seine Farbe
#----------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------
# neuerStift(position, richtung, farbe) gibt ein (neues) Dictionary mit den Schlusseln
# 'position', 'richtung' und 'farbe' zuruck,
# deren Werte durch die Parameter beim Funktionsaufruf gesetzt sind.
def neuerStift(position, richtung, farbe):
s = {}
s['position'] = position
s['richtung'] = richtung
s['farbe'] = farbe
return sn-Ecke mit einem Stift malen 2.1.20
#----------------------------------------------------------------------------------------
# drehe(stift, delta) dreht stift um delta Grad.
def drehe(stift, delta):
stift['richtung'] = (stift['richtung'] + delta) % 360
#----------------------------------------------------------------------------------------
# ziel(start, laenge, winkel) gibt den Punkt zuruck,
# den man vom Punkt start mit Winkel winkel in Lange laenge erreicht.
def ziel(start, laenge, winkel):
x_ziel = start[0] + laenge * math.cos(math.radians(winkel))
y_ziel = start[1] + laenge * math.sin(math.radians(winkel))
return (x_ziel, y_ziel)
#----------------------------------------------------------------------------------------
# male(stift, laenge, sichtbar) bewegt stift entlang einer Linie der Lange laenge.
# Falls sichtbar Wert True hat, wird die Linie auf die Leinwand von stddraw gemalt.
# Anderenfalls wird nur die Position des Stiftes verandert und nicht gemalt.
def male(stift, laenge, sichtbar=True):
# Die Linie geht von der jetzigen Position startpunkt des Stiftes
# zu seiner neuen Position.
# Zuerst wird die neue Position zielpunkt berechnet und zur Position des Stiftes.
# Falls gemalt werden soll, wird ein Strich von startpunkt zu zielpunkt gemalt.
startpunkt = stift['position']
zielpunkt = ziel(startpunkt, laenge, stift['richtung'])
stift['position'] = zielpunkt
if sichtbar:
# Male die Linie auf die Leinwand.
stddraw.setPenColor(stift['farbe'])
stddraw.line(startpunkt[0], startpunkt[1], zielpunkt[0], zielpunkt[1])
stddraw.show(100)
n-Ecke mit einem Stift malen 2.1.21
Was wollen wir mit dem Stift malen?
Wir wollen ein Programm schreiben,
das mit einem Stift ein n-Eck malt (n wird eingegeben).
Das n-Eck soll in den Einheitskreis mit Radius 1 und Mittelpunkt p0, 0q gemalt werden.
n-Ecke mit einem Stift malen 2.1.22
72˝
Der Einheitskreis hat Radius 1 und Mittelpunkt p0, 0q.
Ein regelmaßiges n-Eck besteht aus n gleichen
Dreiecken.
Fur ein regelmaßiges n-Eck im Einheitskreis
ist 2α “ 360n (also α “ 180
n).
Es kann im Punkt pcos 180n ,´ sin 180
n q beginnen,
die Stiftrichtung ist dann 90˝, und
die Seitenlange ist 2 ¨ sin 180n .
Nach dem Malen einer Seite wird der Stift um360n
˝gedreht.
n-Ecke mit einem Stift malen 2.1.23
72˝
Der Einheitskreis hat Radius 1 und Mittelpunkt p0, 0q.
Ein regelmaßiges n-Eck besteht aus n gleichen
Dreiecken.
Fur ein regelmaßiges n-Eck im Einheitskreis
ist 2α “ 360n (also α “ 180
n).
Es kann im Punkt pcos 180n ,´ sin 180
n q beginnen,
die Stiftrichtung ist dann 90˝, und
die Seitenlange ist 2 ¨ sin 180n .
Nach dem Malen einer Seite wird der Stift um360n
˝gedreht.
n-Ecke mit einem Stift malen 2.1.23
72˝
α
1
pcosα, sinαq
pcosα,´ sinαq
sinα
Der Einheitskreis hat Radius 1 und Mittelpunkt p0, 0q.
Ein regelmaßiges n-Eck besteht aus n gleichen
Dreiecken.
Fur ein regelmaßiges n-Eck im Einheitskreis
ist 2α “ 360n (also α “ 180
n).
Es kann im Punkt pcos 180n ,´ sin 180
n q beginnen,
die Stiftrichtung ist dann 90˝, und
die Seitenlange ist 2 ¨ sin 180n .
Nach dem Malen einer Seite wird der Stift um360n
˝gedreht.
n-Ecke mit einem Stift malen 2.1.23
nEck.py . . . die Funktionen zum Malen des n-Ecks
# Nun schreiben wir eine Funktion, die das n-Eck malt, und eine Funktion, die die Leinwand vorbereitet.
#--------------------------------------------------------------------------------------------------------------
# male_nEck(n, f=stddraw.BLACK) malt ein regelmaßiges n-Eck mit Farbe f in den Einheitskreis.
def male_nEck(n, f=stddraw.BLACK):
# Die Seitenlange eines regelmaßigen n-Ecks im Einheitskreis ist:
seitenlaenge = 2*math.sin(math.radians(180/n))
# Erzeuge einen Stift mit Farbe f,
# setze ihn auf eine Startposition auf den Einheitskreis, die man von (0,0) im Winkel -1/2 * 360/n erreicht,
# und stelle seine Richtung auf 90 Grad ein.
s = neuerStift( (math.cos(math.radians(180/n)),-math.sin(math.radians(180/n))), 90, f )
# Male mit Stift s ein n-Eck.
for j in range(n):
male(s, seitenlaenge)
drehe(s, 360/n)
#--------------------------------------------------------------------------------------------------------------
# richteLeinwandEin() stellt die Große der Leinwand von stddraw so ein,
# dass der Einheitskreis (das ist der Kreis mit Radius 1 und Mittelpunkt (0,0))
# darauf passt. Der Einheitskreis wird weiß gemalt, der Rest der Leinwand ist schwarz.
def richteLeinwandEin():
stddraw.setCanvasSize(800,800)
stddraw.setXscale(-1,1)
stddraw.setYscale(-1,1)
stddraw.clear(stddraw.BLACK)
stddraw.setPenColor(stddraw.WHITE)
stddraw.filledCircle(0,0,1)
n-Ecke mit einem Stift malen 2.1.24
Das Hauptprogramm von nEck.py
#----------------------------------------------------------------------------------------------------------
# Das Hauptprogramm liest int n von der Kommandozeile. Anschließend wird ein n-Eck gemalt und angezeigt.
n = int(sys.argv[1])
richteLeinwandEin()
stddraw.setPenRadius(0.01)
male_nEck(n, stddraw.BOOK_BLUE)
stddraw.show()
#----------------------------------------------------------------------------------------------------------
python3 nEck.py 5 python3 nEck.py 7 python3 nEck.py 12n-Ecke mit einem Stift malen 2.1.25
Funktionen mit Ruckgabewerten:
neuerStift (Ruckgabewert vom Typ dict)
ziel (Ruckgabewert vom Typ tuple, auch Beispiel fur”mehr als ein Ruckgabewert“)
Funktionen ohne Ruckgabewerte:
drehe(s, delta) hat Seiteneffekt auf Stift s
male(stift, laenge, sichtbar=True) hat Seiteneffekt auf
Stift stift und Leinwand von stddraw
male_nEck(n, f=stddraw.BLACK) hat Seiteneffekt auf Leinwand von stddraw
richteLeinwandEin() hat Seiteneffekt auf Leinwand von stddraw
Funktion mit optionalem Parameter:
male(stift, laenge, sichtbar=True) kann aufgerufen werden durch
male(s, l, t) (Parameter-Variable sichtbar erhalt Wert t) oder
male(s, l) (Parameter-Variable sichtbar erhalt Default-Wert True)
male_nEck(n, f=stddraw.BLACK) kann aufgerufen werden durch
male_nEck(n, c) (Parameter-Variable f erhalt Wert c) oder
male_nEck(n) (Parameter-Variable f erhalt Default-Wert stddraw.BLACK)n-Ecke mit einem Stift malen 2.1.26
Zusammenfassung
§ Durch Definition und Benutzung von Funktionen hat man beim Programmieren neue
Moglichkeiten zum Strukturieren von Programmen.
§ Man muss sich den Ablauf eines Programms nicht mehr Schritt fur Schritt in elementaren
Anweisungen vorstellen, sondern kann abstrakter uber Funktionsaufrufe und Ruckgabewerte
argumentieren.
§ Programme kann man aufschreiben als Definition von Funktionen gefolgt von einem
Hauptprogramm.
§ Der Programmcode wird dadurch einfacher
zu entwickeln, zu verstehen, zu verbessern und zu warten.
§ Dadurch lassen sich auch”kompliziertere“ Anwendungen programmieren.
2.1.27
Anhang: Sortieren eines Arrays durch Minimum-Suchen
Aufgabe:
sortiere beliebig viele Zahlen in aufsteigender Reihenfolge.
Anhang: Sortieren durch Minimum-Suche 2.1.28
Anhang: Sortieren eines Arrays durch Minimum-Suchen
Aufgabe:
sortiere beliebig viele Zahlen in aufsteigender Reihenfolge.
Idee des Sortierens mittels Minimum-Suche:
suche im Array a das kleinste Element
tausche es an die Stelle a[0]
suche im Array a[1:] das kleinste Element
tausche es an die Stelle a[1]
suche im Array a[2:] das kleinste Element
tausche es an die Stelle a[2]
a[0] a[1] a[2] a[3]
16 22 12 18
12 22 16 18
Anhang: Sortieren durch Minimum-Suche 2.1.28
Anhang: Sortieren eines Arrays durch Minimum-Suchen
Aufgabe:
sortiere beliebig viele Zahlen in aufsteigender Reihenfolge.
Idee des Sortierens mittels Minimum-Suche:
suche im Array a das kleinste Element
tausche es an die Stelle a[0]
suche im Array a[1:] das kleinste Element
tausche es an die Stelle a[1]
suche im Array a[2:] das kleinste Element
tausche es an die Stelle a[2]
a[0] a[1] a[2] a[3]
16 22 12 18
12 22 16 18
12 16 22 18
Anhang: Sortieren durch Minimum-Suche 2.1.28
Anhang: Sortieren eines Arrays durch Minimum-Suchen
Aufgabe:
sortiere beliebig viele Zahlen in aufsteigender Reihenfolge.
Idee des Sortierens mittels Minimum-Suche:
suche im Array a das kleinste Element
tausche es an die Stelle a[0]
suche im Array a[1:] das kleinste Element
tausche es an die Stelle a[1]
suche im Array a[2:] das kleinste Element
tausche es an die Stelle a[2]
a[0] a[1] a[2] a[3]
16 22 12 18
12 22 16 18
12 16 22 18
12 16 18 22
Anhang: Sortieren durch Minimum-Suche 2.1.28
Anhang: Sortieren eines Arrays durch Minimum-Suchen
Aufgabe:
sortiere beliebig viele Zahlen in aufsteigender Reihenfolge.
Idee des Sortierens mittels Minimum-Suche:
suche im Array a das kleinste Element
tausche es an die Stelle a[0]
suche im Array a[1:] das kleinste Element
tausche es an die Stelle a[1]
suche im Array a[2:] das kleinste Element
tausche es an die Stelle a[2]
a[0] a[1] a[2] a[3]
16 22 12 18
12 22 16 18
12 16 22 18
12 16 18 22
Etwas formaler:
for i in range(len(a)-1):
suche in a[i:] das kleinste Element a[j]
tausche a[i] und a[j]Anhang: Sortieren durch Minimum-Suche 2.1.28
Anhang: Sortieren eines Arrays durch Minimum-Suchen
Aufgabe:
sortiere beliebig viele Zahlen in aufsteigender Reihenfolge.
Etwas formaler:
for i in range(len(a)-1):
suche in a[i:] das kleinste Element a[j]
tausche a[i] und a[j]
Struktur des Programms:
Funktion zum Suchen des Index des kleinsten Elements im Abschnitt des Arrays
Funktion zum Tauschen zweier Eintrage (gegeben durch Indizes) eines Array
Funktion zum Sortieren eines Arrays
Hauptprogramm zum
Einlesen der Zahlen
Aufruf der Sortier-Funktion
Ausgabe des Ergebnisses
Anhang: Sortieren durch Minimum-Suche 2.1.28
# minsort.py
#-----------------------------------------------------------------------------------------------
# Lies Zahlen (int) von der Kommandozeile und gib sie sortiert in aufsteigender Reihenfolge aus.
#-----------------------------------------------------------------------------------------------
import sys
# tausche(a,i,j) erhalt Array a, int i und int j als Argumente
# und tauscht die Eintrage a[i] und a[j] von a (als Seiteneffekt).
def tausche(a, i, j):
(a[i], a[j]) = (a[j], a[i])
# indexDesMinimums(a,anfang) erhalt Array a und int anfang als Argumente.
# Ruckgabewert ist der Index des kleinsten Eintrags in a[anfang:].
def indexDesMinimums(a, anfang):
indexDesMins = anfang
for i in range(anfang+1,len(a)):
if a[indexDesMins] > a[i] : indexDesMins = i
return indexDesMins
# minSortierung(a) erhalt Array a als Parameter und sortiert a (als Seiteneffekt) aufsteigend.
def minSortierung(a):
for i in range(len(a)-1):
# print(a) # Ausgabe zum Testen des Programms
# Bestimme den Index des kleinsten Elementes in a[i:]
k = indexDesMinimums(a, i)
# Tausche das kleinste Element von a[i:] in a[i].
tausche(a, i, k) Anhang: Sortieren durch Minimum-Suche 2.1.29
#----- Hauptprogramm ---------------------------------------------------
# Kopiere die Zahlen aus der Kommandozeile in ein Array a.
a = []
for i in range(1,len(sys.argv)):
a += [int(sys.argv[i])]
# Sortiere das Array a und gib es aus.
minSortierung(a)
print(a)
#------------------------------------------------------------------------
Aufruf des Programms mit Ausgabe zum Testen:
python minsort.py 2 -2 89 -34 25 -12 -13 13 999 23 15
[2, -2, 89, -34, 25, -12, -13, 13, 999, 23, 15]
[-34, -2, 89, 2, 25, -12, -13, 13, 999, 23, 15]
[-34, -13, 89, 2, 25, -12, -2, 13, 999, 23, 15]
[-34, -13, -12, 2, 25, 89, -2, 13, 999, 23, 15]
[-34, -13, -12, -2, 25, 89, 2, 13, 999, 23, 15]
[-34, -13, -12, -2, 2, 89, 25, 13, 999, 23, 15]
[-34, -13, -12, -2, 2, 13, 25, 89, 999, 23, 15]
[-34, -13, -12, -2, 2, 13, 15, 89, 999, 23, 25]
[-34, -13, -12, -2, 2, 13, 15, 23, 999, 89, 25]
[-34, -13, -12, -2, 2, 13, 15, 23, 25, 89, 999]
[-34, -13, -12, -2, 2, 13, 15, 23, 25, 89, 999]
Aufruf des Programms (ohne Ausgabe zum Testen):
python minsort.py 12 14 27 13 89 45 23 111 1
[1, 12, 13, 14, 23, 27, 45, 89, 111]
Anhang: Sortieren durch Minimum-Suche 2.1.30
3 Objekt-orientierte Programmierung (erste Schritte)
3. Objekt-orientierte Programmierung (erste Schritte)
3.1 Benutzung von Daten-Typen
Vorlesung 10
3. Objekt-orientierte Programmierung (erste Schritte)
3.1 Benutzung von Daten-TypenDatentyp Color
Datentypen fur Strings und Datenstrome
Datentyp Picture
Schreiben wie Goethe oder Schiller
Anhang: Sortieren durch Minimum-Suche 3.1.1
3.1 Benutzung von Datentypen
Datentypen dienen der Speicherung bestimmter Daten
§ Array: Folge beliebiger Daten, Zugriff uber Index
§ Dictionary: (ungeordnete) Menge von Schlusseln und Werten, Zugriff uber Schlussel
§ str: Folge von Zeichen
§ stddraw: Leinwand zum Bemalen
und der Bereitstellung von Funktionen/Methoden zu deren Manipulation
§ Array: z.B. Zuweisung, durchlaufe alle Elemente, finde das Maximum aller Elemente
§ Dictionary: z.B. Zuweisung, durchlaufe alle Elemente
§ str: z.B. Zuweisung, Konkatenation
§ stddraw: z.B. male einen Strich, losche die Leinwand
In dieser Vorlesung wollen wir nochmal ansehen, wie die Benutzung von Datentypen geht.
Im nachsten Semester geht es auch darum, wie man eigene Datentypen implementiert.
Anhang: Sortieren durch Minimum-Suche 3.1.1
1 Der Datentyp Color
Auf der Titelseite der FAZ vom 26.6.2019 stand eine
Graphik uber die Entwicklung der Jahresdurchschnitts-
temperatur an einem nicht genannten Ort seit 1850.
Fur jedes Jahr steht von links nach rechts ein vertikaler
Balken.
Ein weißer Balken steht dafur, dass die
Durschnittstemperatur des Jahres (etwa) das Mittel der
Temperaturen seit 1850 ist. Je weiter die
Jahresdurchschnittstemperatur unter dem Mittelwert liegt,
desto dunkleblauer ist der Ballen,
und je weiter sie uber dem Mittelwert liegt, desto
dunkelroter wird der Balken.
Wir wollen eine solche Graphik fur Jena (oder andere Orte)
malen.Datentyp Color 3.1.2
Eine abstrakte Vorstellung von Farbe
Jede Farbe setzt sich aus rot, grun und blau in unterschiedlichen Intensitaten zusammen.
Bei maximaler Intensitat aller Farben zusammen erhalten wir weiß,
bei minimaler Intensitat schwarz.
Farben werden durch Tripel pr , g , bq angegeben,
bei denen r die Intensitat von rot,
g die Intensitat von grun und
b die Intensitat von blau angibt.
Jede Intensitat ist eine ganze Zahl aus dem Bereich 0 . . . 1.
Datentyp Color 3.1.3
Die API des Datentyps Color in color.py
Color(r,g,b) eine neue Farbe mit Rot-, Grun- und Blau-Bestandteilen r, g und b;
r, g und b sind int-Werte aus dem Bereich 0 . . . 255
c.getRed() der Rot-Bestandteil der Farbe c
c.getGreen() der Grun-Bestandteil der Farbe c
c.getBlue() der Blau-Bestandteil der Farbe c
str(c) Darstellung der Farbe c als String pR,G ,Bq
Color() ist der Konstruktor und erzeugt ein neues Objekt von Typ Color.
getRed(), getGreen() und getBlue() sind Methoden des Datentyps Color.
Sie werden auf Objekte vom Typ Color angewendet.
str() ist eine Funktion, die es fur jeden Datentyp geben soll.
(Es gibt keine Methoden zum Andern eines Color-Objektes.)Datentyp Color 3.1.4
Die API des Moduls stddraw im Buch
Farb-Objekte vom Typ Color konnen
als Farben bei stddraw verwendet
werden.
Datentyp Color 3.1.5
Der Farbverlauf von rot
Color(0, 0, 0) ist schwarz und Color(255, 255, 255) ist weiß.
Ein”richtiges“ rot ist Color(255, 0, 0).
Eine Farbe Color(i, 0, 0) mit 0<i<255 ist ein”dunkleres“ rot:
je kleiner i ist, des dunkler ist das rot.
Eine Farbe Color(255, i, i) mit 0<i<255 ist ein”helleres“ rot:
je großer i ist, desto heller ist das rot.
Wir schreiben ein Programm, das den Farbverlauf vom dunkelsten bis zum hellsten rot malt.
Datentyp Color 3.1.6
# rot_farbverlauf.py
#---------------------------------------------------------------------------------------
# Malt den Farbverlauf von rot in Streifen auf die Leinwand von stddraw.
# Color(0,0,0), Color(1,0,0),...,Color(255,0,0),Color(255,1,1),...,Color(255,255,255)
# Rot-Ton: 0 1 ... 255 256 ... 510
#---------------------------------------------------------------------------------------
import stddraw, color
#---------------------------------------------------------------------------------------
# rot(n) gibt ein Color-Objekt mit Rot-Ton n gemaß der obigen Darstellung zuruck.
def rot(n):
if n<=255: c = color.Color( n, 0, 0 )
else: c = color.Color( 255, n-255, n-255)
return c
#---------------------------------------------------------------------------------------
# Das Hauptprogramm richtet eine Leinwand mit x-Skala 0...510 ein
# und malt fur jedes n in 0...510 einen Streifen mit Farbe rot(n) an x-Position n.
#---------------------------------------------------------------------------------------
def hauptprogramm():
stddraw.setCanvasSize(1200,800)
stddraw.setXscale(0,510)
for i in range(0,511):
c = rot(i)
stddraw.setPenColor(c)
stddraw.filledRectangle(i, 0, 1.4, 1)
stddraw.show()
#----------------------------------------------------------------------------------------------
if __name__=='__main__': hauptprogramm()
#----------------------------------------------------------------------------------------------
Datentyp Color 3.1.7
python3 rot_farbverlauf.py
Hier wurden die Streifen mit Breite 1 gemalt:
stddraw.filledRectangle(i, 0, 1, 1)
Durch Rundungsfehler von stddraw (das Bild ist
1200 Pixel breit und hat 511 ganzzahlige
x-Positionen) werden dabei nicht alle Pixel der
Leinwand bemalt und es entstehen dunne weiße
Streifen, die man nicht haben will.
python3 rot_farbverlauf.py
Hier wurden die Streifen mit Breite 1.4 gemalt:
stddraw.filledRectangle(i, 0, 1.4, 1)
Dadurch werden alle Rundungsfehler ubermalt . . .
Datentyp Color 3.1.8
Farbverlaufe fur alle Farben
Funktionen, die eine der drei Grundfarben rot, grun und blau im angegebenen Ton zuruckgeben,
konnen wir genauso implementieren.
# farbverlaeufe.py
#---------------------------------------------------------------------------------------
# Stellt Funktionen fur Farbverlaufe von rot, blau und grun zur Verfugung.
# Fur rot ist der Verlauf
# Color(0,0,0), Color(1,0,0),...,Color(255,0,0),Color(255,1,1),...,Color(255,255,255)
# Rot-Ton: 0 1 255 256 510
# Fur die anderen Farben ist das entsprechend.
#---------------------------------------------------------------------------------------
import stddraw, color
#---------------------------------------------------------------------------------------
# rot(n) gibt ein Color-Objekt mit Rot-Ton n gemaß der obigen Darstellung zuruck.
def rot(n): return color.Color( min(n,255), max(0,n-255), max(0,n-255) )
#---------------------------------------------------------------------------------------
# gruen(n) gibt ein Color-Objekt mit Grun-Ton n gemaß der obigen Darstellung zuruck.
def gruen(n): return color.Color( max(0,n-255), min(n,255), max(0,n-255) )
#---------------------------------------------------------------------------------------
# blau(n) gibt ein Color-Objekt mit Blau-Ton n gemaß der obigen Darstellung zuruck.
def blau(n): return color.Color( max(0,n-255), max(0,n-255), min(n,255) )
Datentyp Color 3.1.9
Nun konnen wir Farbverlaufe der drei Farben malen.
# farbverlaeufe.py (Fortsetzung)
#---------------------------------------------------------------------------------------
# Das Testprogramm malt den Farbverlauf von blau beginnend mit schwarz
# und dahinter den Farbverlauf von rot beginnend mit weiß
# und dahinter den Farbverlauf von grun beginnend mit schwarz.
#--------------------------------------------------------------
def testprogramm():
stddraw.setCanvasSize(1200,800)
stddraw.setXscale(0,1541)
for i in range(0,511):
stddraw.setPenColor( blau(i) )
stddraw.filledRectangle(i, 0, 1.8, 1)
stddraw.setPenColor( rot(510-i) )
stddraw.filledRectangle(510+i, 0, 1.8, 1)
stddraw.setPenColor( gruen(i) )
stddraw.filledRectangle(1020+i, 0, 1.8, 1)
stddraw.show()
#---------------------------------------------------------------------------------------
if __name__=='__main__': testprogramm()
Datentyp Color 3.1.10
Nun konnen wir Farbverlaufe der drei Farben malen.
# farbverlaeufe.py (Fortsetzung)
#---------------------------------------------------------------------------------------
# Das Testprogramm malt den Farbverlauf von blau beginnend mit schwarz
# und dahinter den Farbverlauf von rot beginnend mit weiß
# und dahinter den Farbverlauf von grun beginnend mit schwarz.
#--------------------------------------------------------------
def testprogramm():
stddraw.setCanvasSize(1200,800)
stddraw.setXscale(0,1541)
for i in range(0,511):
stddraw.setPenColor( blau(i) )
stddraw.filledRectangle(i, 0, 1.8, 1)
stddraw.setPenColor( rot(510-i) )
stddraw.filledRectangle(510+i, 0, 1.8, 1)
stddraw.setPenColor( gruen(i) )
stddraw.filledRectangle(1020+i, 0, 1.8, 1)
stddraw.show()
#---------------------------------------------------------------------------------------
if __name__=='__main__': testprogramm()
python3 farbverlaeufe.py
Datentyp Color 3.1.10
Die Leuchtdichte einer Farbe
Die Leuchtdichte (Luminanz) einer RGB-Farbe pr , g , bq ist
E pr , g , bq “ 0.299 ¨ r ` 0.587 ¨ g ` 0.114 ¨ b .
Man benutzt sie, um Farbfotos schwarz-weiß zu drucken.
Eine RGB-Farbe px , x , xq mit gleichem Anteil aller Farben erscheint uns grau.
Ersetzt man in einem Farbfoto jede Farbe pr , g , bq durch pE pr , g , bq,E pr , g , bq,E pr , g , bqq,
konnen wir das entstandene Schwarz-Weiß-Bild gut erkennen.
Die Leuchtdichte ist auch wichtig beim farbigen Schreiben auf farbigem Hintergrund.
Die Differenz der Leuchtdichten der beiden Farben sollte mindestens 128 sein.
Anderenfalls kann man die Schrift nicht deutlich erkennen.
Datentyp Color 3.1.11
Aufgabe:
Schreibe ein Programm, das
die RGB-Werte fur zwei Farben von der Kommandozeile einliest
und
ein Rechteck mit der einen Farbe malt und
die Leuchtdichten der Farben in der anderen Farbe darauf schreibt.
Die Funktion zur Berechnung der Leuchtdichte soll spater auch in anderen Programmen benutzbar
sein.
Das soll uns verdeutlichen, dass die Schrift bei großem Leuchtdichten-Unterschied besser zu lesen ist.
Datentyp Color 3.1.12
# luminanz.py
#----------------------------------------------------------------------------------------------------
import sys, stddraw, color
#----------------------------------------------------------------------------------------------------
# farbeEinlesen(i) nimmt sys.argv[i], sys.argv[i+1], sys.argv[i+2] als drei RGB-Parameter
# und gibt die Farbe (Typ color) zuruck.
def farbeEinlesen(i):
return color.Color(int(sys.argv[i]),int(sys.argv[i+1]),int(sys.argv[i+2]))
#----------------------------------------------------------------------------------------------------
# luminanz(farbe) gibt die Luminanz von farbe (Typ Color) zuruck.
def luminanz(farbe):
l = 0.299*farbe.getRed() + 0.587*farbe.getGreen() + 0.114*farbe.getBlue()
return int(round(l))
#----------------------------------------------------------------------------------------------------
def modultest():
# Lies zwei Farben f1 und f2 von der Kommandozeile ein.
f1 = farbeEinlesen(1)
f2 = farbeEinlesen(4)
# Male ein Rechteck mit Farbe f1.
stddraw.setPenColor(f1)
stddraw.filledRectangle(0.2,0.4,0.6,0.2)
# Schreibe die Luminanz von f1 und f2 und deren Differenz in Farbe f2 darauf.
stddraw.setPenColor(f2)
stddraw.text( 0.5,0.5, "Die Farben haben Luminanz %d und %d." % (luminanz(f1), luminanz(f2)) )
stddraw.text( 0.5,0.45, "Die Differenz der Luminanzen ist %d." % abs(luminanz(f1)-luminanz(f2)) )
stddraw.show()
#----------------------------------------------------------------------------------------------------
if __name__ == '__main__': modultest()
Datentyp Color 3.1.13
python3 luminanz.py 50 100 80 167 10 225
python3 luminanz.py 5 220 225 167 10 225
Datentyp Color 3.1.14
Der Unterschied zwischen Methoden und Funktionen
a = 100
f = color.Color(a,a/2,a/3)
g = f.getGreen()
stddraw.setPenColor(f)
Datentyp Color 3.1.15
Der Unterschied zwischen Methoden und Funktionen
a = 100
f = color.Color(a,a/2,a/3)
g = f.getGreen()
stddraw.setPenColor(f)
Objekt vom Typ int
Datentyp Color 3.1.15
Der Unterschied zwischen Methoden und Funktionen
a = 100
f = color.Color(a,a/2,a/3)
g = f.getGreen()
stddraw.setPenColor(f)
Objekt vom Typ int
Modulname
Datentyp Color 3.1.15
Der Unterschied zwischen Methoden und Funktionen
a = 100
f = color.Color(a,a/2,a/3)
g = f.getGreen()
stddraw.setPenColor(f)
Objekt vom Typ int
Objekt vom Typ Color
Modulname
Datentyp Color 3.1.15
Der Unterschied zwischen Methoden und Funktionen
a = 100
f = color.Color(a,a/2,a/3)
g = f.getGreen()
stddraw.setPenColor(f)
Objekt vom Typ int
Objekt vom Typ Color
Modulname
Variablenname
Datentyp Color 3.1.15
Der Unterschied zwischen Methoden und Funktionen
a = 100
f = color.Color(a,a/2,a/3)
g = f.getGreen()
stddraw.setPenColor(f)
Objekt vom Typ int
Objekt vom Typ Color
Modulname
Methode fur Objekt vom Typ ColorVariablenname
Datentyp Color 3.1.15
Der Unterschied zwischen Methoden und Funktionen
a = 100
f = color.Color(a,a/2,a/3)
g = f.getGreen()
stddraw.setPenColor(f)
Objekt vom Typ int
Objekt vom Typ Color
Modulname
Methode fur Objekt vom Typ Color
Aufruf einer Color Methode
Variablenname
Datentyp Color 3.1.15
Der Unterschied zwischen Methoden und Funktionen
a = 100
f = color.Color(a,a/2,a/3)
g = f.getGreen()
stddraw.setPenColor(f)
Objekt vom Typ int
Objekt vom Typ Color
Modulname
Methode fur Objekt vom Typ Color
Aufruf einer Color Methode
Variablenname
Datentyp Color 3.1.15
Der Unterschied zwischen Methoden und Funktionen
a = 100
f = color.Color(a,a/2,a/3)
g = f.getGreen()
stddraw.setPenColor(f)
Objekt vom Typ int
Objekt vom Typ Color
Modulname
Methode fur Objekt vom Typ Color
Aufruf einer Color Methode
Variablenname
Funktion aus Modul stddraw
Datentyp Color 3.1.15
Der Unterschied zwischen Methoden und Funktionen
a = 100
f = color.Color(a,a/2,a/3)
g = f.getGreen()
stddraw.setPenColor(f)
Objekt vom Typ int
Objekt vom Typ Color
Modulname
Methode fur Objekt vom Typ Color
Aufruf einer Color Methode
Variablenname
Funktion aus Modul stddraw
Aufruf einer Funktion aus Modul stddraw
Datentyp Color 3.1.15
2 Datentypen fur Strings und Datenstrome
API einiger Methoden (es gibt sehr viele) fur den Datentyp str:
str('text') gibt ein str-Objekt mit dem Inhalt text zuruck;
abkurzende Schreibweise ist 'text'
s[i] gibt das i-te Zeichen von String s zuruck;
wie bei Arrays beginnt die Zahlung mit 0
s.split() gibt ein Array mit den Token von String s zuruck;
ein Token ist eine verbundene Folge von Zeichen ohne Leerzeichen, Tabulator und
Zeilenumbruch
s.rstrip() gibt das str-Objekt zuruck, das aus String s entsteht, indem Leerz., Tabulat. und
Zeilenumbruche am Ende entfernt werden
s.isnumeric() gibt True zuruck, falls String s nur aus Ziffern besteht (Python3)
s.find(t) gibt den kleinsten Index (int) zuruck, an dem String t in String s beginnt (bzw.
´1, falls t nicht vorkommt)
s.replace(alt,neu) gibt ein str-Objekt zuruck, das aus String s entsteht,
indem jedes Vorkommen des Strings alt durch den String neu ersetzt wird.
Datentypen str und TextIOWrapper 3.1.16
Datentyp fur Datenstrome
API wichtiger Methoden zum Lesen eines Datenstroms:
open(name, 'r') ein Datenstrom wird geoffnet und ein DS-Objekt zum Lesen wird
zuruckgegeben; es entsteht aus der Datei name
d.readline() die nachste Zeile (string) im Datenstrom d; das Zeilenende '\n'
steht am Ende der Zeile; falls das Dateiende erreicht ist, wird der
leere String '' zuruckgegeben
d.readlines() alle Zeilen (string) des Datenstroms d
d.close() schließt den Datenstrom d
sys.stdin ist DS-Objekt fur standard input.
Datentypen str und TextIOWrapper 3.1.17
API wichtiger Methoden zum Schreiben eines Datenstroms:
open(name, 'w') ein Datenstrom wird geoffnet und ein DS-Objekt zum Schreiben wird
zuruckgegeben;
der Datenstrom schreibt in die Datei name; falls die Datei bereits existiert,
wird ihr alter Inhalt geloscht
open(name, 'a') ein Datenstrom wird geoffnet und ein DS-Objekt zum Schreiben wird
zuruckgegeben;
der Datenstrom schreibt in die Datei name; falls die Datei bereits existiert,
wird der Datenstrom angehangt
d.write(s) hangt s (Typ string) an den Datenstrom d
d.close() schließt den Datenstrom d
sys.stdout ist DS-Objekt fur standard output.
Datentypen str und TextIOWrapper 3.1.18
Graphische Darstellung der Entwicklung der
Jahresdurchschnittstemperaturen
Aufgabe:
Stelle die Entwicklung der durchschnittlichen Jahrestemperaturen (in Jena) graphisch durch ein
Streifendiagramm dar. Fur jedes Jahr wird ein Streifen gemalt. Seine Farbe stellt die Abweichung
von der Durchschnittstemperatur aller Jahre dar.
Ist die Abweichung negativ, wird sie durch den Farbverlauf von blau von dunkel zu hell dargestellt.
Je weiter ein Jahr unter der Durschnittstemperatur liegt, desto dunkler wird es blau dargestellt.
Ist die Abweichung positiv, wird sie durch den Farbverlauf von rot von hekk zu dunkel dargestellt.
Je weiter ein Jahr uber der Durchschnittstemperatur liegt, desto dunkler wird es ro dargestellt.
Jahre mit einer durchschnittlichen Temperatur werden sehr hell dargestellt.
Datentypen str und TextIOWrapper 3.1.19
Grobe Struktur des Programmablaufs
Eingabe: 1824 13.50
1825 13.38
...
2017 15.85
2018 16.94
filtere die Temperaturen aus der Datei
[ 13.50, 13.38, ..., 15.85, 16.94 ]
wandele die Temperaturen in Farben um
und male sie als Streifen auf die Leinwand
Modul farbverlaeufe.py
rot(n) gibt Farbe mit Rot-Ton n zuruck
gruen(n) gibt Farbe mit Grun-Ton n zuruck
blau(n) gibt Farbe mit Blau-Ton n zuruck
Datentypen str und TextIOWrapper 3.1.20
# temperaturStreifen.py
#------------------------------------------------------------------------------------------------------
# Liest den Namen einer Datei von der Kommandozeile, deren Zeilen aus einer Jahreszahl und
# einem Zahlenwert (float) bestehen (z.B. Jahresdurchschnittstemperaturen).
# Die Zahlenwerte werden als Streifendiagramm graphisch dargestellt.
# Die Werte unter dem Durchschnitt werden durch blaue Streifen dargestellt (je kleiner, umso dunkler),
# die Werte uber dem Durchschnitt werden durch rote Striefen dargestellt (je großer, unso dunkler).
#------------------------------------------------------------------------------------------------------
import sys, stddraw, color
from farbverlaeufe import blau, rot
#------------------------------------------------------------------------------------------------------
# liesEingabe(dateiname) liest die Eingabedatei aus der Datei mit Namen dateiname (string).
# Die Datei wird als Tabelle aus zwei Spalten (getrennt durch ' ') aufgefasst.
# Die zweite Spalte wird in einem Array zuruckgegeben.
def liesEingabe(dateiname):
# Offne die Datei und lies die erste Zeile.
datei = open(dateiname, 'r')
zeile = datei.readline()
# werte speichert die Werte der zweiten Spalte.
werte = []
# Solange aus der Datei noch eine Zeile gelesen werden konnte:
# speichere den Wert aus der 2.Spalte in werte und lies die nachste Zeile.
while zeile != '':
wert = float( zeile.split()[1] )
werte += [wert]
zeile = datei.readline()
# Gib alle eingelesenen Werte zuruck.
return werte
Datentypen str und TextIOWrapper 3.1.21
# Fortsetzung von temperaturStreifen.py
#-------------------------------------------------------------------------------------------------------------------
# Gibt einen ganzzahligen Wert aus dem Bereich 0..510 zuruck, der dem "Farbton" von wert auf der
# Skala von unten (entspricht 0, schwarz) bis oben (entspricht 510, weiß) entspricht.
def farbton(wert, unten, oben):
m = 510*(wert-unten)/(oben-unten)
return int(round(m))
#-------------------------------------------------------------------------------------------------------------------
# Erhalt ein Array aus Zahlenwerten und wandelt sie in Farben um.
# Werte unter dem Mittelwert werden in Blautone umgewandelt. Kleine Werte haben dunklere Blautone als großere Werte.
# Wert uber dem Mittelwert werden in Rottone umgewandelt. Kleine Werte haben hellere Rottone als großere Werte.
# Das Array mit den in Farben umgewandelten Werten wird zuruckgegeben.
def werteZuFarben(werte):
durchschnittsWert = sum(werte)/len(werte)
minWert = min(werte)
maxWert = max(werte)
farben = []
for w in werte:
# Falls der Wert kleiner als der Durchschnitt ist, wird er durch einen Blauton dargestellt: je kleiner, umso dunkler.
if w<=durchschnittsWert:
farben += [ blau( farbton(w, minWert, durchschnittsWert) ) ]
else:
# Falls der Wert großer als der Durchschnitt ist, wird er durch einen Rotton dargestellt: je kleiner, umso heller.
farben += [ rot( 510 - farbton(w, durchschnittsWert, maxWert) ) ]
return farben
Datentypen str und TextIOWrapper 3.1.22
# Fortsetzung von temperaturStreifen.py
#------------------------------------------------------------------------------------------------------
# Das Hauptprogramm liest die darzustellenden Wert aus einer Datei,
# wandelt sie in Farben um und stellt sie Streifen auf der Leinwand dar.
def hauptprogramm():
# Lies die darzustellenden Wert aus der Datei, deren Name von der Kommandozeile gelesen wird.
werte = liesEingabe(sys.argv[1])
farben = werteZuFarben(werte)
# Die Leinwand wird eingerichtet.
stddraw.setCanvasSize(1200,800)
stddraw.setXscale(0, len(werte))
# Die Farben der Reihe nach von links nach rechts als Streifen auf die Leinwand gemalt.
for i in range(0,len(farben)):
# Der Streifen wird in der durch den Wert bestimmten Farbe gemalt.
stddraw.setPenColor(farben[i])
stddraw.filledRectangle(i, 0, 1.1, 1)
# stddraw.show(50)
# Das Ergebnis wird angezeigt.
stddraw.show()
#------------------------------------------------------------------------------------------------------
if __name__=='__main__': hauptprogramm()
#------------------------------------------------------------------------------------------------------
Datentypen str und TextIOWrapper 3.1.23
python temperaturStreifen.py Jena-JahresMittel-Temp.txt
Datentypen str und TextIOWrapper 3.1.24
Um die fast schwarzen Streifen etwas aufzuhellen, kann man Minimum und Maximum aus dem Bereich
hinausschieben, in dem Werte vorkommen.Ersetze minWert = min(werte) durch minWert = min(werte)-0.7
maxWert = max(werte) maxWert = max(werte)+0.7
Dadurch wird die Graphik insgesamt etwas heller.
python temperaturStreifen.py Jena-JahresMittel-Temp.txt
Datentypen str und TextIOWrapper 3.1.25
Um die vielen hellen Streifen etwas abzudunkeln, kann man den Mittelwert bei den Blautonen nach oben
und bei den Rottonen nach unten verschieben.
Mache die Farbwahl mit farben += [ blau( farbton(w, minWert, durchschnittsWert+0.3) ) ]
farben += [ rot( 510 - farbton(w, durchschnittsWert-0.3, maxWert) ) ]
Dadurch wird die Graphik insgesamt etwas dunkler.
python temperaturStreifen.py Jena-JahresMittel-Temp.txt
Datentypen str und TextIOWrapper 3.1.26
3 Digitale BilderDer Datentyp Picture
Pixel p0, 0q Spalte 9
Zeile 5
Breite
Hohe
Ein digitales Bild stellt man sich als ein Gitter aus Pixeln vor.
Jedes Pixel hat eine Position (Spalte,Zeile) und eine Farbe.
Die Zahlung beginnt oben links mit Spalte 0 und Zeile 0.
Im Beispiel links ist das Pixel p9, 5q rot.
Der Datentyp Picture ist im Modul picture.py definiert.
Er stellt Methoden zum Lesen und Schreiben von Bildern und deren Pixeln zur Verfugung.
Datentyp Picture 3.1.27
Die API fur den Datentyp Picture in picture.py
Datentyp Picture 3.1.28
Anzeigen eines Bildes
# bildAnzeigen.py
# Liest den Dateinamen eines Bildes von der Komandozeile und zeigt das Bild an.
#----------------------------------------------------------------------------------------------
import sys, stddraw
from picture import Picture
#----------------------------------------------------------------------------------------------
# Richte die Leinwand von stddraw so ein, dass ihre Breite bzw. Hohe
# die Breite bzw. Hohe des anzuzeigenden Bildes ist.
def richteLeinwandEin(bild):
breite = bild.width()
hoehe = bild.height()
stddraw.setCanvasSize(breite,hoehe)
#------------------------------------------------------------------------------
# Zeige das Bild bild (Picture) auf der Leinwand von stddraw an.
def bildAnzeigen(bild):
richteLeinwandEin(bild)
stddraw.picture(bild)
stddraw.show()
#-----------------------------------------------------------------------------------------
# Lies den Dateinamen eines Bildes (.jpg oder .png) von der Kommandozeile und zeige es an.
def modultest():
dateiname = sys.argv[1]
bild = Picture(dateiname)
bildAnzeigen(bild)
#------------------------------------------------------------------------------------
if __name__ == '__main__': modultest()
#------------------------------------------------------------------------------------
# python bildAnzeigen.py Spektraltorte.jpg
#--------------------------------------------
# python bildAnzeigen.py Spektraltorte.jpg
Datentyp Picture 3.1.29
Umwandeln eines Farbbildes in ein Schwarzweißbild
Idee:
Andere die Farbe jedes Pixels in seine Graustufe.
Die Graustufe einer Farbe f ist die Farbe,
die fur jeden der drei RGB-Werte die Luminanz von f hat.
Datentyp Picture 3.1.30
# farbeNachSW.py
#-------------------------------------------------------------------------------------------------
# Liest den Dateinamen eines Bildes von der Kommandozeile und zeigt es in schwarz-weiß an.
#-------------------------------------------------------------------------------------------------
import sys, stddraw, color, luminanz, picture, bildAnzeigen
#-------------------------------------------------------------------------------------------------
# graustufe(f) gibt die Graustufe (Typ Color) der Farbe f (Typ Color) zuruck.
def graustufe(f):
l = luminanz.luminanz(f)
return color.Color(l,l,l)
#----- Hauptprogramm ----------------------------------------------------------------------------
# Lies den Dateinamen des Bildes von der Kommandozeile und erzeuge das Picture-Objekt foto daraus.
foto = picture.Picture(sys.argv[1])
# Zeige das Bild an.
bildAnzeigen.richteLeinwandEin(foto)
stddraw.picture(foto)
stddraw.show(1)
# Gehe Zeilen- und Spaltenweise alle Pixel des Bildes durch
# und ersetze dabei jede Pixel-Farbe durch ihre Luminanz.
# Wenn eine Zeile ersetzt wurde, dann zeige das Bild an.
for z in range(foto.height()):
for s in range(foto.width()):
pixel_farbe = foto.get(s,z)
g = graustufe(pixel_farbe)
foto.set(s,z,g)
stddraw.picture(foto)
stddraw.show(1)
stddraw.show()
Datentyp Picture 3.1.31
Farbverlaufe
Wir haben Farbverlaufe bereits mit stddraw gemalt.
Es geht auch mit Picture. Dabei mussen wir selber jedes Pixel des Bildes bemalen.
Das Problem der”weißen Streifen“ durch Rundungsfehler bei der Pixel-Berechnung entfallt dabei.
# farbverlaeufePicture.py
#------------------------------------------------------------------
from picture import Picture
from bildAnzeigen import bildAnzeigen
from farbverlaeufe import rot, blau
#------------------------------------------------------------------
# Das Programm malt den Farbverlauf von blau beginnend mit schwarz
# und dahinter den Farbverlauf von rot beginnend mit weiß.
#------------------------------------------------------------------
p = Picture(1021, 800)
for i in range(0,511):
c = blau(i)
for j in range(800): p.set(i,j, c)
for i in range(0,511):
c = rot(510-i)
for j in range(800): p.set(510+i,j, c)
bildAnzeigen(p)
#------------------------------------------------------------------
# python3 farbverlaeufePicture.py
python3 farbverlaeufePicture.py
Datentyp Picture 3.1.32
Zusammenfassung
§ Mit Datentypen werden verschiedenste Daten zum Rechnen nutzbar gemacht. In einer API
liest man, welche Nutzung moglich ist.
§ Methoden fur Datentypen ermoglichen eine abstrakte Handhabung der Daten.
§ Wir kennen die Schreibweise fur die Anwendung von Methoden auf Daten-Objekte und den
Unterschied zur Anwendung von Funktionen.
3.1.33
Abschluss-Beispiel: Schreiben wie Goethe oder SchillerZufallige Texte erzeugen, bei denen Goethes Faust den Zufall steuert
Einen Text kann man statistisch analysieren:
man schaut sich alle Text-Schnipsel der Lange 5 an
und gibt an, welche Schnipsel der Lange 5 dahinter kommen.
Beispiel: bei der Analyse von Goethes Faust findet man z.B.:
hinter . . . kommen im Faust . . .
' Da d' 'u, o ' | 'ank’ ' | 'ie? S' | 'u dic'
'u dic' 'h? Me' | 'h das' | 'h spr' | 'h nun' | 'h uns' | 'h aus' | 'h vor'
'h uns' 'rer B' | ', den' | ' besi' | ' ein ' | 'er La' | '? Fau'
'? Fau' 'st ab' | 'st. W' | 'st. S' | 'st. D' | 'st. I' | ...
'st. I' 'n Leb' | 'ch ne' | 'ch se' | 'ch ha' | 'ch ha' | 'hr se' | ...
'hr se' 'yd ei' | 'ht di' | 'yd ei' | 'yd wo' | 'hr gu' | 'lig m' | ...
'yd ei' 'n vie' | 'n Sch' | 'n lie'
'n vie' 'lgeli' | 'l, Zu' | 'l zu ' | 'l gew' | 'len G'
Schreiben wie Goethe oder Schiller 3.1.34
Abschluss-Beispiel: Schreiben wie Goethe oder SchillerZufallige Texte erzeugen, bei denen Goethes Faust den Zufall steuert
Beispiel: bei der Analyse von Goethes Faust findet man z.B.:
hinter . . . kommen im Faust . . .
' Da d' 'u, o ' | 'ank’ ' | 'ie? S' | 'u dic'
'u dic' 'h? Me' | 'h das' | 'h spr' | 'h nun' | 'h uns' | 'h aus' | 'h vor'
'h uns' 'rer B' | ', den' | ' besi' | ' ein ' | 'er La' | '? Fau'
'? Fau' 'st ab' | 'st. W' | 'st. S' | 'st. D' | 'st. I' | ...
'st. I' 'n Leb' | 'ch ne' | 'ch se' | 'ch ha' | 'ch ha' | 'hr se' | ...
'hr se' 'yd ei' | 'ht di' | 'yd ei' | 'yd wo' | 'hr gu' | 'lig m' | ...
'yd ei' 'n vie' | 'n Sch' | 'n lie'
'n vie' 'lgeli' | 'l, Zu' | 'l zu ' | 'l gew' | 'len G'
Nun konnen wir einen Text mit”der gleichen Wahrscheinlichkeit wie Goethes Faust“ schreiben,
indem wir mit einem Schnipsel beginnen,
immer wieder zufallig ein Folgeschnipsel auswahlen . . .
Bsp.: Da du dich uns? Faust. Ihr seyd ein viel, ZuSchreiben wie Goethe oder Schiller 3.1.34
Aufgabe:
schreibe ein Programm,
das einen Text und eine Schnipsellange liest,
die”Tabelle“ der im Text aufeinanderfolgenden Schnipsel berechnet
und daraus einen Zufallstext (einer vorgegebenen Lange) erzeugt.
Zum Einlesen (und Saubern) des Textes benutzen wir aus Modul dateiEinlesen.py die
Funktion textdateiAlsString(dateiname).
API von dateiEinlesen.py:
textdateiAlsString(dateiname) liest Datei dateiname und gibt ihren Inhalt
als einen String zuruck. Aus dem String wurden alle Sonderzeichen entfernt.
Zwei Worter im String sind durch ein Leerzeichen getrennt.
Schreiben wie Goethe oder Schiller 3.1.35
Wie soll die”
Tabelle“ gespeichert werden?
Die Daten-Frage
Wir speichern die”Tabelle“ als Dictionary.
Die Schlussel sind die Schnipsel,
und ein Wert ist ein Array aus allen Schnipseln,
die hinter dem Schlussel vorkommen.
Beispiel:
aus Tabellenzeile
hinter . . . kommen im Faust . . .
' Da d' 'u, o ' | 'anke ' | 'ie? S' | 'u dic'
wird im Dictionary
Schlussel ' Da d'
mit Wert ['u, o ', 'anke ', 'ie? S', 'u dic']Schreiben wie Goethe oder Schiller 3.1.36
# textAutomat.py
#-----------------------------------------------------------------------------------
import sys, random, dateiEinlesen
#-----------------------------------------------------------------------------------
# Die Funktion erzeugeSchnipselAutomat(text, sl) gibt das Dictionary fur
# text und sl zuruck. Die Zustandsubergange sind als Dictionary gespeichert.
# Jeder Zustand x ist ein Schlussel. Der zugehorige Wert ist ein Array
# ein Array, das fur jedes Vorkommen von xy in text einen Eintrag y
# hat. Wenn xy mehrmals vorkommt, kommt y auch entsprechend oft im
# Array vor (damit sparen wir uns das Berechnen der Gewichte).
def erzeugeSchnipselAutomat(text, sl):
automat = {}
for i in range(len(text)-2*sl):
schluessel = text[i:i+sl]
if not schluessel in automat:
automat[schluessel] = []
automat[schluessel] += [text[i+sl:i+2*sl]]
return automat
#-----------------------------------------------------------------------------------
# startSchnipsel(automat) gibt ein Array aller Schnipsel (Zustande)
# zuruck, die im Automat auf ein Satzendezeichen folgen konnen.
def startSchnipsel(automat):
startschnipsel = []
for s in automat:
if s[-2] in '.!?': startschnipsel += automat[s]
return startschnipselSchreiben wie Goethe oder Schiller 3.1.37
#-----------------------------------------------------------------------------------
# zufallsText(automat,sl,laenge) gibt einen Text der Lange laenge zuruck,
# der vom WSA mit Schnipsellange sl erzeugt werden kann.
def zufallsText(automat, sl, laenge):
# Wahle zufallig einen Satzanfang.
satz = random.choice(startSchnipsel(automat))
# Laufe durch den Automat, bis ein Text der gewunschten Lange erzeugt wurde.
for i in range(0,laenge,sl):
endschnipsel = satz[i:i+sl]
if endschnipsel in automat:
# print(endschnipsel + ': ' + str(automat[endschnipsel]))
folgeschnipsel = random.choice(automat[endschnipsel])
satz += folgeschnipsel
return satz
#-----------------------------------------------------------------------------------
def modultest():
dateiname = sys.argv[1]
schnipselLaenge = int(sys.argv[2])
textLaenge = int(sys.argv[3])
# Lies eine Textdatei ein und wandele sie in einen String um.
text = dateiEinlesen.textdateiAlsString(dateiname)
# Erzeuge daraus einen Wort-Schnipsel-Automat.
automat = erzeugeSchnipselAutomat(text, schnipselLaenge)
# Erzeuge einen Zufallstext mit dem Automaten.
print(zufallsText(automat, schnipselLaenge, textLaenge))
#-----------------------------------------------------------------------------------
if __name__ == '__main__': modultest()
Schreiben wie Goethe oder Schiller 3.1.38
# python textAutomat.py Goethe-ItalienischeReise1.txt 3 200
# Winder Reihen wieder gerett, habe. Hierauf wohl eben konnten, Ture und uber.
# Den Januar 1787. Verwahre ich vor Herr alles aus dem Zwergoldener
# dem Hafer, wegenitunterdreichzug gern hunden. Indes schon
# python textAutomat.py Goethe-ItalienischeReise1.txt 6 200
# Hamilton und seines Lebens. Die Zimmer nur durch denselben zu trennen und bewegten.
# Wer hat es die letzte bewohnt und fugte hinzu, daß ich denn
# als Mitternacht aus diesem Tiere ein Jammer, Gange fand ich di
# python textAutomat.py Goethe-ItalienischeReise1.txt 12 200
# Heute gesellten sich reitend ein Herr und eine Dame zu uns, ein Englander sprechen,
# der mir uber meinen Werther etwas zu sagen habe.
# Vor einem halben Jahre wurde hierauf, und ware sie mir doppelt wert gewesen, g
# python3 textAutomat.py textAutomat.py 4 200
# !? startschnipsel in automattext, sl automat, sl, laenge Erzeuge daraus eine Ausgabelange
# sl erzeuge einen Stringdateinander folgeschnipselAutomat if s1 in der vom WSA
# mit der TextDatei. import sys, rando
Schreiben wie Goethe oder Schiller 3.1.39
4 Algorithmen
Wir haben bisher Programme zur Losung verschiedener Probleme geschrieben. Jedes Programm
basiert auf einer Idee (Algorithmus), die man in jeder Programmierprache aufschreiben kann.
Beim Entwickeln von Algorithmen geht es u.a. darum, moglichst schnelle Algorithmen mit wenig
Speicherplatzbedarf zu finden.
In diesem Kapitel schauen wir uns zuerst an, wie man experimentell feststellt, wie”schnell“ ein
Algorithmus ist.
Anschließend schauen wir uns Algorithmen zum Suchen von Verbindungen in Netzwerken an.
Mehr uber Algorithmen gibt es im zweiten Teil der Vorlesung.
1. Elemente des Programmierens
2. Funktionen und Module
3. Objekt-orientierte Programmierung (erste Schritte)
4. Algorithmen
4.1 Rechenzeit
4.6 Das Small-World-Problem und die Suche nach Wegen in Netzwerken
Schreiben wie Goethe oder Schiller 4.0.41
Vorlesung 11
4. Algorithmen
4.1 RechenzeitExperimentelle Bestimmung/Schatzung der Rechenzeit
Abstrakte Schatzung der Rechenzeit
Beispiele fur Rechenzeitanalysen
4.6 Das Small-World-Problem und die Suche nach Wegen in Netzwerken
Schreiben wie Goethe oder Schiller 4.1.1
4.1 Rechenzeit von Programmen
Wir haben z.B. beim
§ Berechnen von Potenzen 2**n
§ Berechnen von Fibonacci-Zahlen
§ Sortieren von Zahlenfolgen
gesehen, dass verschiedene Programme zwar das gleiche Ergebnis berechnen,
jedoch fur die betrachteten Eingaben sehr unterschiedlich schnell sind.
Wann kann man sagen, dass ein Programm schneller als ein anderes ist?
Wie kann man die Rechenzeit von Programmen analysieren?
Kann man auch die Rechenzeit von (noch nicht implementierten) Algorithmen analysieren?
Wir betrachten jetzt der Einfachheit halber nur Funktionen/Programme mit einem Argument.
Einleitung 4.1.2
1. Problem: Rechenzeiten von Programmen sind unvergleichbar
Wir haben gemessen, dass die Funktion bubblesort(a) ein Array a aus 16000 Zahlen in 0.003 Sek. sortiert,
und heapsort(a) das gleiche Array in 0.106 Sek. sortiert.
Bei einem Array b aus 16000 Zahlen braucht bubblesort(b) 23.593 Sek. und heapsort(b) 0.101 Sek.
In Grundvorlesungen lernt man, dass Heapsort schneller ist als Bubblesort. Was stimmt nun?
Einleitung 4.1.3
1. Problem: Rechenzeiten von Programmen sind unvergleichbar
Wir haben gemessen, dass die Funktion bubblesort(a) ein Array a aus 16000 Zahlen in 0.003 Sek. sortiert,
und heapsort(a) das gleiche Array in 0.106 Sek. sortiert.
Bei einem Array b aus 16000 Zahlen braucht bubblesort(b) 23.593 Sek. und heapsort(b) 0.101 Sek.
In Grundvorlesungen lernt man, dass Heapsort schneller ist als Bubblesort. Was stimmt nun?
Wenn man die Rechenzeiten fur jede Eingabe vergleicht,
ist die Rechenzeit vieler Funktionen nicht miteinander vergleichbar.
Deshalb vergleicht man die Rechenzeit nur fur jede Eingabelange.
Die Rechenzeit einer Funktion fur eine Eingabelange n ist
ihre großte Rechenzeit fur alle Eingaben der Lange n.
§ Bei int-Argumenten ist die Eingabelange die Lange der int-Zahl in Binardarstellung.§ Bei Array-Argumenten ist die Eingabelange die Lange des Arrays.§ Bei Netzwerk-Argumenten ist die Eingabelange die Anzahl der Knoten/Kanten des Netzwerks.
Einleitung 4.1.3
1. Problem: Rechenzeiten von Programmen sind unvergleichbar
Wenn man die Rechenzeiten fur jede Eingabe vergleicht,
ist die Rechenzeit vieler Funktionen nicht miteinander vergleichbar.
Deshalb vergleicht man die Rechenzeit nur fur jede Eingabelange.
Die Rechenzeit einer Funktion fur eine Eingabelange n ist
ihre großte Rechenzeit fur alle Eingaben der Lange n.
§ Bei int-Argumenten ist die Eingabelange die Lange der int-Zahl in Binardarstellung.
§ Bei Array-Argumenten ist die Eingabelange die Lange des Arrays.
§ Bei Netzwerk-Argumenten ist die Eingabelange die Anzahl der Knoten/Kanten des Netzwerks.
Die Zahl 1234567890 hat Binardarstellung 1001001100101100000001011010010, also Lange 31.
Es gibt 230 « 109 Zahlen der Lange 31.
Einleitung 4.1.3
1. Problem: Rechenzeiten von Programmen sind unvergleichbar
Wenn man die Rechenzeiten fur jede Eingabe vergleicht,
ist die Rechenzeit vieler Funktionen nicht miteinander vergleichbar.
Deshalb vergleicht man die Rechenzeit nur fur jede Eingabelange.
Die Rechenzeit einer Funktion fur eine Eingabelange n ist
ihre großte Rechenzeit fur alle Eingaben der Lange n.
§ Bei int-Argumenten ist die Eingabelange die Lange der int-Zahl in Binardarstellung.
§ Bei Array-Argumenten ist die Eingabelange die Lange des Arrays.
§ Bei Netzwerk-Argumenten ist die Eingabelange die Anzahl der Knoten/Kanten des Netzwerks.
Das Array [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] hat Lange 10.
Es gibt 1010 Arrays mit 10 Elementen aus dem Bereich 1 . . . 10.
Einleitung 4.1.3
1. Problem: Rechenzeiten von Programmen sind unvergleichbar
Wenn man die Rechenzeiten fur jede Eingabe vergleicht,
ist die Rechenzeit vieler Funktionen nicht miteinander vergleichbar.
Deshalb vergleicht man die Rechenzeit nur fur jede Eingabelange.
Die Rechenzeit einer Funktion fur eine Eingabelange n ist
ihre großte Rechenzeit fur alle Eingaben der Lange n.
§ Bei int-Argumenten ist die Eingabelange die Lange der int-Zahl in Binardarstellung.
§ Bei Array-Argumenten ist die Eingabelange die Lange des Arrays.
§ Bei Netzwerk-Argumenten ist die Eingabelange die Anzahl der Knoten/Kanten des Netzwerks.
Das Netzwerk von Seite 4.2.2 hat Lange 10 (10 Knoten).
Es gibt 210¨9
2 « 3.5 ¨ 1013 (nicht-isomorphe) Netzwerke der Große 10.
Einleitung 4.1.3
2. Problem: Es gibt zu viele Eingaben
Das Alter des Universums ist etwa 4 ¨ 1017 Sekunden.
Es gibt 1919 ě 4 ¨ 1023 Arrays der Lange 19 aus Zahlen 1 . . . 19.
Wenn Heapsort zum Sortieren eines solchen Arrays mindestens 10´6 Sekunden braucht,
dann braucht man mehr Zeit als das Alter des Universums,
um alle Arrays der Lange 19 zu sortieren
und die Rechenzeit meiner Heapsort-Funktion fur Eingaben der Lange 19 zu bestimmen.
Fazit: man kann die Rechenzeit einer Funktion nicht praktisch bestimmen – dafur braucht man
eine gute Theorie.
Einleitung 4.1.4
Um die Theorie zu untermauern,
beginnen wir in dieser Vorlesung mit ein paar praktischen Messungen.
Dazu schatzen wir die”praktische“ Rechenzeit einer Funktion fur eine Eingabelange n dadurch ab,
dass wir
(zufallig) eine Eingabe der Lange n wahlen und
die Rechenzeit fur diese Eingabe
als maximale Rechenzeit fur alle Eingaben gleicher Lange nehmen.
Die Messungen geben uns einen Hinweis auf die”theoretische“ Rechenzeit.
Einleitung 4.1.5
1 Experimentelles Messen der Rechenzeit einer Funktion fur ein
Argument/Eingabe
Zum Messen der Rechenzeit benutzen wir die Funktion time() aus dem Modul time.py,
die die Zeit seit dem 1.1.1970 in Sekunden als float zuruckgibt.
Jede Messung sieht wie folgt aus:
schaue auf die Uhr
starte die zu messende Funktion und warte, bis sie beendet ist
schaue auf die Uhr
die Differenz der Uhrzeiten ist die Rechenzeit
Wir werden eine Messreihe aus einer Reihe von Messungen durchfuhren,
bei denen das Argument fur die Funktion immer großer wird.
Der Einfachheit halber wollen wir nur Funktionen betrachten,
die nur von einem Argument abhangig sind.Messen der Rechenzeit 4.1.6
# messreihe.py
#---------------------------------------------------------------------------------------
# Funktionen zum Durchfuhren von Rechenzeitmessungsexperimenten.
#---------------------------------------------------------------------------------------
import sys, time, random
#---------------------------------------------------------------------------------------
# randomArray(n) erzeugt ein Array der Lange n mit zufalligen Eintragen aus -10n...10n.
def randomArray(n):
a = [0]*n
for i in range(n):
a[i] = random.randrange(-10*n, 10*n+1)
return a
#---------------------------------------------------------------------------------------
# miss(testfunktion, n) ruft testfunktion(n) auf und gibt die Zeit (in Sekunden)
# zuruck, die dieser Aufruf gedauert hat.
def miss(testfunktion, n):
messAnfang = time.time()
testfunktion(n)
messEnde = time.time()
return messEnde - messAnfang
Messen der Rechenzeit 4.1.7
Beispiel: finde im Array drei Eintrage mit Summe 0
Als ausfuhrliches Beispiel wollen wir die Rechenzeit der Funktion countTriples(a) im Modul
threesum.py untersuchen.
Die Funktion erhalt als Argument ein Array a aus Zahlen
und sucht darin nach drei Eintragen (Tripel), deren Summe 0 ist (und gibt sie aus).
Die Anzahl solcher Tripel wird zuruckgegeben. (Ggf. werden die gefundenen Tripel ausgegeben.)
Das Hauptprogramm liest n von der Kommandozeile,
erzeugt ein Array der Lange n mit zufallig gewahlten Eintragen aus dem Bereich ´10 ¨ n . . . 10 ¨ n,
gibt das Array aus (falls es nicht zu groß ist)
und gibt aus, wieviele Tripel im Array Summe 0 haben.
$ python3 threesum.py 5
Array: [-1, 3, -3, 0, 3]
Tripel 1: 3 -3 0
Tripel 2: -3 0 3
Anzahl gefundener Tripel: 2
$ python3 threesum.py 10
Array: [-2, -10, 1, -4, -10, -4, 10, 10, -3, 6]
Tripel 1: -2 -4 6
Tripel 2: -2 -4 6
Anzahl gefundener Tripel: 2Rechenzeitanalyse von countTriples 4.1.8
# threesum.py
#-------------------------------------------------------------------------------------------------------------------
import sys, random
from messreihe import randomArray
#-------------------------------------------------------------------------------------------------------------------
# countTriples(a) probiert systematisch alle Tripel aus Eintragen im Array a
# durch und zahlt, wieviel Summe 0 haben.
# Diese Anzahl wird zuruckgegeben.
# Die Rechenzeit hat Großenordnung n**3 (n ist die Große von a).
def countTriples(a):
n = len(a)
count = 0
for i in range(n-2):
for j in range(i+1,n-1):
for k in range(j+1,n):
if (a[i] + a[j] + a[k]) == 0:
count += 1
if n<20: print( 'Tripel %2d: %d %d %d' % (count, a[i], a[j], a[k]) )
return count
#-------------------------------------------------------------------------------------------------------------------
def hauptprogramm():
a = randomArray(int(sys.argv[1])) # Lies n von der Kommandozeile und erzeuge ein zufalliges Array der Lange n.
if len(a)<20: print( 'Array: %s' % str(a) )
ergebnis = countTriples(a) # Zahle die Tripel in a mit Summe 0.
print( 'Anzahl gefundener Tripel: %d' % ergebnis ) # Gib das Ergebnis aus.
#-------------------------------------------------------------------------------------------------------------------
if __name__=='__main__': hauptprogramm()
#-------------------------------------------------------------------------------------------------------------------
Rechenzeitanalyse von countTriples 4.1.9
Problem 3: Die Rechenzeit ist abhangig vom Rechner
Wir wollen eine Aussage daruber treffen konnen,
wie die Rechenzeit der Funktion countTriples(a) fur beliebig große Arrays a ist.
Dazu machen wir erstmal ein paar Messungen.Rechner 1:
Große Zeit (s)
------------------
40 0.00
60 0.00
80 0.01
100 0.02
120 0.04
140 0.06
160 0.08
180 0.12
200 0.16
220 0.21
240 0.27
260 0.34
280 0.43
300 0.53
320 0.64
340 0.77
360 0.92
380 1.09
Rechner 2:
Große Zeit (s)
------------------
40 0.00
60 0.01
80 0.02
100 0.03
120 0.04
140 0.07
160 0.09
180 0.11
200 0.18
220 0.26
240 0.30
260 0.39
280 0.53
300 0.63
320 0.79
340 0.89
360 1.12
380 1.14
Auf den ersten Blick kann man nichts
erkennen.
Die genauen Rechenzeiten hangen vom
Rechner ab, auf dem das Programm lauft.
Rechenzeitanalyse von countTriples 4.1.10
Wir wollen eine Aussage daruber treffen konnen,
wie die Rechenzeit der Funktion countTriples(a) fur beliebig große Arrays a ist.
Dazu machen wir erstmal ein paar Messungen und zeichnen daraus eine Kurve.
Rechner 1:
Große Zeit (ms)
------------------
40 0.00
60 0.00
80 0.01
100 0.02
120 0.04
140 0.06
160 0.08
180 0.12
200 0.16
220 0.21
240 0.27
260 0.34
280 0.43
300 0.53
320 0.64
340 0.77
360 0.92
380 1.09
400 1.28
420 1.52
440 1.72
460 1.98
480 2.28
500 2.54
520 2.94
540 3.22
560 3.65
0 200 400 600 800 1,000
0
10
20
Anzahl der Eintrage im Array
Rec
hen
zeit
inS
eku
nd
en
Blaue Kurve: Rechner 1
Rote Kurve: Rechner 2
Schwarze Kurve: Rechner 3
(doppelt so schnell wie Rechner 2)
Rechenzeiten auf
unterschiedlichen Rechnern
ergeben von der”Form“ her
ahnliche Kurven.
Die Kurve ist von der”Form“
her anders als jede lineare
Kurve.
Rechenzeitanalyse von countTriples 4.1.11
Wir wollen eine Aussage daruber treffen konnen,
wie die Rechenzeit der Funktion countTriples(a) fur beliebig große Arrays a ist.
Dazu machen wir erstmal ein paar Messungen und zeichnen daraus eine Kurve.
Rechner 1:
Große Zeit (ms)
------------------
40 0.00
60 0.00
80 0.01
100 0.02
120 0.04
140 0.06
160 0.08
180 0.12
200 0.16
220 0.21
240 0.27
260 0.34
280 0.43
300 0.53
320 0.64
340 0.77
360 0.92
380 1.09
400 1.28
420 1.52
440 1.72
460 1.98
480 2.28
500 2.54
520 2.94
540 3.22
560 3.65
0 200 400 600 800 1,000
0
10
20
Anzahl der Eintrage im Array
Rec
hen
zeit
inS
eku
nd
en
Blaue Kurve: Rechner 1
Rote Kurve: Rechner 2
Schwarze Kurve: Rechner 3
(doppelt so schnell wie Rechner 2)
Rechenzeiten auf
unterschiedlichen Rechnern
ergeben von der”Form“ her
ahnliche Kurven.
Die Kurve ist von der”Form“
her anders als jede lineare
Kurve.
Rechenzeitanalyse von countTriples 4.1.11
Wie konnen wir experimentell abschatzen, wie die Rechenzeitkurven sich weiter entwickeln?D.h. wie konnen wir – ohne die Funktion z.B. auf einem Array der Große 1000000 zu starten – abschatzen,
wielange die Berechnung der Funktion dauert?
Wie konnen wir eine Aussage uber die Schnelligkeit des Programms machen,
die fur alle unterschiedlich schnellen Rechner nutzlich ist?
Dazu starten wir folgende Messreihe:
wir messen, wie stark sich die Rechenzeit vergroßert, wenn man die Eingabegroße verdoppelt.
Rechenzeitanalyse von countTriples 4.1.12
Die Messreihe wird vom Programm messreiheArray.py durchgefuhrt.
In der Messreihe wird die Rechenzeit der Funktion testfunktion untersucht.
testfunktion hat ein Array a als Argument.
Rechenzeitanalyse von countTriples 4.1.13
Die Messreihe wird vom Programm messreiheArray.py durchgefuhrt.
In der Messreihe wird die Rechenzeit der Funktion testfunktion untersucht.
testfunktion hat ein Array a als Argument.
In jeder Messung der Messreihe wird die Rechenzeit von testfunktion(a) gemessen,
wobei a ein zufallig gewahltes Array einer bestimmten Lange ist.
Beim Start der Messreihe hat a eine vorgegebene Lange.
Die Lange von a wird von Messung zu Messung verdoppelt.
Nach jeder Messung wird ausgegeben,
wie sich die Rechenzeit im Vergleich zur vorherigen Messung vergroßert hat.
Die Messreihe wird beendet, wenn eine vorgegebene Zeit erreicht wurde.
Rechenzeitanalyse von countTriples 4.1.13
In jeder Messung der Messreihe wird die Rechenzeit von testfunktion(a) gemessen,
wobei a ein zufallig gewahltes Array einer bestimmten Lange ist.
Beim Start der Messreihe hat a eine vorgegebene Lange.
Die Lange von a wird von Messung zu Messung verdoppelt.
Nach jeder Messung wird ausgegeben,
wie sich die Rechenzeit im Vergleich zur vorherigen Messung vergroßert hat.
Die Messreihe wird beendet, wenn eine vorgegebene Zeit erreicht wurde.
$ python3 messreiheArray.py threesum countTriples 100 1000
Eing.lange | Rechenzeit | Faktor
------------------------------------
100 | 0.021 |
200 | 0.153 | 7.42
400 | 1.263 | 8.25
800 | 10.181 | 8.06
1600 | 82.237 | 8.08
3200 | 664.290 | 8.08Rechenzeitanalyse von countTriples 4.1.13
In jeder Messung der Messreihe wird die Rechenzeit von testfunktion(a) gemessen,
wobei a ein zufallig gewahltes Array einer bestimmten Lange ist.
Beim Start der Messreihe hat a eine vorgegebene Lange.
Die Lange von a wird von Messung zu Messung verdoppelt.
Nach jeder Messung wird ausgegeben,
wie sich die Rechenzeit im Vergleich zur vorherigen Messung vergroßert hat.
Die Messreihe wird beendet, wenn eine vorgegebene Zeit erreicht wurde.
python3 messreiheArray.py modul funktion startgroesse dauer
fuhrt die Messreihe fur die Funktion funktion aus dem Modul modul.py durch.
Die erste Messung wird auf einem Array der Lange startgroesse durchgefuhrt.
Die Messreihe dauert dauer Sekunden.
Rechenzeitanalyse von countTriples 4.1.13
# messreiheArray.py
#--------------------------------------------------------------------------------------------------
import sys, time
from messreihe import miss, randomArray
# Importiere das Modul mit der Funktion, die fur die Messreihe benutzt wird.
exec('from ' + sys.argv[1] + ' import ' + sys.argv[2] + ' as testfunktion')
n = int(sys.argv[3]) # die Lange des Arrays bei der ersten Messung
versuchsdauer = float(sys.argv[4]) # die Dauer der Messreihe in Sekunden
versuchsEnde = time.time() + versuchsdauer # die Uhrzeit, bei der der Versuch beendet wird
letzteMessung = 0 # die Rechenzeit der letzten Messung
# Gib den Kopf fur die Tabelle mit den Messergebnissen aus.
print( ' %11s | %12s | %6s \n%s' % ('Eing.lange', ' Rechenzeit', 'Faktor', ' '+'-'*36) )
# Fuhre die Messreihe mit wachsendem n durch, bis die Zeit abgelaufen ist.
while time.time() < versuchsEnde:
# Erzeuge das zufallige Array der Lange n fur die nachste Messung.
a = randomArray(n)
# Miss die Rechenzeit von testfunktion(a).
messErgebnis = miss(testfunktion, a)
# Gib das Ergebnis der Messung aus.
if letzteMessung==0: print( '# %12d | %10.3f |' % (n, messErgebnis) )
else: print( '# %12d | %10.3f | %6.2f ' % (n, messErgebnis, messErgebnis/letzteMessung) )
# Bereite die nachste Messung vor.
letzteMessung = messErgebnis
n *= 2
Rechenzeitanalyse von countTriples 4.1.14
$ python3 messreiheArray.py threesum countTriples 100 1000
Eing.lange | Rechenzeit | Faktor
-------------------------------------
100 | 0.021 |
200 | 0.153 | 7.42
400 | 1.263 | 8.25
800 | 10.181 | 8.06
1600 | 82.237 | 8.08
3200 | 664.290 | 8.08
Wir sehen, dass die Verdoppelung der Eingabelange die Rechenzeit etwa verachtfacht.
Wenn t die Funktion ist, die die Eingabelange auf die Rechenzeit abbildet,
gilt also tp2 ¨ nq “ 8 ¨ tpnq
Da p2 ¨ nq3 “ 23 ¨ n3 “ 8 ¨ n3,
konnen wir schließen,
dass die Funktion t eine Funktion der Großenordnung tpnq “ n3 ist.
(Eine genauere Abschatzung ist tpnq “ n3
50673000, aber konstante Faktoren werden z.B.
durch die Geschwindigkeit des Rechners beeinflusst, und deshalb lassen wir sie weg.)
n n3
1 1
2 8
4 64
8 544Rechenzeitanalyse von countTriples 4.1.15
Das Ergebnis der experimentellen Analyse ist also,
dass countTriples bei Eingabe eines Arrays der Lange n
eine Rechenzeit der Großenordnung n3 zu haben scheint.
Lasst sich das auch ohne Experimente am Programm erkennen?
Dazu wollen wir zahlen,
wie oft einzelne Programmzeilen bei der Ausfuhrung des Programms durchlaufen werden.
Bevor wir die Zahlung abstrakt mathematisch machen, machen wir sie experimentell.
Wir konnen unser Programm zur Durchfuhrung und Analyse der Messreihe so umbauen,
dass es die Anzahl aller (wiederholt) ausgefuhrten Programmzeilen zahlt.
Aus Programm arrayMessreihe.py machen wir das Programm arrayMessreiheZ.py
indem Zeile messErgebnis = miss(testfunktion, a) durch
messErgebnis = testfunktion(a) ersetzen.
Das Wort Rechenzeit in der Ausgabe wird durch Zeilenzahler ersetzt.
Das Ausgabeformat in der Spalte Zeilenzahler wird von %10.3f auf %10d geandert.Rechenzeitanalyse von countTriples 4.1.16
# threesumlinecount.py
#----------------------------------------------------
def countTlines(a):
# Fast wie countTriples() in threesum.py,
# aber zusatzlich wird ein Zahler zz mitgefuhrt,
# der nach jeder Ausfuhrung einer Programmzeile
# um 1 erhoht wird. Am Ende des Funktionsaufrufs
# wird der Zahlerwert zuruckgegeben.
zz = 0
n = len(a)
zz += 1
count = 0
zz += 1
for i in range(n-2):
zz += 1
for j in range(i+1,n-1):
zz += 1
for k in range(j+1,n):
zz += 2
if (a[i] + a[j] + a[k]) == 0:
zz += 1
count += 1
return zz
def countTriples(a):
n = len(a)
count = 0
for i in range(n-2):
for j in range(i+1,n-1):
for k in range(j+1,n):
if (a[i] + a[j] + a[k]) == 0:
count += 1
return count
Rechenzeitanalyse von countTriples 4.1.17
Wir starten nun eine Messreihe, mit der wir herausfinden wollen,
wie stark die Verdopplung der Eingabegroße die Anzahl der ausgefuhrten Zeilen (d.h. den
Ruckgabewert von countTlines) erhoht.
Das Ergebnis ist”verbluffend“ und bestatigt die Interpretation der vorherigen Experimente.
$ python3 messreiheArrayZ.py threesumlinecount countTlines 100 200
Eing.lange | Zeilenzahler | Faktor
-------------------------------------
100 | 166718 |
200 | 1333545 | 8.00
400 | 10667556 | 8.00
800 | 85336967 | 8.00
1600 | 682682381 | 8.00
3200 | 5461396585 | 8.00
Wir konnen also die Großenordnung der Rechenzeit auch durch Zahlen der ausgefuhrten
Programmzeilen bestimmen.
Muss man tatsachlich alle ausgefuhrten Programmzeilen zahlen? Rechenzeitanalyse von countTriples 4.1.18
Wir zahlen jetzt nur noch, wie oft die am haufigsten ausgefuhrte Programmzeile ausgefuhrt wird.
# threesumlinecount.py
#---------------------------------------------------------------------------------
# countTinnerline(a) gibt zuruck, wie oft (ungefahr) die "innerste" Programmzeile
# in den verschachtelten Schleifen von threesum.countTriples ausgefuhrt wird.
# Dazu wird ein Zahler zz eingefuhrt, der entsprechend hochgezahlt wird.
def countTinnerline(a):
zz = 0
n = len(a)
count = 0
for i in range(n-2):
for j in range(i+1,n-1):
for k in range(j+1,n):
zz += 1
if (a[i] + a[j] + a[k]) == 0:
count += 1
return zz
def countTriples(a):
n = len(a)
count = 0
for i in range(n-2):
for j in range(i+1,n-1):
for k in range(j+1,n):
if (a[i] + a[j] + a[k]) == 0:
count += 1
return count
Rechenzeitanalyse von countTriples 4.1.19
Wir starten nun eine Messreihe, mit der wir nachschauen,
wie stark die Verdoppelung der Eingabegroße die Anzahl der Ausfuhrungen der”innersten“ Zeile
der Funktion (d.h. den Ruckgabewert von counTinnerline) vergroßert.
Es kommt”im Prinzip“ das gleiche Ergebnis heraus wie zuvor:
Eing.lange | Zeilenzahler | Faktor
-------------------------------------
100 | 161700 |
200 | 1313400 | 8.12
400 | 10586800 | 8.06
800 | 85013600 | 8.03
1600 | 681387200 | 8.02
3200 | 5456214400 | 8.01
Wir haben jetzt auf unterschiedliche Arten (Rechenzeit in Sekunden, Haufigkeit der Ausfuhrung
aller Programmzeilen, Haufigkeit der Ausfuhrung der am haufigsten ausgefuhrten Programmzeile)
experimentell herausgefunden, dass die Rechenzeit bei Eingabegroße n die Großenordnung n3 hat.
Lasst sich das mit einem mathematischen Modell bestatigen?Rechenzeitanalyse von countTriples 4.1.20
2 Abstrakte Schatzung der Rechenzeit
Zuerst versuchen wir abstrakt, die Haufigkeit der Ausfuhrung jeder Programmzeile zu bestimmen.
Programm Haufigkeit der Ausfuhrung der Zeile «
n = len(a) 1
counter = 0 1
for i in range(n-2): n ´ 2 n
for j in range(i+1,n-1): pn ´ 3q ` pn ´ 4q ` . . .` 1 n2
2
for k in range(j+1,n): n3
6
if (a[i]+a[j]+a[k]) == 0: n3
6
counter += 1 abhangig von der Eingabe
die Summe ist: ?
Wir sehen:
1. Wir wissen nicht, wie man zahlen soll, wenn die Ausfuhrung einer Programmzeile von der Eingabe
(und nicht nur von der Eingabegroße) abhangig ist.
2. Eine exakte Zahlung ist da unmoglich.Rechenzeitanalyse von countTriples 4.1.21
2 Abstrakte Schatzung der Rechenzeit
Zuerst versuchen wir abstrakt, die Haufigkeit der Ausfuhrung jeder Programmzeile zu bestimmen.
Programm Haufigkeit der Ausfuhrung der Zeile «
n = len(a) 1
counter = 0 1
for i in range(n-2): n ´ 2 n
for j in range(i+1,n-1): pn ´ 3q ` pn ´ 4q ` . . .` 1 n2
2
for k in range(j+1,n): n3
6
if (a[i]+a[j]+a[k]) == 0: n3
6
counter += 1 abhangig von der Eingabe n3
6
die Summe ist: ?
Wir mussen die Sache also vereinfachen und aufs exakte Zahlen verzichten (Faustregeln):
1. Gehe bei den ausgefuhrten Zeilen vom ungunstigsten Fall aus.
D.h., wenn die Ausfuhrung einer Programmzeile von der Eingabe abhangig ist,
dann nimm an, dass die Eingabe so ist, dass die Zeile ausgefuhrt wird.Rechenzeitanalyse von countTriples 4.1.21
2 Abstrakte Schatzung der Rechenzeit
Zuerst versuchen wir abstrakt, die Haufigkeit der Ausfuhrung jeder Programmzeile zu bestimmen.
Programm Haufigkeit der Ausfuhrung der Zeile «
n = len(a) 1
counter = 0 1
for i in range(n-2): n ´ 2 n
for j in range(i+1,n-1): pn ´ 3q ` pn ´ 4q ` . . .` 1 n2
for k in range(j+1,n): n3
if (a[i]+a[j]+a[k]) == 0: n3
counter += 1 abhangig von der Eingabe n3
die Großenordnung ist n3
Wir mussen die Sache also vereinfachen und aufs exakte Zahlen verzichten (Faustregeln):
2. Bei einem Produkt streicht man alle konstanten Faktoren.
Bei einer Summe nimmt man nur den großten Summanden.
Statt der exakten Schrittzahl erhalt man so ihre Großenordnung.
Rechenzeitanalyse von countTriples 4.1.21
Zusammenfassung der Rechenzeitanalyse von countTriples(a)
Mit der experimentellen Analyse haben wir gesehen,
dass sich fur Eingaben bis zur Lange 3200 die Rechenzeit verachtfacht,
wenn die Eingabelange verdoppelt wird.
Das fuhrt zu der Vermutung, dass die Rechenzeitfunktion die Großenordnung n3 hat
(n ist die Eingabelange).
Bei der abstrakten Analyse haben wir gesehen,
dass die Funktion aus drei ineinandergeschachtelten Schleifen besteht,
die jeweils im (nicht eintretenden) schlechtesten Fall fur Werte 1 . . . n durchlaufen werden.
Deshalb hat die Rechenzeitfunktion die Großenordnung n3.
Diese Analyse liefert eine obere Schranke der Rechenzeit.
Die”echte“ Rechenzeit kann auch eine kleinere Großenordnung haben . . .
Rechenzeitanalyse von countTriples 4.1.22
3 Weitere Beispiele fur Rechenzeitanalysen
§ Sortieren mit Bubblesort
§ Sortieren mit Pythons Sortierfunktion list.sort()
§ Berechnung der Halfte einer int-Zahl
§ Berechnung des Quadrats einer int-Zahl (auch Multiplikation)
§ Berechnung des ganzzahligen Logarithmus zur Basis 2
§ Berechnung einer Fibonacci-Zahl (nicht rekursiv, langsam)
§ Berechnung einer Fibonacci-Zahl (schnell)
§ Berechnung der Potenz 2n (schnell)
§ Berechnung der Potenz 2n (langsam)
Beispiele fur Rechenzeitanalysen 4.1.23
Rechenzeitanalyse von bubblesort(a)
# sortierenUndSuchen.py
#--------------------------------------------------------
# bubblesort(liste) sortiert das Array liste aufsteigend
# mit dem Bubblesort-Algorithmus.
def bubblesort(liste):
getauscht = True
while getauscht:
getauscht = False
for i in range(len(liste)-1):
if liste[i]>liste[i+1]:
liste[i], liste[i+1] = liste[i+1], liste[i]
getauscht = True
Experimentelle Analyse:
python3 messreiheArray.py sortierenUndSuchen \
bubblesort 1000 100
Eing.lange | Rechenzeit | Faktor
------------------------------------
1000 | 0.231 |
2000 | 0.912 | 3.95
4000 | 3.970 | 4.35
8000 | 14.747 | 3.71
16000 | 59.679 | 4.05
32000 | 250.239 | 4.19
Bei Verdoppelung der Eingabelange vervierfacht sich die
Rechenzeit. Das fuhrt zu der Vermutung, dass die
Rechenzeitfunktion t die Eigenschaft tp2 ¨ nq “ 4 ¨ tpnq.
Da p2 ¨ nq2 “ 4 ¨ n2 bzw. da log2 4 “ 2, hat dann
die Rechenzeitfunktion tpnq die Großenordnung n2.Beispiele fur Rechenzeitanalysen 4.1.24
Rechenzeitanalyse von bubblesort(a)
# sortierenUndSuchen.py
#--------------------------------------------------------
# bubblesort(liste) sortiert das Array liste aufsteigend
# mit dem Bubblesort-Algorithmus.
def bubblesort(liste):
getauscht = True
while getauscht:
getauscht = False
for i in range(len(liste)-1):
if liste[i]>liste[i+1]:
liste[i], liste[i+1] = liste[i+1], liste[i]
getauscht = True
Abstrakte Analyse:
Die Funktion hat zwei ineinandergeschachtelte Schleifen.
Die innere Schleife (for-Schleife) wird jedesmal, wenn sie
erreicht wird, etwa n-mal durchlaufen.
Die außere Schleife (while-Schleife) hat folgende
Eigenschaft: die Schleife wird nicht mehr wiederholt, wenn
das Array sortiert ist.
Nach dem ersten Durchlauf steht das großte Element an
der richtigen Stelle und wird nie wieder getauscht, nach
dem zweiten Durchlauf steht auch das zweitgroßte an der
richtigen Stelle und wird nie wieder getauscht usw. Also
ist das Array spatestens nach n Durchlaufen der
while-Schleife sortiert.
Da jede der ineinandergeschachtelten Schleifen bei
Erreichen hochstens n-mal durchlaufen wird, hat die
Rechenzeitfunktion die Großenordnung n2.
Beispiele fur Rechenzeitanalysen 4.1.24
Rechenzeitanalyse von Pythons Sortierfunktion list.sort()
python3 messreiheArray.py sortierenUndSuchen pythonsListSort 1000 100
Eing.lange | Rechenzeit | Faktor
------------------------------------
1000 | 0.000 |
2000 | 0.001 | 2.18
4000 | 0.001 | 2.21
8000 | 0.003 | 2.24
16000 | 0.007 | 2.17
32000 | 0.015 | 2.15
64000 | 0.032 | 2.14
128000 | 0.069 | 2.15
256000 | 0.150 | 2.19
512000 | 0.344 | 2.29
1024000 | 0.797 | 2.32
2048000 | 1.825 | 2.29
4096000 | 4.136 | 2.27
8192000 | 9.338 | 2.26
16384000 | 20.999 | 2.25
Experimentelle Analyse:
Bei Verdoppelung der Eingabelange wachst die Rechenzeit
etwa um einen Faktor 2.2. Das fuhrt zu der Vermutung,
dass die Rechenzeitfunktion t eine Großenordnung etwas
großer als n hat.
Eine solche Großenordnung ist z.B. n ¨ log n.
Optimale Sortierverfahren haben diese Großenordnung.
Beispiele fur Rechenzeitanalysen 4.1.25
Analyse der Rechenzeit von Funktionen mit int-Argument
Die Messreihe geht genauso wie fur Funktionen mit Array-Argument,
aber statt des Array-Arguments wird ein int-Argument genommen,
dessen Lange von Messung zu Messung verdoppelt wird.
Die Verdoppelung der Lange wird (ungefahr) durch Quadrieren erreicht.
Beispiele fur Rechenzeitanalysen 4.1.26
# messreiheInt.py
#-----------------------------------------------------------------------------------
import sys, time
from messreihe import miss
from funktionen import logd as laenge
# Importiere das Modul mit der Funktion, die fur die Messreihe benutzt wird.
exec('from ' + sys.argv[1] + ' import ' + sys.argv[2] + ' as testfunktion')
n = int(sys.argv[3]) # das Argument fur die erste Messung
versuchsdauer = float(sys.argv[4]) # die Dauer der Messreihe in Sekunden
versuchsEnde = time.time() + versuchsdauer # die Uhrzeit, bei der der Versuch beendet wird
letzteMessung = 0 # die Rechenzeit der letzten Messung
# Gib den Kopf fur die Tabelle mit den Messergebnissen aus.
print( ' %12s | %12s | %6s \n%s' % ('Eing.lange', ' Rechenzeit', 'Faktor', '-'*42) )
# Fuhre die Messreihe mit wachsendem n durch, bis die Zeit abgelaufen ist.
while time.time() < versuchsEnde:
# Miss die Rechenzeit von testfunktion(a).
messErgebnis = miss(testfunktion, n)
# Gib das Ergebnis der Messung aus.
if letzteMessung==0: print( ' %15d | %10.3f |' % (laenge(n), messErgebnis) )
else: print( ' %15d | %10.3f | %6.2f ' % (laenge(n), messErgebnis, messErgebnis/letzteMessung) )
# Bereite die nachste Messung vor.
letzteMessung = messErgebnis
n *= n
Beispiele fur Rechenzeitanalysen 4.1.27
Rechenzeitanalyse der Halbierung x//2
# funktionen.py
#------------------------------------------
# halbiere(x) gibt die ganzzahlige Halfte
# von x (Typ int) zuruck.
def halbiere( x ):
x = x//2
return x
Experimentelle Analyse:
python3 messreiheInt.py funktionen halbiere 1000000 200
Eing.lange | Rechenzeit | Faktor
-------------------------------------
19 | 0.000 |
39 | 0.000 | 0.11
79 | 0.000 | 1.00
159 | 0.000 | 1.00
318 | 0.000 | 1.00
637 | 0.000 | 7.50
1275 | 0.000 | 0.27
2551 | 0.000 | 1.50
5102 | 0.000 | 4.50
10204 | 0.000 | 0.93
20409 | 0.000 | 1.88
40819 | 0.000 | 1.70
81639 | 0.000 | 1.93
163279 | 0.000 | 1.89
326558 | 0.000 | 2.06
653117 | 0.000 | 1.92
1306235 | 0.001 | 2.32
Bei Verdoppelung der Eingabelange n verdoppelt sich die
Rechenzeit.
Beispiele fur Rechenzeitanalysen 4.1.28
Rechenzeitanalyse der Halbierung x//2
# funktionen.py
#------------------------------------------
# halbiere(x) gibt die ganzzahlige Halfte
# von x (Typ int) zuruck.
def halbiere( x ):
x = x//2
return x
Experimentelle Analyse:
Bei Verdoppelung der Eingabelange n verdoppelt sich die
Rechenzeit. Das fuhrt zu der Vermutung, dass die
Rechenzeitfunktion t die Eigenschaft tp2 ¨ nq “ 2 ¨ tpnq.
Da p2 ¨ nq “ 2 ¨ n bzw. da log2 2 “ 1, hat dann
die Rechenzeitfunktion tpnq die Großenordnung n1 (d.h. n).
Beispiele fur Rechenzeitanalysen 4.1.28
Rechenzeitanalyse der Halbierung x//2
# funktionen.py
#------------------------------------------
# halbiere(x) gibt die ganzzahlige Halfte
# von x (Typ int) zuruck.
def halbiere( x ):
x = x//2
return x
Abstrakte Analyse:
Die Funktion hat keine Schleifen und nur die Anweisung
x = x//2.
Die Halbierung findet wie mittels”schriftlicher Addition“ statt.
Dabei geht man einmal alle Ziffern der zu halbierenden Zahl
durch und macht fur jede Ziffer eine kleine Anzahl Operationen.
Also erhalt man die Anzahl der Ziffern der Zahl (d.h. ihre
Lange) als Großenordnung der Rechenzeitfunktion, d.h.
tpnq “ n.
Beispiele fur Rechenzeitanalysen 4.1.28
Rechenzeitanalyse des Quadrierens x*x
# funktionen.py
#------------------------------------------
# quadriere(x) gibt fur x vom Typ int
# gibt x*x zuruck.
def quadriere( x ):
x = x*x
return x
Experimentelle Analyse:
python3 messreiheInt.py funktionen quadriere 10000 100
Eing.lange | Rechenzeit | Faktor
-------------------------------------
13 | 0.000 |
26 | 0.000 | 1.00
53 | 0.000 | 1.50
106 | 0.000 | 1.00
212 | 0.000 | 1.00
425 | 0.000 | 1.33
850 | 0.000 | 1.50
1700 | 0.000 | 2.50
3401 | 0.000 | 4.47
6803 | 0.000 | 2.82
13606 | 0.000 | 2.39
27213 | 0.000 | 2.94
54426 | 0.001 | 2.84
108852 | 0.003 | 3.09
217705 | 0.008 | 2.96
435411 | 0.025 | 2.99
870823 | 0.073 | 2.98
Bei Verdoppelung der Eingabelange n verdreifacht sich die
Rechenzeit.
Beispiele fur Rechenzeitanalysen 4.1.29
Rechenzeitanalyse des Quadrierens x*x
# funktionen.py
#------------------------------------------
# quadriere(x) gibt fur x vom Typ int
# gibt x*x zuruck.
def quadriere( x ):
x = x*x
return x
Experimentelle Analyse:
Bei Verdoppelung der Eingabelange n verdreifacht sich die
Rechenzeit. Das fuhrt zu der Vermutung, dass die
Rechenzeitfunktion t die Eigenschaft tp2 ¨ nq “ 3 ¨ tpnq hat.
Da p2 ¨ nqlog2 3“ 2 ¨ nlog2 3, hat
die Rechenzeitfunktion tpnq die Großenordnung nlog2 3« n1.58.
Beispiele fur Rechenzeitanalysen 4.1.29
Rechenzeitanalyse des Quadrierens x*x
# funktionen.py
#------------------------------------------
# quadriere(x) gibt fur x vom Typ int
# gibt x*x zuruck.
def quadriere( x ):
x = x*x
return x
Abstrakte Analyse:
Wenn man wie bei der”schriftlichen Multiplikation“ quadriert,
erhalt man eine Rechenzeit der Großenordnung n2.
Es gibt aber auch andere Algorithmen zum Multiplizieren.
Der Karazuba-Algorithmus hat eine Rechenzeit der
Großenordnung nlog2 3.
Jetzt kann man stark vermuten, dass Python diesen
Algorithmus verwendet.
Bemerkung zur Multiplikation zweier Zahlen:
Die Multiplikation von a und b hat die entsprechende
Rechenzeit der Großenordnung
pLange von a` Lange von bqlog2 3.
Beispiele fur Rechenzeitanalysen 4.1.29
Rechenzeitanalyse von logd(x)
# funktionen.py
#------------------------------
# logd(x) gibt den ganzzahligen
# 2er-Logarithmus von x zuruck.
def logd( x ):
i = 0
while x>1:
x = x//2
i += 1
return i
Experimentelle Analyse:
python3 messreiheInt.py funktionen logd 1000000 200
Eingabelange n | Rechenzeit | Faktor
--------------------------------------
19 | 0.000 |
39 | 0.000 | 1.63
79 | 0.000 | 1.81
159 | 0.000 | 2.21
318 | 0.000 | 2.41
637 | 0.000 | 2.78
1275 | 0.001 | 2.83
2551 | 0.002 | 3.43
5102 | 0.007 | 3.68
10204 | 0.027 | 3.76
20409 | 0.099 | 3.74
40819 | 0.390 | 3.92
81639 | 1.542 | 3.96
163279 | 6.185 | 4.01
326558 | 24.649 | 3.99
653117 | 98.404 | 3.99
Bei Verdoppelung der Eingabelange vervierfacht sich die Rechenzeit.Beispiele fur Rechenzeitanalysen 4.1.30
Rechenzeitanalyse von logd(x)
# funktionen.py
#------------------------------
# logd(x) gibt den ganzzahligen
# 2er-Logarithmus von x zuruck.
def logd( x ):
i = 0
while x>1:
x = x//2
i += 1
return i
Experimentelle Analyse:
Bei Verdoppelung der Eingabelange vervierfacht sich die Rechenzeit.
Das fuhrt zu der Vermutung, dass die Rechenzeitfunktion t die
Eigenschaft tp2 ¨ nq “ 4 ¨ tpnq hat.
Da p2 ¨ nq2 “ 4 ¨ n2 bzw. da log2 4 “ 2, hat
die Rechenzeitfunktion tpnq die Großenordnung n2.
Beispiele fur Rechenzeitanalysen 4.1.30
Rechenzeitanalyse von logd(x)
# funktionen.py
#------------------------------
# logd(x) gibt den ganzzahligen
# 2er-Logarithmus von x zuruck.
def logd( x ):
i = 0
while x>1:
x = x//2
i += 1
return i
Abstrakte Analyse:
Die Funktion hat eine Schleife.
Bei Eingabelange n wird sie (etwa) n-mal durchlaufen.
In der Schleife findet eine Halbierung statt.
Die Rechenzeit der Halbierung einer Zahl der Lange n hat
Großenordnung n.
Also hat jeder Schleifendurchlauf Rechenzeit der Großenordnung n.
Da die Schleife n-mal durchlaufen wird,
hat die Rechenzeit tpnq die Großenordnung n ¨ n “ n2.
Die innere Schleife (for-Schleife) wird jedesmal, wenn sie erreicht
wird, etwa n-mal durchlaufen.
Beispiele fur Rechenzeitanalysen 4.1.30
Rechenzeitanalyse des schnellen Potenzierens potenziere(x)
# funktionen.py
#---------------------------------------
# potenziere(n) berechnet "2 hoch n"
# mittels wiederholtem Quadrieren.
def potenziere(x):
if x==0: return 1
elif x==1: return 2
else:
b = potenziere(x//2)
q = b*b
if x%2==0: return q
else: return q*2
Experimentelle Analyse:
python3 messreiheInt.py funktionen potenziere 10 200
Eing.lange | Rechenzeit | Faktor
-------------------------------------
3 | 0.000 |
6 | 0.000 | 1.00
13 | 0.000 | 8.94
26 | 0.647 | 17852.82
Killed
Es scheint keinen festen Faktor zu geben, um den sich die Rechenzeit
bei Verdoppelung der Eingabelange vergroßert.
Beispiele fur Rechenzeitanalysen 4.1.31
Rechenzeitanalyse des schnellen Potenzierens potenziere(x)
# funktionen.py
#---------------------------------------
# potenziere(n) berechnet "2 hoch n"
# mittels wiederholtem Quadrieren.
def potenziere(x):
if x==0: return 1
elif x==1: return 2
else:
b = potenziere(x//2)
q = b*b
if x%2==0: return q
else: return q*2
Experimentelle Analyse:
Es scheint keinen festen Faktor zu geben, um den sich die Rechenzeit
bei Verdoppelung der Eingabelange vergroßert.
Das fuhrt zu der Vermutung, dass die Rechenzeitfunktion tpnq keine
Großenordnung n, n2, n3, n4, . . . hat.
D.h. die Funktion hat keine polynomielle Rechenzeit.
Wir konnen sie auf exponentielle Rechenzeit testen.
Dazu andern wir in der Messreihe die Vergroßerung der Eingabelange
von Messung zu Messung.
Bisher – beim Test auf polynomielle Rechenzeit – wird die
Eingabelange von Messung zu Messung verdoppelt (indem der
Eingabewert quadriert wird).
Beim Test auf exponentielle Rechenzeit wird die Eingabelange von
Messung zu Messung um 1 vergroßert (indem der Eingabewert
verdoppelt wird).
Beispiele fur Rechenzeitanalysen 4.1.31
# messreiheIntExpo.py
#-----------------------------------------------------------------------------------
# wie messreiheInt.py, aber die Lange des Arguments fur die Testfunktionen wird von
# Messung zu Messung um 1 vergroßert, indem das Argument verdoppelt wird.
#-----------------------------------------------------------------------------------
import sys, time
from messreihe import miss
from funktionen import logd as laenge
# Importiere das Modul mit der Funktion, die fur die Messreihe benutzt wird.
exec('from ' + sys.argv[1] + ' import ' + sys.argv[2] + ' as testfunktion')
n = int(sys.argv[3]) # das Argument fur die erste Messung
versuchsdauer = float(sys.argv[4]) # die Dauer der Messreihe in Sekunden
versuchsEnde = time.time() + versuchsdauer # die Uhrzeit, bei der der Versuch beendet wird
letzteMessung = 0 # die Rechenzeit der letzten Messung
# Gib den Kopf fur die Tabelle mit den Messergebnissen aus.
print( ' %14s | %12s | %6s \n%s' % ('Eingabelange n', ' Rechenzeit', 'Faktor', '-'*42) )
# Fuhre die Messreihe mit wachsendem n durch, bis die Zeit abgelaufen ist.
while time.time() < versuchsEnde:
# Miss die Rechenzeit von testfunktion(a).
messErgebnis = miss(testfunktion, n)
# Gib das Ergebnis der Messung aus.
if letzteMessung==0: print( ' %15d | %10.3f |' % (laenge(n), messErgebnis) )
else: print( ' %15d | %10.3f | %6.2f ' % (laenge(n), messErgebnis, messErgebnis/letzteMessung) )
# Bereite die nachste Messung vor.
letzteMessung = messErgebnis
n *= 2
Beispiele fur Rechenzeitanalysen 4.1.32
Rechenzeitanalyse von fiboDirekt(x)
# funktionen.py
#---------------------------------------------------
# fiboDirekt(x) gibt die x-te Fibonacci-Zahl zuruck.
# Die Berechnung erfolgt iterativ.
def fiboDirekt(x):
a = 0
b = 1
for i in range(2,x+1):
b, a = a+b, b
return b
Experimentelle Analyse auf exponentielle Rechenzeit:
python3 messreiheIntExpo.py funktionen fiboDirekt 10000 40
Eing.lange | Rechenzeit | Faktor
------------------------------------
13 | 0.004 |
14 | 0.011 | 2.68
15 | 0.034 | 3.12
16 | 0.115 | 3.33
17 | 0.409 | 3.57
18 | 1.556 | 3.80
19 | 6.089 | 3.91
20 | 24.310 | 3.99
21 | 98.427 | 4.05
Bei Vergroßerung der Eingabelange um 1 vervierfacht sich die
Rechenzeit.
Beispiele fur Rechenzeitanalysen 4.1.33
Rechenzeitanalyse von fiboDirekt(x)
# funktionen.py
#---------------------------------------------------
# fiboDirekt(x) gibt die x-te Fibonacci-Zahl zuruck.
# Die Berechnung erfolgt iterativ.
def fiboDirekt(x):
a = 0
b = 1
for i in range(2,x+1):
b, a = a+b, b
return b
Experimentelle Analyse auf exponentielle Rechenzeit:
Bei Vergroßerung der Eingabelange um 1 vervierfacht sich die
Rechenzeit.
Das fuhrt zu der Vermutung, dass die Rechenzeitfunktion t die
Eigenschaft tpn ` 1q “ 4 ¨ tpnq hat.
Da 4n`1“ 4 ¨ 4n, hat dann
die Rechenzeitfunktion tpnq die Großenordnung 4n.
Beispiele fur Rechenzeitanalysen 4.1.33
Rechenzeitanalyse von fiboDirekt(x)
# funktionen.py
#---------------------------------------------------
# fiboDirekt(x) gibt die x-te Fibonacci-Zahl zuruck.
# Die Berechnung erfolgt iterativ.
def fiboDirekt(x):
a = 0
b = 1
for i in range(2,x+1):
b, a = a+b, b
return b
Abstrakte Analyse:
Die Funktion hat eine Schleife.
Bei Eingabelange n wird sie (etwa) 2n-mal durchlaufen.
Die Fibonacci-Zahlen wachsen sehr schnell.
Die Großenordnung der Fibonacci-Funktion fibpxq ist 2x .
Da fibpxq in der Funktion im Extremfall etwa 22n ist,
benotigt die Addition in der Schleife Zeit der Großenordnung
log2 22n“ 2n.
Da die Schleife 2n-mal durchlaufen wird,
hat die Rechenzeit tpnq der Funktion die Großenordnung
2n¨ 2n
“ 22n“ 4n.
Beispiele fur Rechenzeitanalysen 4.1.33
Rechenzeitanalyse von fiboSchnell(x)
# funktionen.py
#-----------------------------------------------------
# fibo(b) gibt (fib_{b-1},fib_{b}) zuruck.
# Es gilt:
# fib_{2n} = fib_{n}*fib_{n-1} + fib_{n+1}*fib_{n}
# fib_{2n+1} = fib_{n}**2 + fib_{n+1}**2
def fibo(b):
if b<=1: return (0,b)
if b%2==1:
(x,y) = fibo(b//2)
return ( y*x+(x+y)*y, y**2+(x+y)**2 )
(x,y) = fibo(b//2)
return ( x*x+y*y, y*(2*x+y) )
#-----------------------------------------------------
# fiboSchnell(n) gibt fib_n zuruck. Die Berechnung
# erfolgt mit der schnellen Funktion fibo(n)
def fiboSchnell(x):
return fibo(x)[1]
Experimentelle Analyse auf exponentielle Rechenzeit:
python3 messreiheIntExpo.py funktionen fiboSchnell 10000 40
Eing.lange | Rechenzeit | Faktor
-------------------------------------
13 | 0.000 |
14 | 0.000 | 2.54
15 | 0.001 | 2.70
16 | 0.002 | 2.80
17 | 0.005 | 3.11
18 | 0.016 | 3.05
19 | 0.046 | 2.95
20 | 0.135 | 2.95
21 | 0.402 | 2.97
22 | 1.222 | 3.04
23 | 3.644 | 2.98
24 | 11.002 | 3.02
25 | 33.748 | 3.07
Bei Vergroßerung der Eingabelange um 1 verdreifacht sich die
Rechenzeit.Beispiele fur Rechenzeitanalysen 4.1.34
Rechenzeitanalyse von fiboSchnell(x)
# funktionen.py
#-----------------------------------------------------
# fibo(b) gibt (fib_{b-1},fib_{b}) zuruck.
# Es gilt:
# fib_{2n} = fib_{n}*fib_{n-1} + fib_{n+1}*fib_{n}
# fib_{2n+1} = fib_{n}**2 + fib_{n+1}**2
def fibo(b):
if b<=1: return (0,b)
if b%2==1:
(x,y) = fibo(b//2)
return ( y*x+(x+y)*y, y**2+(x+y)**2 )
(x,y) = fibo(b//2)
return ( x*x+y*y, y*(2*x+y) )
#-----------------------------------------------------
# fiboSchnell(n) gibt fib_n zuruck. Die Berechnung
# erfolgt mit der schnellen Funktion fibo(n)
def fiboSchnell(x):
return fibo(x)[1]
Experimentelle Analyse auf exponentielle Rechenzeit:
Bei Vergroßerung der Eingabelange um 1 verdreifacht sich die
Rechenzeit.
Das fuhrt zu der Vermutung, dass die Rechenzeitfunktion t die
Eigenschaft tpn ` 1q “ 3 ¨ tpnq hat.
Da 3n`1“ 3 ¨ 3n, hat dann
die Rechenzeitfunktion tpnq die Großenordnung 3n.
Beispiele fur Rechenzeitanalysen 4.1.34
Rechenzeitanalyse von fiboSchnell(x)
# funktionen.py
#-----------------------------------------------------
# fibo(b) gibt (fib_{b-1},fib_{b}) zuruck.
# Es gilt:
# fib_{2n} = fib_{n}*fib_{n-1} + fib_{n+1}*fib_{n}
# fib_{2n+1} = fib_{n}**2 + fib_{n+1}**2
def fibo(b):
if b<=1: return (0,b)
if b%2==1:
(x,y) = fibo(b//2)
return ( y*x+(x+y)*y, y**2+(x+y)**2 )
(x,y) = fibo(b//2)
return ( x*x+y*y, y*(2*x+y) )
#-----------------------------------------------------
# fiboSchnell(n) gibt fib_n zuruck. Die Berechnung
# erfolgt mit der schnellen Funktion fibo(n)
def fiboSchnell(x):
return fibo(x)[1]
Abstrakte Analyse:
Die Funktion ist rekursiv.
Die Rekursionstiefe ist log2 x – also ungefahr die Lange n von x .
Das fallt nicht weiter ins Gewicht.
Die Fibonacci-Zahlen wachsen sehr schnell.
Die Großenordnung der Fibonacci-Funktion fibpxq ist 2x .
Da fibpxq in der Funktion im Extremfall Lange 2n hat (n ist die
Lange von x),
benotigen die Multiplikationen in den return-Anweisungen
Rechenzeit der Großenordnung p2nq
1.5“ 21.5¨n
“ 3n.
Beispiele fur Rechenzeitanalysen 4.1.34
Rechenzeitanalyse des schnellen Potenzierens potenziere(x)
# funktionen.py
#---------------------------------------
# potenziere(n) berechnet "2 hoch n"
# mittels wiederholtem Quadrieren.
def potenziere(x):
if x==0: return 1
elif x==1: return 2
else:
b = potenziere(x//2)
q = b*b
if x%2==0: return q
else: return q*2
Experimentelle Analyse:
python3 messreiheIntExpo.py funktionen potenziere 10000 20
Eingabelange n | Rechenzeit | Faktor
------------------------------------------
13 | 0.000 |
14 | 0.000 | 2.03
15 | 0.001 | 2.48
16 | 0.001 | 1.85
17 | 0.002 | 2.14
18 | 0.004 | 2.12
19 | 0.009 | 2.19
20 | 0.019 | 2.07
21 | 0.041 | 2.11
22 | 0.086 | 2.10
23 | 0.183 | 2.13
24 | 0.389 | 2.13
25 | 0.828 | 2.13
26 | 1.755 | 2.12
27 | 3.712 | 2.12
28 | 7.785 | 2.10
29 | 16.315 | 2.10
Bei Vergroßerung der Eingabelange um 1 verdoppelt sich die
Rechenzeit.
Beispiele fur Rechenzeitanalysen 4.1.35
Rechenzeitanalyse des schnellen Potenzierens potenziere(x)
# funktionen.py
#---------------------------------------
# potenziere(n) berechnet "2 hoch n"
# mittels wiederholtem Quadrieren.
def potenziere(x):
if x==0: return 1
elif x==1: return 2
else:
b = potenziere(x//2)
q = b*b
if x%2==0: return q
else: return q*2
Experimentelle Analyse:
Bei Vergroßerung der Eingabelange um 1 verdoppelt sich die
Rechenzeit.
Das fuhrt zu der Vermutung, dass die Rechenzeitfunktion t die
Eigenschaft tpn ` 1q “ 2 ¨ tpnq hat.
Da 2n`1“ 2 ¨ 2n, hat dann
die Rechenzeitfunktion tpnq die Großenordnung 2n.
Beispiele fur Rechenzeitanalysen 4.1.35
Rechenzeitanalyse des langsamen Potenzierens
potenziereLangsam(x)
# funktionen.py
#---------------------------------------
# Berechne "2 hoch n" mittels
# wiederholtem Multiplizieren.
def potenziereLangsam(n):
e = 1
for i in range(n):
e *= 2
return e
Experimentelle Analyse:
python3 messreiheIntExpo.py funktionen potenziereLangsam 100 20
Eingabelange n | Rechenzeit | Faktor
------------------------------------------
6 | 0.000 |
7 | 0.000 | 1.78
8 | 0.000 | 2.43
9 | 0.000 | 2.59
10 | 0.000 | 2.51
11 | 0.001 | 2.75
12 | 0.004 | 3.19
13 | 0.015 | 3.44
14 | 0.052 | 3.49
15 | 0.194 | 3.69
16 | 0.746 | 3.85
17 | 2.975 | 3.99
18 | 11.914 | 4.00
19 | 47.910 | 4.02
Bei Vergroßerung der Eingabelange um 1 vervierfacht sich die
Rechenzeit.
Beispiele fur Rechenzeitanalysen 4.1.36
Rechenzeitanalyse des langsamen Potenzierens
potenziereLangsam(x)
# funktionen.py
#---------------------------------------
# Berechne "2 hoch n" mittels
# wiederholtem Multiplizieren.
def potenziereLangsam(n):
e = 1
for i in range(n):
e *= 2
return e
Experimentelle Analyse:
Bei Vergroßerung der Eingabelange um 1 vervierfacht sich die
Rechenzeit.
Das fuhrt zu der Vermutung, dass die Rechenzeitfunktion t die
Eigenschaft tpn ` 1q “ 4 ¨ tpnq hat.
Da 4n`1“ 4 ¨ 4n, hat dann
die Rechenzeitfunktion tpnq die Großenordnung 4n.
Beispiele fur Rechenzeitanalysen 4.1.36
Rechenzeitanalyse der binaren Suche binaereNullSuche(a)
#------------------------------------------------------
# binareSuche(liste, ziel) sucht mittels
# binarer Suche nach ziel im (aufsteigend sortierten)
# Array liste.
def binaereSuche(liste, ziel):
links = 0
rechts = len(liste)-1
mitte = (links+rechts)//2
while not liste[mitte]==ziel and links<rechts:
if liste[mitte]>ziel: rechts = mitte-1
else: links = mitte+1
mitte = (links+rechts)//2
if liste[mitte]==ziel: return mitte
else: return -1
#--------------------------------------------------------
# binareNullSuche(liste) sucht mittels binarer Suche
# nach dem Eintrag 0 im sortierten Array liste.
def binaereNullSuche(liste):
return binaereSuche(liste, 0)
Experimentelle Analyse:
python3 messreiheArray.py sortierenUndSuchen \
binaereNullSuche 1000 10
Eing,lange | Rechenzeit | Faktor
------------------------------------
8000 | 0.000 |
16000 | 0.000 | 1.16
32000 | 0.000 | 0.79
64000 | 0.000 | 1.56
128000 | 0.000 | 1.14
256000 | 0.000 | 1.25
512000 | 0.000 | 1.21
1024000 | 0.000 | 1.08
2048000 | 0.000 | 1.02
4096000 | 0.000 | 1.01
Bei Verdoppelung der Eingabelange vergroßert sich die
Rechenzeit kaum. Das fuhrt zu der Vermutung, dass die
Großenordnung der Rechenzeitfunktion kleiner als
polynomiell (n, n2, . . .) ist.Beispiele fur Rechenzeitanalysen 4.1.37
Rechenzeitanalyse der binaren Suche binaereNullSuche(a)
#------------------------------------------------------
# binareSuche(liste, ziel) sucht mittels
# binarer Suche nach ziel im (aufsteigend sortierten)
# Array liste.
def binaereSuche(liste, ziel):
links = 0
rechts = len(liste)-1
mitte = (links+rechts)//2
while not liste[mitte]==ziel and links<rechts:
if liste[mitte]>ziel: rechts = mitte-1
else: links = mitte+1
mitte = (links+rechts)//2
if liste[mitte]==ziel: return mitte
else: return -1
#--------------------------------------------------------
# binareNullSuche(liste) sucht mittels binarer Suche
# nach dem Eintrag 0 im sortierten Array liste.
def binaereNullSuche(liste):
return binaereSuche(liste, 0)
Abstrakte Analyse:
Die Funktion enthalt eine while-Schleife.
In jedem Durchlauf der Schleife wird die Große des
Bereichs links...rechts halbiert. Also wird die Schleife
bei Eingabe eines Arrays der Lange n hochstens log2 n-mal
durchlaufen.
Die Indizes, mit denen gerechnet wird, haben hochstens
Wert n und folglich Lange log2pnq.
Halbieren und Addieren mit diesen Indizes haben
Rechenzeit der Großenordnung log2pnq.
Die Rechenzeitfunktion tpnq hat also Großenordnung
log2pnq ¨ log2pnq.
Beispiele fur Rechenzeitanalysen 4.1.37
Rechenzeitanalyse eines schnelleren countTriples(a)
# Zahlt die Tripel mit Summe 0 im Array a.
Funktion countTriplesSchnell(a):
sortiere a
count = 0
for i in range(0,len(a)-2):
for j in range(i+1, len(a)-1):
suche mit binarer Suche nach -(a[i]+a[j]) in a
falls es gefunden wurde:
count += 1
return count
Abstrakte Analyse:
Die Funktion sortiert zuerst ein Array der Lange n. Das
hat Rechenzeit der Großenordnung n ¨ logpnq.
Anschließend durchlauft die Funktion zwei
ineinandergeschachtelte Schleifen.
Beispiele fur Rechenzeitanalysen 4.1.38
Rechenzeitanalyse eines schnelleren countTriples(a)
# Zahlt die Tripel mit Summe 0 im Array a.
Funktion countTriplesSchnell(a):
sortiere a
count = 0
for i in range(0,len(a)-2):
for j in range(i+1, len(a)-1):
suche mit binarer Suche nach -(a[i]+a[j]) in a
falls es gefunden wurde:
count += 1
return count
Abstrakte Analyse:
Die Funktion sortiert zuerst ein Array der Lange n. Das
hat Rechenzeit der Großenordnung n ¨ logpnq.
Anschließend durchlauft die Funktion zwei
ineinandergeschachtelte Schleifen.
Die Schleifen werden beide jeweils hochsten n-mal
durchlaufen werden.
Im Inneren der Schleifen findet eine binare Suche in einem
Array der Lange n statt. Sie hat Rechenzeit der
Großenordnung plog2pnqq2.
Also hat der Teil der Funktion mit den Schleifen
Rechenzeit der Großenordnung n ¨ n ¨ plog2pnqq2.
Beispiele fur Rechenzeitanalysen 4.1.38
Rechenzeitanalyse eines schnelleren countTriples(a)
# Zahlt die Tripel mit Summe 0 im Array a.
Funktion countTriplesSchnell(a):
sortiere a
count = 0
for i in range(0,len(a)-2):
for j in range(i+1, len(a)-1):
suche mit binarer Suche nach -(a[i]+a[j]) in a
falls es gefunden wurde:
count += 1
return count
Abstrakte Analyse:
Die Funktion sortiert zuerst ein Array der Lange n. Das
hat Rechenzeit der Großenordnung n ¨ logpnq.
Anschließend durchlauft die Funktion zwei
ineinandergeschachtelte Schleifen.
Dieser Teil der Funktion hat Rechenzeit der
Großenordnung n ¨ n ¨ plog2pnqq2.
Die Rechenzeit der Funktion ist die Summe der
Rechenzeiten der beiden Teile”Sortieren“ und
”Schleifen“.
Da die Rechenzeit von”Sortieren“ kleiner ist als die von
”Schleifen“,
Also hat die Funktion eine Rechenzeit der Großenordnung
pn ¨ log2pnqq2.
Da pn ¨ log2pnqq2ă n3, ist diese Funktion schneller als die
am Anfang der Vorlesung implementierte Funktion
countTriples(a).
Beispiele fur Rechenzeitanalysen 4.1.38
Klassifikationen gemaß der Großenordnung des Wachstums der
Rechenzeit
Großenordnung des Wachstums Faktor fur die
VerdoppelungshypotheseBeschreibung Funktion
konstant 1 1
logarithmisch log n 1
linear n 2
linearithmisch n ¨ log n 2.1
quadratisch n2 4
kubisch n3 8
exponentiell 2n 2n
Beispiele fur Rechenzeitanalysen 4.1.39
Zusammenfassung
Die Großenordnung der Rechenzeit eines Programms oder eines Algorithmus gibt verlassliche Auskunft uber
die”Schnelligkeit“ des Programms.
Wir haben gesehen, wie man sie experimentell abschatzen und abstrakt mathematisch anchweisen kann.
Dabei brauchen wir unterschiedliche experimentelle Tests fur die Analyse auf polynomielle Rechenzeit bzw.
exponentielle Rechenzeit.
Die folgende Tabelle enthalt typische Rechenzeitfunktionen mit dem Namen ihrer Großenordnung, und den
Zuwachs an Rechenzeit eines Programms, das bei Eingabegroße m wenige Sekunden braucht, bei einer
Eingabe der Große 100 ¨m.
Großenordnung der Verlangerung der
Rechenzeitfunktion Beispiel Rechenzeit (s.o.)
linear tp`q “ ` wenige Minuten
quasi-linear tp`q “ ` ¨ log ` wenige Minuten
quadratisch tp`q “ ` 2 einige Stunden
kubisch tp`q “ ` 3 ein paar Wochen
exponentiell tp`q “ 2` ewig 4.1.40
4.6 Suche nach Wegen in NetzwerkenDas Small-World-Phanomen
Die Untersuchung von Netzwerken hat sich – verstarkt durch die weltweite Vernetzung – zu einem
lebendigen Forschungsgebiet entwickelt.
Aber bereits in den 1960er Jahren hat man sich mit Fragen beschaftigt, die man erst seit wenigen
Jahren z.B. mit den”Freundschaftsnetzwerk“ der sozialen Netzwerke beantworten kann.
Das Small-World-Experiment (Stanley Milgram, 1967) sollte herausfinden, wie kurz der”Abstand“
zwischen zwei beliebigen Menschen ist. Dieser Abstand ist die Lange der kurzesten Kette von
Freunden, Freunden von Freunden usw., die die beiden Menschen verbindet. Milgram vermutete,
dass diese Ketten zwischen zwei beliebigen Menschen hochstens Lange 6 haben.
Wir werden sehen, wie man das algorithmisch uberprufen konnte, wenn wir das
Freunschaftsnetzwerk hatten.
Da wir es nicht haben, schauen wir uns die Frage abstrakt an und losen sie fur beliebige Netzwerke.
Das Small-World-Phanomen 4.6.1
Vorlesung 12
4. Algorithmen
4.1 Rechenzeit
4.6 Das Small-World-Problem und die Suche nach Wegen in NetzwerkenNetzwerke und ihre Speicherung
Kurzeste Wege in Netzwerken
Kurzeste Wege in gewichteten Netzwerken
Das Small-World-Phanomen 4.6.2
1 Netzwerke (aus Knoten und Kanten)
Unser Beispielnetzwerk besteht aus Flughafen und Direktflugen zwischen ihnen.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
Knoten
a b Kante zwischen Knoten a und Knoten b (und zwischen b und a)
Knoten
(Flughafen)
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVA
XYG
WMI
Kanten
(Direktfluge in
beide Richtungen)
FRA TXL
FRA AMS
AMS CDG
CDG LCY
LCY AMS
TXL WMI
WMI XYG
CDG MRS
MRS GVA
MRS FCO
GVA XYG
FCO XYG
FRA GVA
FRA XYG
Netzwerke 4.6.3
Noch ein Netzwerk (aus Knoten und Kanten)
aus: Introduction to Programming in Python (Sedgewick, Wayne, Dondero, 2015)
Netzwerke 4.6.4
Anwendungen von Netzwerken
§ Verkehrssysteme
§ Kommunikationssysteme
§ Humanbiologie
§ Soziale Netzwerke
§ Physikalische Systeme
§ Softwaresysteme
§ Finanzsysteme
Netzwerke 4.6.5
Darstellung von Netzwerken als Textdateien
(siehe z.B. flights.txt und movies.txt)
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVA
XYG
WMI
Pro Zeile: ein Knoten und weitere Knoten, zu
denen er eine Kante hat.
Dazwischen jeweils ein Trennzeichen.
Kanten konnen mehrfach vorkommen.
beispielnetzwerk.txt:
FRA TXL
FRA AMS
AMS CDG
...
GVA XYG
FCO XYG
FRA GVA
FRA XYG
bspnetzwerk.txt:
FRA/TXL/AMS/GVA/XYG
AMS/FRA/LCY/CDG
CDG/LCY/MRS
TXL/WMI
XYG/WMI/FCO/GVA
MRS/GVA/FCO
Netzwerke 4.6.6
Die Speicherung von Netzwerken
Netzwerke werden als Dictionaries aus Knoten mit Arrays ihrer Nachbarn gespeichert.
A C D
E B
Schlussel Wert
(Knoten x) (Array der Nachbarn von x)
A [ C, B, E, D ]
B [ A, D ]
D [ B, C, A ]
C [ A, D, E ]
E [ A, C ]
Dictionary aus Knoten (Schlussel) und Arrays (Werte) aus Nachbarn des Schlussels
Netzwerke 4.6.7
Wir benutzen zwei etwas großere Beispiel-Netzwerke:
movies.txt enthalt Titel/Schauspieler zu 4188 Filmen,
flights.txt ist eine Datei mit Start-/Zielflughafen von 67000 Linienflugen.
$ python showneighbours.py movies.txt /
Manhattan (1979)
Streep, Meryl
Conroy, Frances
Murphy, Michael (I)
Allen, Woody
...
Allen, Woody
Husbands and Wives (1992)
Deconstructing Harry (1997)
Bananas (1971)
Stanley Kubrick: A Life in Pictures (2001)
New York Stories (1989)
...
$ python showneighbours.py flights.txt " "
ERF
PMI
FUE
LPA
AYT
LGW
TFS
LEJ
BCN
DME
ACE
AGA
IST
FUE
FNC
MUC
CGN
...
Netzwerke 4.6.8
2 Kurzeste Wege in Netzwerken
Ein Weg von Knoten a zu Knoten b ist eine Folge von Kanten, die mit a beginnt und mit b endet.
Die Lange eines Weges durch ein (ungewichtetes) Netzwerk ist die Anzahl seiner Kanten.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVA
XYG
WMI
CDG–MRS–GVA–XYG–FRA ist ein Weg von CDG nach FRA (Lange 4).
CDG–AMS–FRA ist ein anderer Weg von CDG nach FRA (Lange 2).
Das ist auch ein kurzester Weg zwischen CDG und FRA. Kurzeste Wege in Netzwerken 4.6.9
2 Kurzeste Wege in Netzwerken
Ein Weg von Knoten a zu Knoten b ist eine Folge von Kanten, die mit a beginnt und mit b endet.
Die Lange eines Weges durch ein (ungewichtetes) Netzwerk ist die Anzahl seiner Kanten.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVA
XYG
WMI
CDG–MRS–GVA–XYG–FRA ist ein Weg von CDG nach FRA (Lange 4).
CDG–AMS–FRA ist ein anderer Weg von CDG nach FRA (Lange 2).
Das ist auch ein kurzester Weg zwischen CDG und FRA. Kurzeste Wege in Netzwerken 4.6.9
2 Kurzeste Wege in Netzwerken
Ein Weg von Knoten a zu Knoten b ist eine Folge von Kanten, die mit a beginnt und mit b endet.
Die Lange eines Weges durch ein (ungewichtetes) Netzwerk ist die Anzahl seiner Kanten.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVA
XYG
WMI
CDG–MRS–GVA–XYG–FRA ist ein Weg von CDG nach FRA (Lange 4).
CDG–AMS–FRA ist ein anderer Weg von CDG nach FRA (Lange 2).
Das ist auch ein kurzester Weg zwischen CDG und FRA. Kurzeste Wege in Netzwerken 4.6.9
2 Kurzeste Wege in Netzwerken
Ein Weg von Knoten a zu Knoten b ist eine Folge von Kanten, die mit a beginnt und mit b endet.
Die Lange eines Weges durch ein (ungewichtetes) Netzwerk ist die Anzahl seiner Kanten.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVA
XYG
WMI
Es kann verschiedene kurzeste Wege zwischen zwei Knoten geben
(z.B. zwischen LCY und GVA).Kurzeste Wege in Netzwerken 4.6.9
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
Warteschlange
CDG
Entfernung bekannt
CDG
Vorganger
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
Warteschlange
CDG
Entfernung bekannt
CDG
Vorganger
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
Warteschlange
CDG
LCY
Entfernung bekannt
CDG
LCY
Vorganger
LCY CDG
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
Warteschlange
CDG
LCY
AMS
Entfernung bekannt
CDG
LCY
AMS
Vorganger
LCY CDG
AMS CDG
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
Warteschlange
CDG
LCY
AMS
MRS
Entfernung bekannt
CDG
LCY
AMS
MRS
Vorganger
LCY CDG
AMS CDG
MRS CDG
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
Warteschlange
LCY
AMS
MRS
Entfernung bekannt
CDG
LCY
AMS
MRS
Vorganger
LCY CDG
AMS CDG
MRS CDG
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCYWarteschlange
LCY
AMS
MRS
Entfernung bekannt
CDG
LCY
AMS
MRS
Vorganger
LCY CDG
AMS CDG
MRS CDG
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCYWarteschlange
AMS
MRS
Entfernung bekannt
CDG
LCY
AMS
MRS
Vorganger
LCY CDG
AMS CDG
MRS CDG
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
Warteschlange
AMS
MRS
Entfernung bekannt
CDG
LCY
AMS
MRS
Vorganger
LCY CDG
AMS CDG
MRS CDG
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
Warteschlange
AMS
MRS
FRA
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
Warteschlange
MRS
FRA
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
Warteschlange
MRS
FRA
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
Warteschlange
MRS
FRA
GVA
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
Warteschlange
FRA
GVA
FCO
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
Warteschlange
FRA
GVA
FCO
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
Warteschlange
FRA
GVA
FCO
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
Warteschlange
FRA
GVA
FCO
TXL
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die WarteschlangeKurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
Warteschlange
FRA
GVA
FCO
TXL
XYG
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
Warteschlange
GVA
FCO
TXL
XYG
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
Warteschlange
GVA
FCO
TXL
XYG
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
Warteschlange
FCO
TXL
XYG
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
FCO
Warteschlange
FCO
TXL
XYG
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
FCO
Warteschlange
TXL
XYG
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXLWarteschlange
TXL
XYG
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXLWarteschlange
TXL
XYG
WMI
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
WMI TXL
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXLWarteschlange
XYG
WMI
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
WMI TXL
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
Warteschlange
XYG
WMI
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
WMI TXL
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
Warteschlange
WMI
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
WMI TXL
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Warteschlange
WMI
Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
WMI TXL
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Warteschlange Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
WMI TXL
Auswahl des aktiven Knotens aus der Warteschlange: erster in der Warteschlange
Der aktive Knoten wird aus der Warteschlange entfernt.
Bearbeitung des aktiven Knotens a: schaue alle Nachbarn b von a an:
falls die Entfernung von b noch nicht bekannt ist:
trage fur b beim Vorganger a ein
trage fur b ein, dass seine Entfernung bekannt ist
setze b in die Warteschlange
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Warteschlange Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
WMI TXL
Dieser Algorithmus heißt Breitensuche.
Kurzeste Wege in Netzwerken 4.6.10
Suche nach kurzesten Wegen in Netzwerken
Wir wollen die kurzesten Wege von CDG zu allen erreichbaren Knoten finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Warteschlange Entfernung bekannt
CDG
LCY
AMS
MRS
FRA
GVA
FCO
TXL
XYG
WMI
Vorganger
LCY CDG
AMS CDG
MRS CDG
FRA AMS
GVA MRS
FCO MRS
TXL FRA
XYG FRA
WMI TXL
Dieser Algorithmus heißt Breitensuche.
Er liefert die Knoten–Vorganger-Kanten – sie bilden den Breitensuchebaum.
(Ein Baum ist ein verbundenes Netzwerk ohne Kreis.)Kurzeste Wege in Netzwerken 4.6.10
Die Idee fur den Breitensuche-Algorithmus
Eingabe: Netzwerk, Startknoten
Ausgabe: kurzeste Wege vom Startknoten aus durch das Netzwerk
Daten: Netzwerk
Warteschlange (Array)
EntfernungBekannt (Array)
Vorganger (Dictionary)
Ablauf: setze den Startknoten in die Warteschlange
und trage ihn bei EnfernungBekannt ein
solange die Warteschlange nicht leer ist wiederhole:
entferne den ersten Knoten aus der Warteschlange – das ist der aktive Knoten
fur jeden Nachbarn b des aktiven Knotens im Netzwerk wiederhole:
falls b noch nicht bei EntfernungBekannt eingetragen:
trage b bei Vorganger mit Wert”aktiver Knoten“ ein
trage b bei EntfernungBekannt ein
setze b in die Warteschlange
Vorganger kann nun zur Ausgabe der kurzesten Wege vom Startknoten aus benutzt werdenKurzeste Wege in Netzwerken 4.6.11
Strukturierung in Module
Modul netzwerk.py
Funktion Beschreibung
einlesen(dateiname, t=' ') liest Netzwerk aus Datei dateiname ein und gibt es als Dictionary
zuruck; t ist das Trennzeichen zwischen den Knoten in der Datei.
Die Schlussel im Dictionary sind die Knoten des Netzwerks, und die Werte
sind Arrays aus Knoten, die die Nachbarn des jeweiligen Schlussels sind.
Modul warteschlange.py
Funktion Beschreibung
neueWS() erzeugt eine neue leere Warteschlange und gibt sie zuruck
eintragen(ws,x) tragt x in die Warteschlange ws ein (am Ende)
entfernen(ws) entfernt das erste Element aus der Warteschlange ws und gibt es zuruck
istLeer(ws) gibt True zuruck, falls die Warteschlange ws leer ist, sonst FalseKurzeste Wege in Netzwerken 4.6.12
Modul breitensuche.py
Funktion Beschreibung
wegesuche(netzwerk, startknoten) durchsucht das Netzwerk netzwerk beginnend mit
startknoten mittels Breitensuche und gibt das dabei berechnete Dic-
tionary Vorganger zuruck.
Das Dictionary hat als Schlussel alle Knoten, die im Netzwerk von
startknoten aus erreichbar sind. Die Werte sind die Vorganger der
Schlussel auf einem kurzesten Weg von startknoten zum Schlussel.
Klient weg.py
liest den Dateinamen mit dem Netzwerk und den Start- und Zielknoten von der Kommandozeile
und gibt den kurzesten Weg zwischen den Knoten aus.
Kurzeste Wege in Netzwerken 4.6.13
netzwerk.py – Einlesen von Netzwerken
In Vorlesung 07 (Berechnung des PageRanks) hatten wir bereits Netzwerke eingelesen
Wir schreiben das nun nochmal als Funktion auf und machen ein Modul daraus.#-----------------------------------------------------------------------------------------
# netzwerk.py
#-----------------------------------------------------------------------------------------
def einlesen(dateiname, trennzeichen):
datei = open(dateiname, 'r')
netzwerk = dict()
for zeile in datei:
knoten = str.split(zeile, trennzeichen)
if len(knoten)==0: continue
anfangsknoten = str.strip(knoten[0])
if anfangsknoten not in netzwerk: netzwerk[anfangsknoten] = []
for z in range(1,len(knoten)):
zielknoten = str.strip(knoten[z])
if zielknoten not in netzwerk: netzwerk[zielknoten] = []
if zielknoten not in netzwerk[anfangsknoten]: netzwerk[anfangsknoten] += [ zielknoten ]
if anfangsknoten not in netzwerk[zielknoten]: netzwerk[zielknoten] += [anfangsknoten]
datei.close()
return netzwerkKurzeste Wege in Netzwerken 4.6.14
warteschlange.py – die Funktionen fur die Warteschlange
#------------------------------------------
# warteschlange.py
#------------------------------------------
def neueWS():
ws = dict()
ws['schlange'] = []
ws['anfang'] = 0
return ws
def istLeer(ws):
return ws['anfang']>=len(ws['schlange'])
def eintragen(ws, x):
ws['schlange'] += [x]
def entfernen(ws):
ws['anfang'] += 1
return ws['schlange'][ws['anfang']-1]
Die Warteschlange wird als Dictionary mit den Schlusseln
'schlange' und 'anfang' implementiert.
Der Wert zu 'schlange' ist ein Array,
und der Wert zu 'anfang' ist der Index im Array, bei
dem die Warteschlange beginnt.
Falls dieser Anfangs-Index großer oder gleich der Lange
des Arrays ist, idt die Warteschlange leer.
In einer neuen (leeren) Warteschlange ist das Array leer
und der Anfangs-Index ist 0.
Ein Element x wird in die Warteschlange eingetragen,
indem es an das Array angehangt wird.
Das erste Element wird aus der Warteschlange entfernt,
indem der Anfangs-Index um 1 erhoht wird.(Die Implementierung ist nicht optimal, da die Elemente nicht aus
dem Array entfernt werden und deshalb Speicherplatz verschwendet
wird. Dafur sparen wir hier Rechenzeit.)Kurzeste Wege in Netzwerken 4.6.15
breitensuche.py – die Implementierung der Breitensuche
# breitensuche.py
#-------------------------------------------------------
from warteschlange import *
def wegesuche(netzwerk, startknoten):
entfernungBekannt = []
vorgaenger = dict()
warteschlange = neueWS()
eintragen(warteschlange, startknoten)
entfernungBekannt += [startknoten]
while not istLeer(warteschlange):
aktiverKnoten = entfernen(warteschlange)
for k in netzwerk[aktiverKnoten]:
if k not in entfernungBekannt:
vorgaenger[k] = aktiverKnoten
entfernungBekannt += [k]
eintragen(warteschlange, k)
return vorgaenger
Die Implementierung der Funktion
breitensuche() entspricht genau der Idee
(siehe Seite . . . ).
Ruckgabewert ist das Dictionary mit dem
Netzwerk aus Knoten und ihren Vorgangern auf
dem kurzesten Weg vom Startknoten.
Kurzeste Wege in Netzwerken 4.6.16
weg.py – der Klient fur die Wegsuche
#-------------------------------------------------
# weg.py
#-------------------------------------------------
def rueckweg(vorgaenger, ziel):
rweg = [ ziel ]
while ziel in vorgaenger:
rweg += [ vorgaenger[ziel] ]
ziel = vorgaenger[ziel]
return rweg
def rekonstruiereWeg(vorgaenger, ziel):
weg = rueckweg(vorgaenger, ziel)
weg.reverse()
return weg
def laengsterKuerzesterWeg(vorgaenger, start):
maxWeglaenge = 0
fernstesZiel = start
for ziel in vorgaenger:
rweg = rueckweg(vorgaenger,ziel)
if len(rweg)-1>maxWeglaenge:
maxWeglaenge = len(rweg)-1
fernstesZiel = ziel
return fernstesZiel
rueckweg(vorgaenger, ziel) beginnt im
Dictionary vorgaenger mit dem Schlussel/Knoten
ziel und geht zu dessen Vorganger, Vorvorganger
etc., bis der Knoten mit dem Vorganger None (d.h.
ohne Vorganger) erreicht wird, bei dem die
Breitensuche begann. Der dabei durchlaufene Weg
wird im Array weg gespeichert, das am Ende der
Funktion zuruckgegeben wird.
rekonstruiereWeg(vorgaenger, ziel) dreht den
von rueckweg(vorgaenger, ziel) berechneten
Weg um. Damit hat man einen kurzesten Weg vom
Starknoten der Breitensuche zu ziel.
laengsterKuerzesterWeg(vorgaenger, start)
sucht den langsten kurzesten Weg, der bei der in
start begonnenen Breitensuche gefunden wurde, und
gibt seinen Endknoten zuruck.
Kurzeste Wege in Netzwerken 4.6.17
weg.py – der Klient fur die Wegsuchedef test():
from breitensuche import wegesuche
import sys
from netzwerk import einlesen
dateiname, trennzeichen = sys.argv[1:3]
netzwerk = einlesen(dateiname, trennzeichen)
startknoten, zielknoten = sys.argv[3:5]
vorgaenger = wegesuche(netzwerk, startknoten)
if not zielknoten in vorgaenger:
print('Es gibt keinen Weg von %s zu %s.' % (startknoten, zielknoten))
else:
print('Ein kurzester Weg von %s nach %s ist ' % (startknoten, zielknoten), end='')
print( str(rekonstruiereWeg(vorgaenger, sys.argv[4])) + '.' )
print('Ein langster kurzester Weg von %s ist ' % (startknoten), end='')
print(str(rekonstruiereWeg(vorgaenger, laengsterKuerzesterWeg(vorgaenger, startknoten))) + '.')
#-------------------------------------------------------------------------------------------
Der Test-Klient liest den Dateinamen mit der Netzwerk-Datei, das darin verwendete Trennzeichen, einen
Start- und einen Zielknoten von der Kommandozeile,
fuhrt die Breitensuche in dem Netzwerk vom Startknoten aus, und gibt einen kurzesten Weg zwischen
Start- und Zielknoten sowie den langsten kurzesten Weg vom Startknoten aus.
Kurzeste Wege in Netzwerken 4.6.18
$ python3 weg.py flights.txt ' ' ERF JFK
Ein kurzester Weg von ERF nach JFK ist ['ERF', 'AYT', 'ZRH', 'JFK'].
Ein langster kurzester Weg von ERF ist ['ERF', 'AYT', 'FRA', 'SEA', 'LKE', 'FBS', 'RCE', 'DHB',
'WSX', 'LPS'].
$ python3 weg.py movies.txt / 'Allen, Woody' 'Loren, Sophia'
Ein kurzester Weg von Allen, Woody nach Loren, Sophia ist ['Allen, Woody', 'Annie Hall (1977)',
'Aiello, Danny', 'Pret-a-Porter (1994)', 'Loren, Sophia'].
Ein langster kurzester Weg von Allen, Woody ist ['Allen, Woody', 'Hannah and Her Sisters (1986)',
'von Sydow, Max (I)', 'Pelle erobreren (1987)', 'Granath, Bjorn', 'Ondskan (2003)',
'Hjulstrom, Lennart', 'Mitt liv som hund (1985)', 'Carlsson, Ralph', 'Fucking Amal (1998)',
'Strom, Patrik'].
Kurzeste Wege in Netzwerken 4.6.19
$ python3 weg.py flights.txt ' ' ERF JFK
Ein kurzester Weg von ERF nach JFK ist ['ERF', 'AYT', 'ZRH', 'JFK'].
Ein langster kurzester Weg von ERF ist ['ERF', 'AYT', 'FRA', 'SEA', 'LKE', 'FBS', 'RCE', 'DHB',
'WSX', 'LPS'].
$ python3 weg.py movies.txt / 'Allen, Woody' 'Loren, Sophia'
Ein kurzester Weg von Allen, Woody nach Loren, Sophia ist ['Allen, Woody', 'Annie Hall (1977)',
'Aiello, Danny', 'Pret-a-Porter (1994)', 'Loren, Sophia'].
Ein langster kurzester Weg von Allen, Woody ist ['Allen, Woody', 'Hannah and Her Sisters (1986)',
'von Sydow, Max (I)', 'Pelle erobreren (1987)', 'Granath, Bjorn', 'Ondskan (2003)',
'Hjulstrom, Lennart', 'Mitt liv som hund (1985)', 'Carlsson, Ralph', 'Fucking Amal (1998)',
'Strom, Patrik'].
Warum lauft das Programm so langsam?
Kurzeste Wege in Netzwerken 4.6.19
$ python3 weg.py flights.txt ' ' ERF JFK
Ein kurzester Weg von ERF nach JFK ist ['ERF', 'AYT', 'ZRH', 'JFK'].
Ein langster kurzester Weg von ERF ist ['ERF', 'AYT', 'FRA', 'SEA', 'LKE', 'FBS', 'RCE', 'DHB',
'WSX', 'LPS'].
$ python3 weg.py movies.txt / 'Allen, Woody' 'Loren, Sophia'
Ein kurzester Weg von Allen, Woody nach Loren, Sophia ist ['Allen, Woody', 'Annie Hall (1977)',
'Aiello, Danny', 'Pret-a-Porter (1994)', 'Loren, Sophia'].
Ein langster kurzester Weg von Allen, Woody ist ['Allen, Woody', 'Hannah and Her Sisters (1986)',
'von Sydow, Max (I)', 'Pelle erobreren (1987)', 'Granath, Bjorn', 'Ondskan (2003)',
'Hjulstrom, Lennart', 'Mitt liv som hund (1985)', 'Carlsson, Ralph', 'Fucking Amal (1998)',
'Strom, Patrik'].
Warum lauft das Programm so langsam?(1) Die Wahl eines Arrays fur entfernungBekannt ist schlecht. Bei der Frage, ob ein Knoten in dem Array ist, wirddas ganze Array
”von links nach rechts“ durchsucht. Besser ist die Wahl eines Dictionaries mit Schlusseln ohne Wert
(d.h. mit Wert None). Bei Dictionaries geht die Suche nach einem Schlussel viel schneller.Kurzeste Wege in Netzwerken 4.6.19
$ python3 weg.py flights.txt ' ' ERF JFK
Ein kurzester Weg von ERF nach JFK ist ['ERF', 'AYT', 'ZRH', 'JFK'].
Ein langster kurzester Weg von ERF ist ['ERF', 'AYT', 'FRA', 'SEA', 'LKE', 'FBS', 'RCE', 'DHB',
'WSX', 'LPS'].
$ python3 weg.py movies.txt / 'Allen, Woody' 'Loren, Sophia'
Ein kurzester Weg von Allen, Woody nach Loren, Sophia ist ['Allen, Woody', 'Annie Hall (1977)',
'Aiello, Danny', 'Pret-a-Porter (1994)', 'Loren, Sophia'].
Ein langster kurzester Weg von Allen, Woody ist ['Allen, Woody', 'Hannah and Her Sisters (1986)',
'von Sydow, Max (I)', 'Pelle erobreren (1987)', 'Granath, Bjorn', 'Ondskan (2003)',
'Hjulstrom, Lennart', 'Mitt liv som hund (1985)', 'Carlsson, Ralph', 'Fucking Amal (1998)',
'Strom, Patrik'].
Warum lauft das Programm so langsam?
(2) Bei laengsterKuerzesterWeg() wird immer wieder die gleiche Information berechnet. Wenn man z.B. bereits
weiß, dass der Weg von ’X’ zum Startknoten Lange 50 hat und ’Y’ hat ’X’ als Vorganger auf dem kurzesten Weg,
dann weiß man sofort die Lange 51 des Weges von ’X’ zum Startknoten. Dieses Wissen nutzt das Programm nicht
aus.Kurzeste Wege in Netzwerken 4.6.19
3 Kurzeste Wege in gewichteten Netzwerken
Ein Weg von Knoten a zu Knoten b ist eine Folge von Kanten, die mit a beginnt und mit b endet.
Die Lange eines Weges durch ein gewichtetes Netzwerk ist die Summe der Gewichte seiner Kanten.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVA
XYG
WMI2
36
2
3 2
6
13
2
2
2
41
CDG–MRS–GVA–XYG–FRA ist ein Weg von CDG nach FRA mit Lange 7.
CDG–LCY–AMS–FRA ist ein anderer Weg von CDG nach FRA mit Lange 8.
CDG–MRS–FCO–XYG–FRA ist der kurzeste Weg zwischen CDG und FRA (Lange 6).Kurzeste Wege in gewichteten Netzwerken 4.6.20
3 Kurzeste Wege in gewichteten Netzwerken
Ein Weg von Knoten a zu Knoten b ist eine Folge von Kanten, die mit a beginnt und mit b endet.
Die Lange eines Weges durch ein gewichtetes Netzwerk ist die Summe der Gewichte seiner Kanten.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVA
XYG
WMI2
36
2
3 2
6
13
2
2
2
41
CDG–MRS–GVA–XYG–FRA ist ein Weg von CDG nach FRA mit Lange 7.
CDG–LCY–AMS–FRA ist ein anderer Weg von CDG nach FRA mit Lange 8.
CDG–MRS–FCO–XYG–FRA ist der kurzeste Weg zwischen CDG und FRA (Lange 6).Kurzeste Wege in gewichteten Netzwerken 4.6.20
3 Kurzeste Wege in gewichteten Netzwerken
Ein Weg von Knoten a zu Knoten b ist eine Folge von Kanten, die mit a beginnt und mit b endet.
Die Lange eines Weges durch ein gewichtetes Netzwerk ist die Summe der Gewichte seiner Kanten.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVA
XYG
WMI2
36
2
3 2
6
13
2
2
2
41
CDG–MRS–GVA–XYG–FRA ist ein Weg von CDG nach FRA mit Lange 7.
CDG–LCY–AMS–FRA ist ein anderer Weg von CDG nach FRA mit Lange 8.
CDG–MRS–FCO–XYG–FRA ist der kurzeste Weg zwischen CDG und FRA (Lange 6).Kurzeste Wege in gewichteten Netzwerken 4.6.20
3 Kurzeste Wege in gewichteten Netzwerken
Ein Weg von Knoten a zu Knoten b ist eine Folge von Kanten, die mit a beginnt und mit b endet.
Die Lange eines Weges durch ein gewichtetes Netzwerk ist die Summe der Gewichte seiner Kanten.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVA
XYG
WMI2
36
2
3 2
6
13
2
2
2
41
CDG–MRS–GVA–XYG–FRA ist ein Weg von CDG nach FRA mit Lange 7.
CDG–LCY–AMS–FRA ist ein anderer Weg von CDG nach FRA mit Lange 8.
CDG–MRS–FCO–XYG–FRA ist der kurzeste Weg zwischen CDG und FRA (Lange 6).Kurzeste Wege in gewichteten Netzwerken 4.6.20
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1
Prioritats-
Warteschlange
CDG 0
Entfernung
bekannt Vorganger
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
Prioritats-
Warteschlange
CDG 0
Entfernung
bekannt
CDG
Vorganger
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
Prioritats-
Warteschlange
CDG 0
LCY 2
Entfernung
bekannt
CDG
Vorganger
LCY CDG
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
Prioritats-
Warteschlange
CDG 0
LCY 2
AMS 6
Entfernung
bekannt
CDG
Vorganger
LCY CDG
AMS CDG
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
Prioritats-
Warteschlange
CDG 0
LCY 2
AMS 6
MRS 1
Entfernung
bekannt
CDG
Vorganger
LCY CDG
AMS CDG
MRS CDG
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
Prioritats-
Warteschlange
LCY 2
AMS 6
MRS 1
Entfernung
bekannt
CDG
Vorganger
LCY CDG
AMS CDG
MRS CDG
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
Prioritats-
Warteschlange
LCY 2
AMS 6
MRS 1
Entfernung
bekannt
CDG
MRS
Vorganger
LCY CDG
AMS CDG
MRS CDG
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
Prioritats-
Warteschlange
LCY 2
AMS 6
MRS 1
GVA 4
Entfernung
bekannt
CDG
MRS
Vorganger
LCY CDG
AMS CDG
MRS CDG
GVA MRS
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
Prioritats-
Warteschlange
LCY 2
AMS 6
MRS 1
GVA 4
FCO 3
Entfernung
bekannt
CDG
MRS
Vorganger
LCY CDG
AMS CDG
MRS CDG
GVA MRS
FCO MRS
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
Prioritats-
Warteschlange
LCY 2
AMS 6
GVA 4
FCO 3
Entfernung
bekannt
CDG
MRS
Vorganger
LCY CDG
AMS CDG
MRS CDG
GVA MRS
FCO MRS
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
Prioritats-
Warteschlange
LCY 2
AMS 6
GVA 4
FCO 3
Entfernung
bekannt
CDG
MRS
LCY
Vorganger
LCY CDG
AMS CDG
MRS CDG
GVA MRS
FCO MRS
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
Prioritats-
Warteschlange
LCY 2
AMS 5
GVA 4
FCO 3
Entfernung
bekannt
CDG
MRS
LCY
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
Prioritats-
Warteschlange
AMS 5
GVA 4
FCO 3
Entfernung
bekannt
CDG
MRS
LCY
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
Prioritats-
Warteschlange
AMS 5
GVA 4
FCO 3
Entfernung
bekannt
CDG
MRS
LCY
FCO
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
Prioritats-
Warteschlange
AMS 5
GVA 4
FCO 3
XYG 5
Entfernung
bekannt
CDG
MRS
LCY
FCO
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
Prioritats-
Warteschlange
AMS 5
GVA 4
XYG 5
Entfernung
bekannt
CDG
MRS
LCY
FCO
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
Prioritats-
Warteschlange
AMS 5
GVA 4
XYG 5
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
Prioritats-
Warteschlange
AMS 5
GVA 4
XYG 5
FRA 8
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA GVA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
Prioritats-
Warteschlange
AMS 5
XYG 5
FRA 8
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA GVA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
Prioritats-
Warteschlange
AMS 5
XYG 5
FRA 8
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA GVA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
Prioritats-
Warteschlange
XYG 5
FRA 8
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA GVA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
Prioritats-
Warteschlange
XYG 5
FRA 8
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA GVA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
Prioritats-
Warteschlange
XYG 5
FRA 6
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
Prioritats-
Warteschlange
XYG 5
FRA 6
WMI 11
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI XYG
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
Prioritats-
Warteschlange
FRA 6
WMI 11
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI XYG
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
Prioritats-
Warteschlange
FRA 6
WMI 11
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI XYG
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
Prioritats-
Warteschlange
FRA 6
WMI 11
TXL 8
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI XYG
TXL FRA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
Prioritats-
Warteschlange
WMI 11
TXL 8
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI XYG
TXL FRA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
Prioritats-
Warteschlange
WMI 11
TXL 8
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI XYG
TXL FRA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
Prioritats-
Warteschlange
WMI 10
TXL 8
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI TXL
TXL FRA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
Prioritats-
Warteschlange
WMI 10
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI TXL
TXL FRA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
WMI
Prioritats-
Warteschlange
WMI 10
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
WMI
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI TXL
TXL FRA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
WMI
Prioritats-
Warteschlange
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
WMI
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI TXL
TXL FRA
Auswahl des aktiven Knotens aus der Prioritats-Warteschlange: Knoten mit kleinster Entfernung
Bearbeitung des aktiven Knotens a:
trage fur a ein, dass seine Entfernung bekannt ist
schaue alle Nachbarn b von a an, deren Entfernung nicht bekannt ist:
falls b bereits in der Prioritats-Warteschlange ist:
aktualisiere Entfernung (in der Prior.-WS) und seinen Vorganger, falls a”besserer“ Vorganger ist
sonst: trage b und seine Entfernung in die Prioritats-Warteschlange und in die Vorganger-Liste ein
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
WMI
Prioritats-
Warteschlange
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
WMI
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI TXL
TXL FRA
Dieser Algorithmus heißt Algorithmus von Dijkstra.
Er liefert die Knoten–Vorganger-Kanten – sie bilden den Kurzesten-Wege-Baum.
(Ein Baum ist ein verbundenes Netzwerk ohne Kreis.)
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Suche nach kurzesten Wegen in gewichteten Netzwerken
Wir wollen alle kurzesten Wege von CDG aus finden.
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
WMI
Prioritats-
Warteschlange
Entfernung
bekannt
CDG
MRS
LCY
FCO
GVA
AMS
XYG
FRA
TXL
WMI
Vorganger
LCY CDG
AMS LCY
MRS CDG
GVA MRS
FCO MRS
XYG FCO
FRA XYG
WMI TXL
TXL FRA
Dieser Algorithmus heißt Algorithmus von Dijkstra.
Er liefert die Knoten–Vorganger-Kanten – sie bilden den Kurzesten-Wege-Baum.
(Ein Baum ist ein verbundenes Netzwerk ohne Kreis.)
Kurzeste Wege in gewichteten Netzwerken 4.6.21
Die Idee fur den Algorithmus von Dijkstra
Eingabe: gewichtetes Netzwerk, Startknoten
Ausgabe: kurzeste Wege vom Startknoten aus durch das gewichtete Netzwerk
Daten: gewichtetes Netzwerk
Prioritats-Warteschlange (Dictionary) (fur Knoten mit Entfernungsmarkierungen)
EntfernungBekannt (Array)
Vorganger (Dictionary)
Ablauf: setze den Startknoten mit Entfernungsmarkierung 0 in die Prioritats-Warteschlange
und trage den Startknoten bei EnfernungBekannt ein
solange die Prioritats-Warteschlange nicht leer ist wiederhole:
entferne den Knoten a mit der kleinsten Entfernungsmarkierung aus der Warteschlange
trage a in EntfernungBekannt ein
fur jeden Nachbarn b von a, der nicht bei EntfernungBekannt eingetragen ist:
e “ Entfernungsmarkierung von a` Gewicht der Kante von a zu b
falls b nicht in der Priorit.-Warteschlange ist: trage b dort mit Entfernungsmark. e ein
sonst: falls e ă Entfernungsmarkierung von b:
andere die Entfernungsmarkierung von b zu e
andere den Vorganger von b zu a
Vorganger kann nun zur Ausgabe der kurzesten Wege vom Startknoten aus benutzt werden
Kurzeste Wege in gewichteten Netzwerken 4.6.22
Darstellung von gewichteten Netzwerken als Textdateien
FRA
TXL
AMS
CDG
FCO
LCY
MRS
GVAXYG
WMI2
36
2
3 2
6
13
2
2
2
4 1
Pro Zeile: ein Knoten und weitere
Knoten/Gewicht-Paare, zu denen er eine Kante
mit dem Gewicht hat.
Dazwischen jeweils ein Trennzeichen.
Kanten konnen mehrfach vorkommen.
gew_beispielnetzwerk:
FRA/TXL/2
FRA/AMS/3
AMS/CDG/6/LCY/3
CDG/LCY/2
TXL/WMI/2
WMI/XYG/6
CDG/MRS/1
MRS/GVA/3
MRS/FCO/2
GVA/XYG/2
FCO/XYG/2
FRA/GVA/4
FRA/XYG/1Kurzeste Wege in gewichteten Netzwerken 4.6.23
Die Speicherung gewichteter Netzwerken
Netzwerke werden als Dictionaries mit Knoten als Schlusseln.
Der Wert zu einem Knoten a ist ein Dictionary
mit Knoten als Schlussel,
so dass der Wert zum Schlussel b das Gewicht der Kante zwischen a und b ist.
A C D
E B
1 2
3 4 5
6Schlussel Wert
(Knoten x) (Dictionary der Nachbarn von x mit Kantengewichten)
A { C:1, E:3, D:6 }
B { D:5 }
D { C:2, A:6, B:5 }
C { A:1, E:4, D:2 }
E { C:4, A:3 }
Kurzeste Wege in gewichteten Netzwerken 4.6.24
Strukturierung in Module
Modul netzwerk.py wird um folgende Funktion erweitert:
Funktion Beschreibung
gew_einlesen(dateiname, t=' ') liest gewichtetes Netzwerk aus Datei dateiname ein und gibt es als
Dictionary zuruck; t ist das Trennzeichen zwischen den Knoten in der Datei.
Die Schlussel im Dictionary sind die Knoten des Netzwerks, und die Werte sind
Dictionaries aus Knoten (Schlussel) und Gewichten (Wert), die die Nachbarn und
das Gewicht der Kanten zwischen den beiden Schlusseln sind.
Modul pwarteschlange.py
Funktion Beschreibung
neueWS() erzeugt eine neue leere Prioritats-Warteschlange und gibt sie zuruck
eintragen(ws,x,k) tragt x mit Wert k in die Prioritats-Warteschlange ws ein
entfernen(ws) entfernt das Element mit dem kleinsten Wert aus der Prioritats-
Warteschlange ws und gibt es zuruck
istLeer(ws) gibt True zuruck, falls die Prioritats-Warteschlange ws leer ist, sonst FalseKurzeste Wege in gewichteten Netzwerken 4.6.25
Modul dijkstra.py
Funktion Beschreibung
wegesuche(netzwerk, startknoten) durchsucht das gewichtete Netzwerk netzwerk beginnend
mit startknoten mittels Breitensuche und gibt das dabei berechnete
Dictionary Vorganger zuruck.
Das Dictionary hat als Schlussel alle Knoten, die im Netzwerk von
startknoten aus erreichbar sind. Die Werte sind die Vorganger der
Schlussel auf einem kurzesten Weg von startknoten zum Schlussel.
Klient gew_weg.py
liest den Dateinamen (und Trennzeichen) mit dem Netzwerk und den Start- und Zielknoten von der
Kommandozeile
und gibt den kurzesten Weg zwischen den Knoten aus.
$ python3 gew_weg.py gew_beispielnetzwerk.txt '/' CDG TXL
Ein kurzester Weg von CDG nach TXL ist ['CDG', 'MRS', 'FCO', 'XYG', 'FRA', 'TXL'].
Der Weg hat Lange 8.Kurzeste Wege in gewichteten Netzwerken 4.6.26
Zusammenfassung
Wir haben Algorithmen zum Finden von kurzesten Wegen in gewichteten und ungewichteten
Graphen implementiert.
Bei der Implementierung haben wir die verschiedenen zu losenden Teilaufgaben auf Module verteilt
und als Funktionen implementiert.
Die Module warteschlange.py und pwarteschlange.py implementieren Datenstrukturen.
Sie dienen der strukturierten Speicherung von Daten und dem Zugriff auf die Speicher-Struktur
uber Funktionen. Dadurch muss der Benutzer nichts uber die konkrete Speicher-Struktur wissem.
(Die Implementierung dieser Speicher-Strukturen ist nicht optimal: sie geht nicht sparsam mit dem Speicher um, und
sie achtet nicht darauf, dass der Zugriff auf die Daten moglichst schnell geht.)
4.6.27
top related