GDI 2008-01

Werbung
Grundlagen der
Informatik
Wintersemester 2007
Prof. Dr. Peter Kneisel
1
Didaktik: Durchführung
 Diese Vorlesung enthält Übungen
 Die Übungen werden je nach Bedarf durchgeführt.
 Zur Vorbereitung werden Übungsblätter, je nach Vorlesungsverlauf
zusammengestellt.
 Weitere Übungen sind im Foliensatz vorhanden und sollten selbständig und
vollständig bearbeitet werden.
 Vorsicht !
 Kommen Sie in alle Veranstaltungen - machen Sie die Übungen
 Überschätzen Sie sich nicht - auch wenn Sie PC-Crack sind
2
Didaktik: Folien
 Der Vorlesungsstoff wird anhand von Folien dargelegt
 Die Folien bilden nur einen Rahmen für die Inhalte. Die Folien sollten daher mit Hilfe
eigener Vorlesungsskizzen ergänzt werden - am besten in Form einer
Vorlesungsnachbereitung max. 3 Tage nach der Vorlesung
 Zusätzlich zu den Folien werden Beispiele an der Tafel oder am Rechner gezeigt.
Diese sollten Sie vollständig mitskizzieren.
 Zur vollständigen Nachbereitung, z.B. als Klausurvorbereitung, sind die Folien
einheitlich strukturiert
 Es gibt genau drei Gliederungsebenen: Kapitel, Unterkapitel, Abschnitte
 Die Inhalte jedes Kapitels und jedes Unterkapitels werden jeweils motiviert und sind
verbal beschrieben. Zusätzlich gibt es jeweils ein stichwortartiges Inhaltsverzeichnis
der Unterkapitel, bzw. Abschnitte
 Die Vorlesung wird ständig überarbeitet, so dass sich die Foliensätze ändern
können (und werden)
 Laden Sie sich zur endgültigen vollständigen Klausurvorbereitung nochmals
zusätzlich den kompletten Foliensatz herunter.
3
Literatur
 Diese Veranstaltung ist anhand (wirklich) vieler Bücher und einer Menge
eigener Erfahrungen erstellt worden. Jedes Buch hat dabei Schwerpunkte in
speziellen Bereichen und ist daher sinnvoll. Eine Auflistung aller dieser Bücher
ist nicht sinnvoll.
Stellvertretend für all diese Bücher sei hier ein Buch angeführt:
 H.P.Gumm, M.Sommer: „Einführung in die Informatik“; Oldenbourg-Verlag 2004
 Motivation ist alles !
Hier ein paar Bücher, die das Interesse und den Spaß an der Wissenschaft im
Allgemeinen und an der Informatik im besonderen wecken soll:





S.Singh: „Fermats letzter Satz“; DTV, 9.Auflage 2004
M. Spitzer: „Geist im Netz“; Spektrum, Akad. Verlag 2000
H. Lyre: „Informationstheorie“; UTB, 2002
A.Hodges: „Alan Turing, Enigma“; Springer-Verlag, 1983
D.R.Hofstadter: „Gödel, Escher, Bach“; Klett-Cotta, 2006 (Taschenbuch 1991)
4
Inhalt
 Wie jede Wissenschaft befasst sich die Informatik mit ihren eigenen „Objekten“.
Was diese „Objekte“ sind und was man mit diesen Objekten machen kann - und
wie - wird in dieser Vorlesung auf eher abstraktem Niveau, aber immer mit
Beispielen aus der Realität eines Informatikers (oder einer Informatikerin),
erläutert.
 Diese Vorlesung konzentriert sich auf den „Kern“ der Informatik. Vertieftere
Einführungen in z.B die Bereiche der Programmierung, Rechnerarchitekturen,
Betriebssysteme, etc. sollen daher bewusst den entsprechenden Veranstaltungen
vorbehalten bleiben
 Inhalt
1.
2.
3.
4.
5.
Informatik
Information und Codes
Zeichen und Zahlen
Datenstrukturen
Algorithmenentwurf
5
Überblick und Einordnung
AD
AFS
RN
Strukturierung
Elemente
Praktische
1
6
Statik (Struktur)
EP
Dynamik (Algorithmik)
OOP SWT
Datenstrukturen
5
Zahlen
4
Zeichen
RA
3
Information 2
Codes
Theoretische
Technische
Informatik
6
Kapitel 1 Informatik
 1962 wurde der Begriff „Informatique“(als Kombination der Begriffe
„Information“ und „automatique“) von Philippe Dreyfus, einem französischen
Ingenieur eingeführt und als „Informatik“ ins Deutsche übernommen. Als junge
Wissenschaft ist die Informatik mittlerweile in viele Bereiche der älteren
Wissenschaften eingezogen und hat viele eigene Bereiche neu erschlossen.
Die Informatik ist damit mittlerweile wesentlich mehr, als der angloamerikanische Begriff „Computer-Science“ vermuten lässt.
Dieses Kapitel möchte einen (kurzen) Überblick über exemplarische Inhalte,
Struktur und Geschichte der Informatik geben
 Inhalt
1.
2.
3.
4.
5.
Motivation
Definition
Die Teilgebiete der Informatik
Die Geschichte der Informatik
Zusammenfassung des Kapitels
7
1.1
Motivation
 Die Beherrschung eines Computers macht Spaß
und gibt der informationssüchtigen Gesellschaft das Gefühl persönlicher Freiheit
(so wie vor Jahren ein roter Sportwagen)
 Die Beherrschung gibt Macht.
Für das Funktionieren einer demokratischen Gesellschaft ist es wichtig, daß
viele Menschen Computer verstehen und beherrschen.
 Der Computer schafft und vernichtet Arbeitsplätze und ist eine Herausforderung
für die Gesellschaft
 Das Verstehen der Gesetzmäßigkeiten bei der Entwicklung von
Computerprogrammen ist eine intellektuelle Herausforderung
 Das Umsetzen dieses Verständnisses ist eine intellektuelle Genugtuung.
 Der Computer schafft neue Betätigungsfelder und Lebensinhalte
 Zunehmend viele Aufgabenstellungen der realen Welt sind ohne Einsatz von
Methoden und Werkzeugen der Informatik nicht mehr zu bewältigen
 Der professionelle Umgang mit Computer ist im Beruftsleben eine nackte
Notwendigkeit !
8
1.2
Was ist Informatik
 Jedes Lehrbuch der Informatik gibt seine Definition der „Informatik“. Auch der
Duden beschreibt die Informatik als „Wissenschaft von der systematischen
Verarbeitung von Informationen, besonders der automatischen Verarbeitung
mit Hilfe von Digitalrechnern“.
Durch die Beschränkung auf den Aspekt der „Verarbeitung“ geht diese
Definition meines Erachtens nicht weit genug. Ich werde daher in diesem
Unterkapitel eine eigene Definition wagen. Die dabei verwendeten Aspekte
werden exemplarisch verdeutlicht, wobei bewusst in Grenzbereiche der
Informatik gegangen wird .
 Was die Informatik wirklich ist, kann kein Lehrbuch erfassen.
Sie werden - hoffentlich - am Ende Ihres Studiums eine sehr
weitreichende Idee davon haben.
 Inhalt
1. Definition
2. Beispiele
9
1.2.1 Definition
Informatik
Die Wissenschaft, die sich mit dem
(automatisierten)
Erfassen
Transportieren
Speichern
Verarbeiten
Umsetzen
von Information befasst
10
1.2.2 Wissenschaft
 Informatik ist nicht die Wissenschaft vom Computer
(sowenig, wie Astronomie die Wissenschaft vom Teleskop ist)
 Informatik ist eine Wissenschaft
… und keine Bastelecke für Software-Spieler
 Aspekte der Informatik als
 „reine Lehre“ (verwandt mit der Mathematik)
 Naturwissenschaft: entdecken und beschreiben von „natürlichen“ Phänomenen
 Ingenieurwissenschaft - mit der typischen Vorgehensweise
 Problemstellung
 Analyse
 Teillösungen
 Synthese
 Lösung
11
1.2.3 Information
 Information ist die Bedeutung, die durch eine Nachricht übermittelt wird
(nachrichtentechnische Definition)
  Kapitel 2
 Information ist eine elementare Kategorie
 Chemie: Stoffumwandlung
 Physik: Energieumwandlung
 Informatik: Informationsumwandlung
12
1.2.4 Erfassen
Sensorik
 Bildverarbeitung
Datenmenge
(Byte)
300000
60000
3000
(52,204,248)
(33,75,125,190,251)
100
13
1.2.5 Transportieren
Telekommunikation
 Telephonie
~5-25000 Hz
300 - 3400 Hz
14
1.2.6 Speichern
Datenrepräsentation
 Abstrakte Datentypen (N. Wirth: Algorithmen und Datenstrukturen)
Einfache Typen
Strukturierte Typen
Abstrakte Typen
Aufzählungstypen
Integer
Real
Boolean
Char
...
Array
Record
Varianten Record
Menge
...
Listen
Binäre Bäume
Vielweg Bäume
Graphen
...
{rot, gelb, grün}
array [n..m] of Type
[0,1,..,65535]
record
Type 1: element 1
Type n: element n
end
[3,4e-038,..3,4e038]
{TRUE, FALSE}
set of Type
{ASC(0),..,ASC(255)}
15
1.2.6 Speichern
Datenrepräsentation
 Objektrepräsentation
(G. Booch: Objektorientierte Analyse und Design)
Assoziation
Klassenname
Vererbung
Attribute
Operationen
Einschränkungen
Aggregation
Verwendung
Instantiierung
Mitarbeiter
Projekt
Buchhaltung
n
Controlling
1
Projektleiter
Teil
projekt
Personalwesen
16
1.2.6 Speichern
Datenrepräsentation
 Objektrepräsentation
(B.Stroustrup: The C++ Programming Language)
Projekt
Mitarbeiter
n
Projektleiter
Buchhaltung
Controlling
Teilprojekt
1
Personalwesen
Assoziation
Vererbung
Aggregation
Verwendung
Instantiierung
Class Teilprojekt: public Projekt {
Projektleiter projektleiter;
Mitarbeiter
mitarbeiter[MAX_MITARBEITER];
public:
Teilprojekt (Projektleiter);
~Teilprojekt ();
}
1
n
Teilprojekt::Teilprojekt(Projektleiter pl) {
// some method-calls of Buchhaltung, Controlling, Personalwesen
}
main {
Teilprojekt1 = new Teilprojekt(Projektleiter1)
// See Budget1 for buget details on Teilprojekt1
}
17
1.2.7 Verarbeiten
 Petri-Netze
Prozessmodelle
(C.A.Petri: Kommunikation und Automaten))
18
1.2.7 Verarbeiten
Prozessmodelle
 Interaktionsdiagramme
(G. Booch: Objektorientierte Analyse und Design)
R1
R2
R3
R4
N2
R5
N1
19
1.2.7 Verarbeiten
KI-Ansätze
a
W
O
F
f
 Neuronale Netze
Aktivierungszustand
Verbindungsgewichtung
Ausgangswert
Aktivierungsfunktion
Ausgabefunktion
Oj
Axon
Wij
Synapsen
ai=F(Wij*Oj ,ai)
Oi=f(ai)
Dendrite
20
1.2.8 Umsetzen
Aktorik
 Manipulatoren
Anzahl Freiheitsgrade
25
9
2 (1)
21
1.2.9 Zusammenfassung
Erfassen Transportieren Speichern Verarbeiten Umsetzen
 Modellierung der realen Welt
 Abbildung realer Objekte und deren Beziehungen (Strukturen) auf rechnerinterne
Objekte und Strukturen
 Reduktion von Redundanz
 Strukturierung von Information
 Abbildung realer Aufgabenstellungen und Prozesse auf Rechnerprozesse
 Umsetzung des Modells auf die reale Welt
 Abbildung von Rechnerprozessen auf reale Prozesse
 Abbildung von Datenstrukturen auf reale Strukturen
22
1.3
Die Teilgebiete der Informatik
 Wie viele Wissenschaften, ist die Informatik kein homogenes Gebilde, sondern
lässt sich anhand unterschiedlicher Kriterien in Teilgebiete strukturieren.
Dieses Kapitel beschreibt die wohl geläufigste Einteilung der Informatik in drei,
bzw. vier Teilbereiche.
 Inhalte
1.
2.
3.
4.
Technische Informatik
Praktische Informatik
Theoretische Informatik
( Angewandte Informatik )
23
1.3.1 Technische Informatik
 Konstruktion von Verarbeitungselementen
 Prozessoren, ...
 Konstruktion von Speicherelementen
 Hauptspeicher, ...
 Konstruktion von Kommunikationselementen
 Bussysteme
 Lokale Rechnernetze (LAN: Local Area Networks), Weitverkehrsnetze (WAN: Wide
Area Networks), ...
 Mobilfunknetze, Satellitenkommunikation, ...
 Konstruktion von Peripherie
 Drucker, Scanner, ....
 Festplatten, Optische Platten, Diskettenlaufwerke, ...
 ...
24
1.3.2 Praktische Informatik
 Umgang mit Programmiersprachen
 Programmierung
 Compilerbau
 ...
 Entwicklung von Software





Analysemethoden
Designmethoden
Realisierungsmethoden
Testverfahren
...
 Unterstützung der Softwareentwicklung
 Projektmanagement von DV-Projekten
 Qualitätsmanagement in DV-Projekten
 ...
 ...
25
1.3.3 Theoretische Informatik
 Sprachen und Automaten
 Formale Sprachen
 Grammatiken
 Sprachdefinitionen
 Berechenbarkeitstheorie
 Komplexitätstheorie
 ...
26
1.3.4 Angewandte Informatik
 Anwendung in verwandten Wissenschaften






Numerische oder stochastischer Verfahren in der Mathematik
Simulationen in der Physik und der Chemie
Bildverarbeitung in der Medizin
Genanalyse in der Biologie
Lehrprogramme für Natur-, Sozial- und Geisteswissenschaften
...
 Anwendungen im täglichen Leben.





Computerspiele, Multimediaanwendungen,
Textverarbeitung, Tabellenkalkulation, Datenbanken, ...
Steuerung von technischen Prozessen
Web-Anwendungen
...
 ...
27
1.4
Die Geschichte der Informatik
 Die Informatik ist eine junge Wissenschaft, hat aber, ähnlich wie andere Naturund Ingenieurwissenschaften Wurzeln, die weit in die Menschheitsgeschichte
hineinragen, Wie keine andere Wissenschaft wurde die Informatik jedoch von
der Erfindung eines Gerätes, dem programmgesteuerten Rechner (später
„Computer“) beeinflusst.
Dieses Unterkapitel wird die Wurzel in der Menschheitsgeschichte und auch die
Entwicklung des Rechners vorstellen.
 Inhalt
1.
2.
3.
4.
5.
6.
Information in der Geschichte
Automaten und Steuerungen
Erleichterung der Rechenarbeit
Pioniere der Informatik - Praktiker
Pioniere der Informatik - Theoretiker
Die Generationen
28
1.4.1 Information in der Geschichte





Erfassung durch Sinnesorgane
Transport durch akustische, optische, chemische Signale
Speicherung durch Gene oder neuronale Elemente
Verarbeitung über neuronale Elemente
Umsetzung direkt oder indirekt über Gliedmaße
 Entwicklung von Wort,- Silben- und Buchstaben-schriften
29
1.4.2 Automaten und Steuerungen
 ca. 100 v. Chr.
Mechanismus von Antikythera
älteste erhaltene Zahnrad-Apparatur
wahrscheinlich zur (analogen) Berechnung der
Bewegungen von Himmelskörpern
 Mittelalter
Mechanische Uhren mit Sonnen-, Mond- und
Planetenbewegungen und Figurenumläufe an
Kirchen und Rathäusern
 17./18. Jhdt.
Spieluhren, Schreib- und Schachspielautomaten
 18./19. Jhdt.
Fliehkraftregler für Dampfmaschinen, mechanischer Webstuhl mit
Lochkartenbebändert (Jacquart, 1805)
30
1.4.3 Erleichterung der Rechenarbeit
 Rechenbretter
 Seit dem Altertum
 China, Japan, Russland
 Addition/Subtraktion ähnlich schnell wie Taschenrechner
 Lehre der Grundrechenarten
 Durch Zahlensystem schematisierbar
 Lehre an mittelalterlichen Universitäten
 Durch Rechenbücher weitere Verbreitung des Wissens
(z.B. Adam Riese 1492-1559)
 Rückführung der Multiplikation/Division auf
Addition/Subtraktion durch logarithmisches Rechnen mit
Hilfe von Tabellen.
31
1.4.4 Mechanische Rechenmaschinen
 Wilhelm Schickart (1592-1635)
 Maschine für die Grundrechenarten (1623)
 Blaise Pascal (1623-1662)
 Gottfried Wilhelm von Leibniz (1646-1716)
 Arithmetik des Dualsystems
 Philipp Matthäus Hahn (1749-1790)
 Feinmechanische Rechenmaschinen
 19./20. Jhdt: Sprossenradmaschine
 Hermann Hollerith
 Lochkartenstanzer/
Sortierer/Tabellierer
32
1.4.5 Pioniere der Informatik - Praktiker
 Charles Babbage (1791-1871)
 Difference Engine (1812). Überprüfung von Logarithmentafeln.
Alle Merkmale eines programmierbaren Computers.
 Entwurf einer Analytical Engine (1836).
Wurde nie gebaut
 Konrad Zuse (geb. 1910)
 Z1: mechanischer Rechner
 Z2 / Z3: Elektromechanischer Relaisrechner im Dualsystem mit
Lochkartensteuerung.
Erster voll funktionstüchtiger Computer (1941)
 Grundlegende Arbeiten zur Programmierung und algorithmischer
Sprachen
 Howard Eiken
 Mark I, II, III, IV (1944)
Dezimalrechnender Relaisrechner
33
1.4.6 Pioniere der Informatik - Theoretiker
 Kurt Gödel
 Theoretische Aussagen zum Algorithmenbegriff:
Es gibt Aussagen die algorithmisch nicht entscheidbar sind (1931)
 Alan M. Turing (1911-1954)
 Definition des Algorithmenbegriffes über eine hypothetische
Maschine
(Turing-Maschine)
 John von Neumann (1903-1957)
 Grundlegende Arbeiten über Computerarchitektur:
 Speicherung der Daten und Programme auf dem gleichen
Medium
 Definition von Registern insb. Indexregister
34
1.4.7 Die Generationen
Generation
Vorgenerat.
1941-1944
1.Generation
1946 - 1958
2. Generation
1959 - 1964
3. Generation
1965 - 1980
4. Generation
Gegenwart
5. Generation
Beispiel
Z3
Mark1
ENIAC, Z22
UNIVAC, IBM650
SIEMENS704
IBM1400, AEG TR
CDC6600
Siemens2002
IBM370, PDP11
Siemens7000,
Cray 1
PC, Gray XMP
Sperry1100, VAX
IBM309x
Workstations
HochleistungsNetze
Technologie
Elektromechanik
Elektroröhren
Speich./Geschw.
0,0002 MIPS
Software
Verdrahtet
0,02 MIPS
1-2 KByte
Maschinensprache
Transistoren
Kernspeicher
0,1 MIPS
32 KByte
ICs
Halbleiterspeicher
Mikroprozessoren
Optische Sp.
Pentium,
Power PC
5 MIPS
1-2 MBytes
Assembler
FORTRAN
Stapelbetrieb
Hochsprachen
C, Pascal
supraleitende
Keramiken
50 MIPS
8-32 MByte
100 MIPS
1 GByte
C++. JAVA
1000 MIPS
viele GBytes
Sprachen der 1981-1999
4. Generation
Parallelisierung
Netzsoftware
OO-Sprachen
PCs
www.top500.org
35
1.5
Zusammenfassung des Kapitels

Die Informatik befasst sich mit der (automatisierten) Erfassung,
dem Transport, der Speicherung, Verarbeitung und dem Umsetzen von
Information
 Die Informatik ist eine „naturwissenschaftliche Ingenieurswissenschaft“
 Die Informatik gliedert sich in Technische, Praktische, Theoretische und
Angewandte Informatik
 Die Geschichte der Informatik beginnt im Altertum, besteht in Ihrer heutigen
Form aber erst seit ca. 1945. Zur Zeit befinden wir uns in der 4. Generation.
36
Kapitel 2 Information
Im Anfang war das Wort
Johannes 1.1
 Information ist der grundlegende Begriff der Informatik. Mehr noch: „Der Begriff
der Information ist vermutlich das zentrale interdisziplinäre Brückenkonzept der
modernen Wissenschaften * “.
Dieses Kapitel beschreibt, aus welchen Aspekten Information besteht, welche
für die Informarik wesentlichen Definitionsansätze es gibt und wie Information in
der Informatik tatsächlich dargestellt wird.
Inhalt
1.
2.
3.
4.
Was ist Information
Nachrichtentechnische Definition
Algorithmische Definition
Darstellung in der Informatik
* (einige Teile dieses Kapitels
entstammen: H.Lyre: „Informationstheorie)
37
2.1
Was ist Information
 Es deutet einiges darauf hin, dass „Information“ ein zumindest ebenso
fundamentaler Begriff ist, wie „Stoff“ in der Chemie und „Energie“ in der Physik
(die tatsächlich schon zu „Materie-Energie“ vereint wurden).
Betrachtet man Information als ursächliche (atomare) Größe so ist die Frage:
„was ist Information“ eher irrelevant. Dafür rücken Fragestellungen wie „woraus
besteht Information“, „worin ist Information“, „was kann ich mit Information
machen“ in den Vordergrund.
In diesem Unterkapitel soll die erste dieser Fragen: „woraus besteht
Information?“ betrachtet werden
 Inhalt
1. Semiotische Dreidimensionalität
2. Semantik und Pragmatik
3. Semantische Ebenen
38
2.1.1 Semiotische Dreidimensionalität
 Die wohl wichtigste Charakterisierung des Informationsbegriffes entspringt der
„Semiotik“ – der Zeichenlehre (Also die Lehre, die sich mit Zeichen bzw.
Symbolen befasst) und lässt sich auf den Informationsbegriff übertragen.
Demnach haben Informationseinheiten drei Aspekte:
 die Syntax betrifft das Auftreten einzelnder Informationseinheiten und ihrer
Beziehungen untereinander.
 die Semantik betrifft die Bedeutung der Informationseinheiten und ihre Beziehungen
untereinander.
 die Pragmatik betrifft die Wirkung der Informationseinheiten und ihrer Beziehungen
untereinander.
 Diese drei Aspekte
 müssen in ihrer Gesamtheit berücksichtigt werden
(entweder explizit oder implizit)
 sind ungewichtet
 haben keinen Bezug zum informationsverarbeitenden System (z.B. Mensch,
Maschine, …)
39
2.1.2 Semantik und Pragmatik
 Carl Friedrich von Weizsäcker:
 Information ist nur, was verstanden wird
 Information ist nur, was Information erzeugt
(die wiederum syntaktische Aspekte hat, verstanden werden muss und Information
erzeugen muss, die wiederum …  hermeneutischer Zirkel)
 Der Aspekt „verstanden werden“ erlaubt keine strenge Formalisierung (denn
was bedeutet „verstanden werden“ – wie kann man es messen)
sehr wohl lässt sich aber der Aspekt „Information erzeugen“ formalisieren.
Beispiel:
 Person A bittet Person B, das Licht einzuschalten:
Sequenz von Zeichen: „B I T T E S C H A L T E D A S L I C H T A N“
 Person B „interpretiert“ die Zeichenkette = wertet die Semantik, die Bedeutung der
Zeichenkette aus: „????“
 Person B generiert neue Information:
Licht = on
oder stellt sich einen erleuchteten Raum vor, was neurologisch zu messen ist.
 Da Semantik und Pragmatik eng miteinander verzahnt sind spricht man auch
vom semantopragmatischen Aspekt der Information
40
2.1.3 Semantische Ebenen
 Der semantopragmatischen Aspekt der Information zeigt die Unmöglichkeit
eines absoluten Begriffs von Information, d.h. Information ist relativ zu den
semantischen Ebenen der beteiligten Systemen.
Beispiel (siehe 2.1.2):
 Person A spricht deutsch, Person B kann kein deutsch
d.h. die semantischen Ebenen sind völlig disjunkt.
Daher ist in diesem Bezugssystem zwar der syntaktische Aspekt von Information,
aber keine semantischer und damit (sehr wahrscheinlich;-) auch kein pragmatischer
Aspekt und damit auch keine Information vorhanden.
 In der Realität sind unterschiedliche semantische Ebenen die Regel und
verändern sich auch dynamisch:
Beispiel: Beim Erlernen der Muttersprache testet ein Kleinkind zunächst Laute.
Bei einer positiven Reaktion (z.B. Ma-Ma) erfolgt rudimentäre Wortbildung, die
mit dem Semantikverständnis von Worten zu komplexeren syntaktischen
Strukturen (Sätzen) mit komplexeren semantischen Strukturen weiterentwickelt
werden.
 In der Informatik strebt man oft (z.B. bei einer Datenkommunikation) gleichartige
semantische Ebenen an.
41
2.2
Nachrichtentechnische Definition (nach Shannon)
 Information hat vielfältige Repräsentationsformen. Noch vor Entstehen der
Informatik als Wissenschaft hat Claude Elwood Shannon (1916-2001) wichtige
Maßzahlen zur Erfassung von Information definiert. Dabei geht er von der
nachrichtentechnischen Repräsentation von Information, der „Nachricht“ aus.
Diese Repräsentation von Information hat „eigentlich“ nur syntaktische Aspekte
(im Sinne der „Semiotischen Dreidimensionalität), denn es wird weder nach
dem Sinn der Nachricht gefragt, noch nach deren Konzequenz.
Dieses Unterkapitel stellt diese Maßzahlen und deren Grundlagen dar.
 Inhalt:
1.
2.
3.
4.
5.
Nachricht
Informationsgehalt einer Nachricht
Informationsgehalt eines Zeichens
Mittlerer Informationsgehalt
Informationsgehalt des Menschen
42
2.2.1 Definition: Nachricht
Informationsübetragung
(nach Shannon, Hartley,
Weaver und Wiener)
Sender

Kanal

Empfänger

Störung
 sei Alphabet X: Menge von Symbolen/Zeichen X = {x1, x2, ... xn}
 Eine Zeichenkette (ein Wort) der Länge n über X ist eine Folge von n Zeichen
aus X (ein n-Tupel über X)
 Beispiel:
X={a,b}
Worte über X:
Worte der Länge n mit n=3:
{a,b,ab,ba,aba,abb,baa,bbb, ...}
{aaa,aab,aba,abb,baa,bab,bba,bbb}
 Die Menge aller n-Tupel über X ist das n-fache
Kreuzprodukt X  X  ...  X (n mal), bezeichnet als Xn
 |Xn| = | X  X  ...  X | = |X| * |X| * ... * |X| = |X|n
 Die Anzahl der Elemente alle Worte mit der exakte Länge n ist |X|n
 Wird eine Zeichenkette übermittelt, so spricht man von Nachricht Nx
43
2.2.2 Definition: Informationsgehalt einer Nachricht
 Ein Maß für die Information (der Informationsgehalt) einer Nachricht Nn,x der
Länge n (über ein Alphabet X) ist die kürzeste Länge der Beschreibung, die
notwendig ist, um die Nachricht Nn,x aus der Menge aller möglichen
Nachrichten der Länge n sicher zu ermitteln
 Beispiel:
 Information der Nachricht N8,{0,1} : Suche in |{0,1}|8 = 256 Wörtern
obere Hälfte ?
ja
nein
obere Hälfte ?
obere Hälfte ?
ja
nein ja
nein
Optimal mit binärem Suchen
Anzahl Fragen:
ld(|Xn|) = ld(|X|n) = n ld(|X|)
...
 Der Informationsgehalt einer aus mehreren (voneinander unabhängigen)
Zeichen bestehenden Zeichenkette ist gleich der Summe der Informationen
der einzelnen Zeichen:

1 * ld(|X|) + 1* ld(|X|) + ... + 1* ld(|X|) = n * ld(|X|) = ld(|X|n)
44
2.2.3 Definition: Informationsgehalt eines Zeichens
 Idee:
 Der Informationsgehalt eines Symbols xi hängt von der Wahrscheinlichkeit seines
Auftretens ab: Je seltener ein Symbol auftritt, desto höher ist sein
Informationsgehalt:
h(xi) = f(1/p(xi))
 Definition nach Shannon (ca. 1950):
Der Informationsgehalt h (Einheit bit) eines Symbols xi ist definiert als der
Logarithmus Dualis des Reziprokwertes der Wahrscheinlichkeit, mit der das
Symbol auftritt:
h(xi) = ld(1/p(xi)) = -ld p(xi)
45
2.2.3 Beispiel: Informationsgehalt
 Beispiel: Sei die Wahrscheinlichkeit von E = 0,5 und die von H = 0,25
 Informationsgehalt des Zeichens „E“ :
hE = ld (1/0.5) = 1bit
 Informationsgehalt des Zeichens „H“ :
hH = ld (1/0,25) = 2 bit
 Informationsgehalt der Zeichenkette „EHE“
hEHE = ld(2) + ld(4) + ld(2) = ld(2 * 4 * 2) = 4 bit
Umrechnungsregel des ld in den 10er-Logarithmus (lg)
log a b =
log c b
log c a
lg b
mit a = 2, c = 10 gilt: ld b =
 3,322 lg b
lg 2
46
2.2.4 Definition: Mittlerer Informationsgehalt
 Kennt man die Einzelwahrscheinlichkeiten aller möglichen Symbole einer
Symbolsequenz, so ist der mittlere Informationsgehalt Hs der Symbole s
(Entropie der Quelle) definiert als:
Hs =  (p(xi) * h(xi)) =  (p(xi) * ld(1/p(xi))) = - ( p(xi) * ld(p(xi)))
 Der mittlere Informationsgehalt Hs,n einer Symbolkette der Länge n ist:
Hs,n = Hs * n
 Beispiel
d.h. die Symbole haben
P
p
h
einen mittleren Informax 0,5
x 0,5 1
tionsgehalt von 1,5 bit.
y
z
0,25
0,25
y
z
0,25 2
0,25 2
Hs = 0,5 * 1bit + 0,25 * 2bit + 0,25 * 2bit = 1,5 bit
47
2.2.5 Informationsaufnahme des Menschen
 Beim Lesen (eines deutschen Textes) erreicht der Mensch eine Geschwindigkeit
von ca. 25 Zeichen/sec
 das entspricht 25 * 2 Bit (mittleren Informationsgehalt in der deutschen Sprache) =
50 Bit/sec
 dieser Wert ist unabhängig vom Alphabet - kann also auch z.B. im chinesischen
erreicht werden (weniger Zeichen/sec, größerer mittlerer Informationsgehalt).
 Nachrichten, die mit anderen Medien dargestellt werden, können ca. genauso
schnell verarbeitet werden.
 Aufnahme des Menschen
 Bewusst aufgenommen werden ca. 50% von 50 Bit/sec also 25 bit/sec
 Bei einer Aufnahmedauer von ca. 16 Stunden am Tag ergibt sich eine
Lebensinformationsmenge von ca. 3 * 1010 Bit
 die Speicherkapazität des Gehirns ist mit ca. 1012 Bit auch in der Lage, diese
Informationsmenge zu speichern (sogar 100 Mal)
 Die Lebensinformationsmenge findet auf einer CD-ROM Platz und ist über
Glasfaserkabel in wenigen Sekunden zu übertragen.
48
2.3
Algorithmische Definition
 Betrachten wir folgende Nachrichten (A und B):
Nachricht A: 1110111011000110110101100010
Nachricht B: 1111000111100011110001111000
nach Shannon ist der Informationsgehalt der ersten Zeichenkette A identisch mit
dem der zweiten Zeichenkette B (denn hA(0)=hB(0) und hA(1)= hB(1))
Aber: Ist das (intuitiv) wirklich so ?
Tatsächlich lässt sich die Information aus Nachricht B leicht (algorithmisch)
beschreiben: „4 1en, dann 3 0en, das Ganze 4 mal“
Hat man also die Regelmäßigkeit der Nachricht „verstanden“ lässt sich die
Information einfacher (kürzer) formulieren. Im Sinne der „Semiotischen
Dreidimensionalität“ berücksichtigt die Algorithmische Definition von Information
zusätzlich zur Syntax auch die Semantik.
 Inhalt:
1. Die Turing-Maschine
2. Das Turing-Programm
3. Beispiele
49
2.3.1 Einige Fragen
1. Kann jede Zeichenkette durch Regeln (einen Algorithmus) beschrieben werden.
2. Wie können diese Regeln zur Generierung von Zeichenketten beschieben
werden?
3. Gibt es ein Modell, mit dem man solche Regeln formalisieren kann?
 Wie sieht ein solches abstraktes Model aus ?
 Gibt es genau ein Model oder mehrere ?
 Sind diese Modelle äquivalent ?
50
2.3.2 Die Turing-Maschine
 Als abstraktes Modell eines Computers beschrieb Alan Turing (1912-1954)
1936 - also noch vor der Erfindung des Digitalrechners - eine nach ihm
benannte abstrakte Maschine
 Formal kann eine Turing-Maschine wie folgt beschrieben werden:
 Alphabet: A = {a0, ... , an}, der Zeichenvorrat der Turing-Maschine, wobei a0 das
Leerzeichen ("blank") darstellt (Oft: a1=0, a2=1)
 Bandinschrift: B: Z  A eine Zuordnung, die jeder Stelle des rechtsseitig
unendlichen Bandes ein Zeichen zuordnet. Dabei wird festgesetzt, dass B(k) = a0
für alle bis auf endlich viele .
 Kopfposition: k  Z
 Zustände: eine endliche Menge von Maschinenzuständen.Q = {q0, ..., qm} Darunter
sind q0, der Anfangszustand und H  Q , die Menge der Haltezustände,
ausgezeichnet.
 Statt Haltzustände wird oft auch eine Halteaktion angegeben
 Turing-Tabelle:
eine Übergangsrelation: d : A  Q  A  Q  {r, l, n, h}, das jedem (gelesenen)
Zeichen in Abhängigkeit eines Zustandes ein neues Zeichen, einen Folgezustand
und eine Aktion (r,l,n,h} zuordnet
51
2.3.3 Das Turing-Programm
a1 a2 a3 a4 ... a6
falls
so ist
die
Maschine
im Zustand
q
das unter dem
Kopf gelesene
Zeichen
das neue
Zeichen
ak
al
die
Aktion
der neue
Zustand
r oder l
q‘
 Die Aktionen:
 r (right): das Verschieben des Kopfes nach rechts
 l (left): das Verschieben des Kopfes nach links
 optional n (none): keine Bewegung des Kopfes
 optional h (halt): Impliziter Übergang in einen Endzustand
52
2.3.4 Beispiel
 Das „Busy beaver“-Problem:
Wie viele „1“-en kann ein terminierendes Turing-Programm auf einem leeren
Band mit einer vorgegebenen Anzahl von Zuständen maximal erzeugen.
 In dieser Notation wird statt eines Übergangs in den Haltezustand (z.B. q5) die
Aktion „halt“ ausgeführt.
11 Schritte, 6 Einsen
96 Schritte, 13 Einsen
 Der Rekord für |Z|=5 liegt bei 4096 „1“en (J.Buntrock, H.Marxen, 1989)
 Es wurde gezeigt, dass es möglich ist, mehr als 4098 „1“en zu generieren allerdings nicht wie.
53
2.3.5 Information
 Die algoritmische Definition definiert Informationgehalt:
Der algorithmische Informationsgehalt einer Nachricht ergibt sich aus der
Länge L des kürzesten Algorithmuses (z.B. Turing-Programms), welches die
Nachricht erzeugt.
 Daraus ergibt sich, dass der algorithmische Informationsgehalt (bis auf eine
kleine Konstante) immer kleiner oder gleich dem (nachrichtentechnischen)
Informationsgehalt einer Nachricht ist, denn im „einfachsten“ Fall kann die
Turing-Maschine die komplette Nachricht auf dem Turingband codieren und
besteht aus einem leeren Programm.
 Es gibt keine Möglichkeit, für beliebige Nachrichten zu bestimmen, ob der
algorithmische Informationsgehalt kleiner als der nachrichtentechnische
Informationsgehalt (ob es also ein Turing-Programm gibt, welches die Nachricht
„geschickter“ codiert).
54
2.4
Darstellung in der Informatik
 Die Wurzeln der Informatik liegen weniger in der Nachrichtentechnik, als
vielmehr in der Mathematik. Darum ist die Repräsentation von Information als
Nachricht weniger relevant als die Darstellung von Zahlen (in binärer
Repräsentation) und algebraischen (bool‘schen) Objekten.
In diesem Unterkapitel geht es um diese Repräsentationen.
 Inhalt
1.
2.
3.
4.
Das Bit in der Informatik
Die Darstellung des Bit
Beispiel
Das Byte und mehr
55
2.4.1 Das Bit in der Informatik
 Definition aus der Informatik:
Ein bit ist die Informationsmenge in einer Antwort, auf eine Frage, die zwei
Möglichkeiten zulässt:




ja /nein
wahr/falsch
schwarz/weiß
...
 Der Informationsgehalt eines Zeichens einer zweielementigen Alphabetes mit
gleicher Auftretungswahrscheinlichkeit ist
(nach Shannon)
h = -ld p = -ld 0,5 = 1bit
56
2.4.2 Die Darstellung des Bit
 Diese zwei Möglichkeiten werden meist mit 0 bzw. 1 codiert
 Die technische Darstellung erfolgt u.a. mit Hilfe von:
 Ladung
 0 = ungeladen
 1 = geladen
 Spannung
 0 = 0 Volt
 1 = 5 Volt
 Magnetisierung
 0 = nicht magnetisiert
 1 = magnetisiert
 Licht
 0 = kein Licht
 1 = Licht
 Reflexionseigenschaften
 0 = reflektiert
 1 = reflektiert nicht
 ...
57
2.4.3 Das Byte und mehr
 Aus bestimmten Gründen
 Geschwindigkeit von Lese- und Schreiboperationen
 Darstellungsmöglichkeit „häufiger“ Zeichen (z.B. Alphabet)
 Darstellungsmöglichkeiten von Zahlen, etc.
werden in der Informatik oft Vielfache von 8bit-Gruppen verwendet (8bit, 16bit, ...)
Eine 8-Bitsequenz heißt ein Byte.
 Diese 8bit werden manchmal nochmals unterstruktuiert in zwei 4er Gruppen, die
dann „Nibble“ heißen.
 Nibble können geschickt als Hexadezimalziffer dargestellt werden.
 Bestimmte 2er-Potenzen werden in der Informatik häufig als Maßzahlen (z.B. für
Speichergrößen) verwendet:




1 KByte = 210 = 1024 Byte (1 Kilobyte)
1 MByte = 210 * 210 Byte (1 Megabyte)
1 GByte = 210 * 210 * 210 Byte (1 Gigabyte)
1 TByte = 210 * 210 * 210 * 210 Byte (1 Terrabyte)
58
2.4
Zusammenfassung des Kapitels
 Was ist Information
 Nachrichtentechnische Definition
 Informationsgehalt
 eines Zeichens (x)
 einer Nachricht (n)
 Mittlerer Informationsgehalt
 ein/aller Zeichen(s) (x)
 einer Nachricht (n)
 Algorithmische Definition
 Definition in der Informatik
h(x) = ld (1/p(x)) = - ld (p(x)
h(n) = h(n1) + h(n2) + h(n3) + ...
H(x) =  p(xi) * h(xi)
n * H(x)
Achtung:
Nicht
verwechseln !
 Bits und Bytes
59
Kapitel 3 Codes
… und das Wort ward Fleisch
Johannes 1.14
 Information ist abstrakt: damit Information in einem Rechner verarbeitet
werden kann, muss sie in eine für den Rechner verarbeitbare Form
transformiert werden.
Dabei kann man sich beliebig ungeschickt anstellen. Dieses Unterkapitel
beschreibt, wie eine solche Transformation funktionieren kann, welche
Möglichkeiten man dabei hat und gibt ein Maß für die Qualität einer
Transformation an.
 Inhalt
1.
2.
3.
4.
Definitionen
Codes zur Optimierung der Codelänge
Codes zur Fehlererkennung und Fehlerkorrektur
Beispiele
60
3.1
Definitionen
 … ein paar Definitionen ..
 Inhalt
1.
2.
3.
4.
5.
Definition
Willkürliche Codes
Fano-Bedingung
Mittlere Wortlänge
Redundanz
61
3.1.1 Definition: Code
 Definition:
Seien X,Y zwei Alphabete
 Eine Codierung ist eine Abbildung C:XnYm aller n-Tupel aus X nach m-Tupel aus Y.
 oft ist n=1
 oft ist X,Y = {0,1}
 Die Worte aus Ym werden Code genannt.
 Die Umkehrrelation C-1 bezeichnet man als Dekodierung
 Definition:
Ein Code heißt vollständig, wenn alle Wörter aus Xn mit Hilfe der Codierung
abgebildet werden können.
 Definition:
Für ein Wort Xin aus C:XinYim ist m die Länge l(Xin) von C(Xin)
(Zur Erinnerung: meist in n=1, d.h. die Codierung bildet ein jeweils ein Zeichen xi
auf mehre Zeichen xim ab)
 Definition:
Ein Code heißt Code gleicher Länge, wenn die Anzahl der Symbole auf die ein
Wort abgebildet wird, für alle Worte gleich ist
(also: l(Xn)=m konstant für alle XnYm).
Ansonsten heißt der Code: Code unterschiedlicher Länge
62
3.1.2 Definition: Eindeutigkeit
 Definition:
Ein Code heißt eindeutig, wenn C-1 injektiv ist, ansonsten heißt er mehrdeutig
 Codes sollten also (meist) so beschaffen sein, dass sie bei der Decodierung
eindeutig sind.
 Gegenbeispiel:
z
p
l
l*p
A
0,2
2,32
0,46 101
3
0,60
E
0,3
1,74
0,52 01
2
0,60
I
0,2
2,32
0,46 100
3
0,60
O
0,25
2,00
0,50 11
2
0,50
U
0,05
4,32
0,22 11100
5
0,25
R=L-H=0,38
h
h*p
H = 2,17
c
L = 2,55
 Problem Dekodierung:
 10111100100
=
101 11100 100
101 11 100 100
(aui)
(aoii)
63
3.1.3 Definition: Fano-Bedingung



Fano-Bedingung:
Kein Codewort darf Anfang eines anderen Codewortes sein
Beispiel:
z
c
z
c
A
101
A
00
E
01
E
10
I
100
I
010
O
11
O
11
U
11100
U
011
Die Fano-Bedingung ist hinreichend aber nicht notwendig
 hinreichend:
Wenn die Fano-Bedingung erfüllt ist, ist der Code eindeutig
 nicht notwendig: Auch eine Codierung, die die Fano-Bedingung nicht erfüllt kann eindeutig
sein.
Beispiel: a  1, b  10

Anmerkung: Eine Betrachtung der Fano-Bedingung macht „eigentlich“ nur Sinn bei Codes
unterschiedlicher Länge (warum ?)
64
3.1.4 Definition: Mittlere Wortlänge
 Codiert man die Zeichen eines Alphabetes binär (also mit Sequenzen eines 2Zeichen-Alphabetes, z.B. 0 und 1) , so versteht man unter der mittleren
Wortlänge L eines Codes die mit den Auftrittswahrscheinlichkeiten gewichtete
Summe der Längen l(xi) der den einzelnen Symbole entsprechenden
Codewörtern
L =  p(xi) * l(xi)
 Beispiel
x
y
z
Code
1
01
00
l
1
2
2
p
0,5
0.25
0,25
h
1
2
2
p*h
0,5
0,5
0,5
p*l
0,5
0,5
0,5
011100011
yxxzyx
H = 1,5 Bit
L = 1,5 Bit
65
3.1.5 Definition: Redundanz
 Die mittlere Wortlänge eines Binärcodes ist immer größer oder gleich dem
mittleren Informationsgehalt.
 Die Differenz zwischen mittlerer Wortlänge und mittlerem Informationsgehalt
wird als Redundanz R des Codes bezeichnet:
R=L-H
 Die Redundanz bezogen auf die Wortlänge nennt man relative Redundanz r:
r=R/L
 Redundanz ist also ein Maß für die Qualität einer Kodierung (insofern die
Länge eines Codes als Qualität angesehen wird)
66
3.1.6 Redundanz – Beispiel
 Beispiel
x
y
z
Code
1
01
00
l
1
2
2
p
0,5
0.25
0,25
h
1
2
2
p*h
0,5
0,5
0,5
H
1,5 Bit
p*l
0,5
0,5
0,5
p
0,7
0.2
0,1
h
0,515
2,322
3,322
L
1,5 Bit
p*h
0,360
0,464
0,332
p*l
0,7
0,4
0,2
H
L
1,16 Bit 1,3 Bit
H =  pi * hi = -  pi * ld(pi)
= 0,360+0,464+0,332 = 1,156
L =  pi * li
= 0,7+0,4+0,2 = 1,3
R =L-H
= 1,3 - 1,156 = 0,144
r =R/L
= 0,144 / 1,3 = 0,111
67
3.1.7 Codierungsarten
 Die Entropiekodierung
 kodiert ungeachtet der zugrundliegenden Information und betrachtet die zu
komprimierten Daten als “reine” Bitsequenz (also nur die Syntax).
 es werden nur (informationstheoretische) Redundanzen eliminiert, es geht keine
Information verloren.
 unterschiedliche Kompressionsquoten bei unterschiedlichen zu komprimierenden
Daten.
 Die Quellenkodierung
 ist abhängig von den zu kodierenden Informationen (daher: Quellcodierung). und
verwendet dazu die Semantik der zu kodierenden Information.
 eliminiert für das “Ziel” (z.B. den Menschen) definierte Redundanzen und ist (meist)
verlustbehaftet.
 Spezifika der Informationen können dadurch gut genutzt werden und man erreicht
eine wesentlich bessere Kompressionsraten bei "akzeptabler" Qualität.
68
3.2
Huffman-Codierung
 Oft ist es wichtig, einen Code möglichst kurz zu gestalten
 aus Gründen der Speicherplatzoptimierung
 aus Gründen der Übertragungskapazitäts-Optimierung
 …
 Idee
 Häufige Symbole – kurze Codes, Seltene Symbole – lange Codes
 Kodierung
 Die Häufigkeit des Auftretens der Zeichen (oder Zeichenketten) wird bestimmt
 Die am häufigsten auftretenden Zeichen (oder Zeichenketten) werden mit kurzen
Bitfolgen (Huffmann-Code) kodiert
 Der Huffmann-Code wird zur Kodierung der Bitfolge verwendet
 Dekodierung
 Dekodierer besitzt identischen Huffmann-Code (oder bekommt die
Zuordnungstabelle explizit übertragen)
 Dekodierer setzt den Huffmann-Code in Bytefolge um
 Die Huffmann-Codierung generiert einen vollständigen, eindeutigen Code
unterschiedlicher Länge (der die Fano-Bedingung erfüllt)
69
3.2.1 Vorgehen
 Der Baum wird von oben nach unten mit den zwei Buchstaben (oder
Buchstabengruppen) mit den jeweils kleinsten Wahrscheinlichkeiten schrittweise
aufgebaut
sei
P(A) = 0,16
P(B) = 0,51
P(C) = 0,09
P(D) = 0,13
P(E) = 0,11
P(C)=0,09
P(E)=0,11
1
0
P(D)=0,13
1
1
1
0
P(A  D)=0,29
P(CE)=0,2
P(B)=0,51
P(A)=0,16
0
P(C  E  A  D)=0,49
0
Kodierung
A = 000
B=1
C = 011
D = 001
E = 010
P(B  C  E  A  D)=1,0
70
3.2.2 Verbesserung
 Codierung ist optimal, wenn sich die Wahrscheinlichkeiten der Zeichen
„geschickt“ ergeben
 „geschickt“ sind Wahrscheinlichkeiten mit negativen 2er-Potenzen.
 Durch Betrachtung (und Codierung) von Zeichenpaaren, -drillingen, ... , nTupeln können solche „geschickten“ Wahrscheinlichkeiten gefunden werden
 Die Redundanzen lassen sich sogar beliebig verkleinern, weil die
Einzelwahrscheinlichkeiten von n-Tupeln beliebig klein werden und dadurch immer
„geschickter“ kombiniert werden können.
 Beispiel:
z
p
z
p
z
p
A
0,80
AA
0,64
AAA
0,512
B
0,20
AB
0,16
AAB
0,128
BA
0,16
ABA
0,128
BB
0,04
...
...
BBB
0,008
Produkt der Einzelwahrscheinlichkeiten
(Annahme: Auftritt von A,B unabhängig)
...
71
3.2.3 Beispiel für Tupelbildung
 Beispiel
z
p
h
h*p
c
l
l*p
A
0,80
0,32
0,26
0
1
0,80
B
0,20
2,32
0,46
1
1
0,20
R = 0,26
H = 0,72
z
p
AA
0,64
0,64
AB
0,16
BA
BB
R = 0,12
h
L = 1,00
h*p
l
l*p
0,41 0
1
0,64
2,64
0,42 10
2
0,32
0,16
2,64
0,42 110
3
0,48
0,04
4,64
0,19 111
3
0,12
H = 1,44
c
L = 1,56
72
3.3
Hamming-Codierung
 Manchmal ist es wichtig, Fehler in einem Code zu erkennen und ggf. zu
korrigieren. (z.B. bei der Übertragung)
 Idee
 Gezielter Einsatz von Redundanz
 Nicht alle möglichen Codeworte sind daher gültig
 Kodierung
 Dem Code werden zusätzliche Bits hinzugefügt.
 Die Werte der zusätzlichen Bits stehen in Bezug zu den ursprünglichen Bits
 Beispiel aus der natürlichen Sprache
 “Ich studiere in Gießer” – Fehler kann erkannt und behoben werden
 “Ich liebe rich” – Fehler kann erkannt, aber nicht behoben werden
73
3.3.1 Beispiel ASCII
 Paritätsbit bei der 7-bit ASCII-Codierung
 wähle das 8te Bit so, dass immer eine gerade Anzahl von Bits gesetzt ist (gerade
Anzahl = „even parity“, ungerade Anzahl = „odd parity“)
Zeichen
@
A
B
C
Binär
100 0000
100 0001
100 0010
100 0011
mit even Parity
1100 0000 :=
1+1=2
0100 0001 :=
1+1+0=2
0100 0010 :=
1+1+0=2
1100 0011 := 1 + 1 + 1 + 1 = 4
 erhält man eine Nachricht mit ungerader Anzahl, so weiß man, dass
(mindestens) ein Bit verkehrt ist.
 man weiß allerdings nicht welches
 man weiß auch nicht, ob nicht mehr als ein Bit verkehrt ist
 man weiß bei richtigem parity-Bit auch nicht, ob nicht mehr als 1 Bit verkehrt ist
 Idee: den „Abstand“ gültiger Worte so groß wie nötig wählen
74
3.3.2 Hamming-Distanz
 Definition:
Der Hamming-Abstand (die Hamming-Distanz D) zwischen zwei Wörtern
ist die Anzahl der Stellen, an denen sich zwei Worte gleicher Länge
unterscheiden.
 Beispiel: Hamming-Abstand von 1100 0000 (A) und 0100 0001 (B) = 2
 Definition:
Der Hamming-Abstand (die Hamming-Distanz D) eines Codes ist der
minimale Hamming-Abstand zwischen zwei beliebigen Wörtern des Codes.
 Beispiel: Hamming-Abstand von ASCII (mit even parity) = 2
 Einige Konsequenzen:
 Codes mit Hamming-Distanz = 0 sind nicht eindeutig
 Bei Codes mit Hamming-Distanz = 1 kann das „Kippen“ eines Bits zu einem
anderen gültigen Codewort führen (muss nicht)
 Bei Codes mit Hamming-Distanz = 2 kann ein Ein-Bit Fehler erkannt werden.
75
3.3.3 Fehlererkennung
 Fehler, bei denen höchstens D-1 Bits gestört sind, können sicher erkannt
werden
 einige andere Fehler können, müssen aber nicht unbedingt erkannt werden können.
(genau dann, wenn die Hamming-Distanz zwischen zwei Wörtern eines Codes
größer als die Distanz des Codes ist)
 Fehler werden erkannt, wenn ein Codewort ungültig ist
gültiges Codewort
„nur“ erkennbares Codewort
A
korrigierbares Codewort
B
1-Bit-Fehler
2-Bit-Fehler
76
3.3.4 Fehlerkorrektur
 Fehler, bei denen höchsten (D-1)/2 Bits gestört sind, können sicher korrigiert
werden
 einige andere Fehler können, müssen aber nicht korrigiert werden können
(genau dann, wenn die Hamming-Distanz zwischen zwei Wörtern eines Codes
größer als die Distanz des Codes ist)
 Falsches Codewort wird dem „nächstmöglichen“ Codewort (d.h. dem mit der
minimalen Distanz) zugeordnet.
gültiges Codewort
korrigierbares Codewort
A
B
1-Bit-Fehler
2-Bit-Fehler
77
3.3.5 Hamming
 Idee
 Jedes Prüfbit stellt die gerade Parität einer gewissen Menge von Bits (einschließlich
sich selbst) sicher
 Jedes Datenbit kann in mehreren dieser Mengen einbezogen sein
... P D D D P D P P
8
1
 Die Hamming-Methode
 Es werden an der 1,2,4,8,... Stelle Prüfbits eingeführt
 Jedes Prüfbit hat damit in seiner dualen Stellennummer genau eine Stelle mit einer
1 (1,2,4,8,... = 1,10,100,1000,...)
 Alle Stellen im Wort, die an derselben Stelle eine 1 haben (und an den anderen 1
oder 0) werden aufsummiert
 1  001,011,101,111, ... also 1,3,5,7, ... Stellen
 10  010,011,110,111, ... also 2,3,6,7, ... Stellen
 100  100,101,110,111, ... also 4,5,6,7, ... Stellen
 Das entsprechende Parity-Bit wird als even-parity Bit gesetzt
 Die Hamming-Methode generiert einen eindeutigen, vollständigen Code
gleicher Länge
78
3.3.6 Beispiel Hamming
 zu kodieren: 1011
 Prüfbit 1 (001)
relevant 011,101,111
also Bit 3,5,7
Summe = 3  Bit setzen
 Prüfbit 2 (010)
relevant 011,110,111
also Bit 3,6,7
Summe = 2  Bit löschen
 Prüfbit 4 (100)
relevant 101,110,111
also Bit 5,6,7
Summe = 2  Bit löschen
1 0 1 P 1 P P
7
1
 kodiert: 1010101
1 0 1 0 1 0 1
1 0 1 P 1 P 1
1 0 1 P 1 0 1
79
3.3.7 Beispiel Hamming
 Fehlerhafter Code: 1000101
 Verfahren
 prüfe alle Parity-Bits
 k = Summe der fehlerhaften
Bitnummern
1 0 0 0 1 0 1
7
1
 k gibt die Nummer des gestörten Bits
an (nur bei 1-Bit Fehler zuverlässig)
 Hier:





Bit1 prüft 3,5,7: falsch
Bit2 prüft 3,6,7: ok
Bit4 prüft 5,6,7: falsch
k=1+4=5
 Bit5 muss getauscht werden
1 0 1 0 1 0 1
80
3.4
Beispiele
 Anhand zweier Beispiele soll gezeigt werden, wie:
 die Natur, Gott (oder das fliegende Spaghetti-Monster)
 der Mensch
Information codiert
 Inhalt
1. Genetische Codierung
2. Bildcodierung
81
3.4.1 Genetische Codierung
 Beim Menschen ist die Desoxyribonukleinsäure (DNS, engl. DNA) der Träger
der genetischen Information und Hauptbestandteil der Chromosomen.
 Die DNS ist ein kettenförmiges Polymer aus Nukleotiden, die sich in ihren
Stickstoffbasen unterscheiden (Thymin/Cytosin bzw. Adenin/Guanin,)
 das Alphabet des Codes ist also:
{Thymin, Cytosin, Adenin, Guanin,} oder auch { T, C, A, G }
 Je drei aufeinanderfolgende Basen bilden ein Wort
 Es gibt also pro Wort 43 = 64 Kombination
 die Wortlänge ist also ld(64) bit = 6 bit




Ein Gen enthält etwa 200 Worte
Ein Chromosom enthält ca. 104 bis 105 Gene
Die Anzahl der Chromosomen pro Zellkern ist beim Menschen 46
Die pro Zellkern gespeicherten Daten haben damit ein Volumen von
6 bit * 200 * 105 * 46 = 55200 bit * 105  5 * 109 bit *  109 Byte = 1 GByte
82
2.2.3 Bildcodierung
Datenkompression bei der Bildcodierung (z.B. JPEG, MPEG, …) durchläuft
typischerweise vier Schritte:
1. Datenaufbereitung
 erzeugt eine geeignete digitale Darstellung der Information
 Bsp.: Zerlegung eines Bildes in Pixelblöcke
2. Datenverarbeitung
 erster Schritt der Kompression, z.B. Transformation aus dem Zeitbereich in den
Frequenzbereich (z.B. durch Discrete Cosinus Transformation – DCT)
3. Quantisierung
 Gewichtung der Amplituden und Zuordnung zu Quantisierungsstufen (nicht
notwendigerweise linear)
4. Entropiekodierung
 verlustfreie Kompression (z.B. durch Huffmann-Codierung)
(2 x  1)u
(2 y  1)v
s
cucv  syx cos
cos
16
16
x 0 y 0
7
7
(2 x  1)u
(2 y  1)v
1
sxy  4  cucvsvu cos
cos
16
16
x 0 y 0
7
1
vu 
4
7
1
für u, v  0
2
bzw. sonst cu , cv  1
cu, cv 
83
3.6
Zusammenfassung des Kapitels
 Definitionen






Codierung, Code, Vollständigkeit, Länge
Eindeutigkeit
Fano-Bedingung
mittlere Wortlänge
Redundanz
Codierungsarten
L =  p(xi) * l(xi)
R=L-H
 Huffmann-Codierung
 Vorgehen
 Verbesserungen
 Hamming-Codierung





Beispiel ASCII
Hamming-Distanz
Fehlererkennung / -korrektur
Hamming-Codierverfahren
Beispiele
 Beispiele
 Genetische Codierung
 Bildcodierung
84
Kapitel 4 Zeichen und Zahlen
… da schrieb er auf die Tafeln, wie die erste Schrift war
5. Mose 10.4
 Auch wenn Objekte der realen Welt beliebig komplex in Zusammensetzung und
Struktur sind, so werden sie meist auf zwei einfache Repräsentationen - als
Abstraktion - abgebildet:
Zeichen und Zahlen.
Dieses Kapitel beschreibt, wie diese Objekte in eine für den Rechner
verarbeitbare Form kodiert werden können.
 Inhalt
1. Kodierung von Zeichen
2. Darstellung von Zahlen
85
4.1
Kodierung von Zeichen
 Die Wurzeln der Informationscodierung in der Menschheitsgeschichte liegt in
der Entwicklung der Schrift. Menschen haben dabei versucht, mündliche
Erzählung in Form von Bild-, Silben- oder Buchstabenschriften dauerhaft zu
„codieren“.
Dabei kommt der Buchstabenschrift im westlichen Kulturbereich eine besondere
Bedeutung zu und wird durch Schriftzeichen aus aller Welt zunehmend ergänzt.
Diese Entwicklung spiegelt sich auch in folgenden Unterkapiteln wider.
 Inhalt
 ASCII
 EBCDIC
 UNICODE
86
4.1.1 ASCII -Tabelle (7Bit)
 American Standard Code for Information Interchange
@ NUL 000 T
DC4 020 (
040 <
060 P
080 d
100 x
120
A
SOH 001 U
NAK 021 )
041 =
061 Q
081 e
101 y
121
B
STX 002 V
SYN 022 *
042 >
062 R
082 f
102 z
122
C
ETX 003 W
ETB 023 +
043 ?
063 S
083 g
103 {
123
D
EOT 004 X
CAN 024 ,
044 @
064 T
084 h
104 _|
124
E
ENQ 005 Y
EM
025 -
045 A
065 U
085 i
105 }
125
F
ACK 006 Z
SUB 026 .
046 B
066 V
086 j
106 ~
126
G
BEL
007 [
ESC 027 /
047 C
067 W
087 k
107
H
BS
008 \
FS
028 0
048 D
068 X
088 l
108
I
HT
009 ]
GS
029 1
049 E
069 Y
089 m
109
J
LF
010 ^
RS
030 2
050 F
070 Z
090 n
110
K
VT
011 _
US
031 3
051 G
071 [
091 o
111
L
FF
012 SP
032 4
052 H
072 \
092 p
112
M
CR
013 !
033 5
053 I
073 ]
093 q
113
N
SO
014 "
034 6
054 J
074 ^
094 r
114
O
SI
015 #
035 7
055 K
075 _
095 s
115
P
DLE 016 $
036 8
056 L
076 `
096 t
116
Q
DC1 017 %
037 9
057 M
077 a
097 u
117
R
DC2 018 &
038 :
058 N
078 b
098 v
118
S
DC3 019 '
039 ;
059 O
079 c
099 w
119
DEL
127
87
4.1.1 ASCII - Sonderzeichen
 Bedeutung der Sonderzeichen im ASCII-Code
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
NUL
SOH
STX
ETX
EOT
ENQ
ACK
BEL
BS
HT
LF
VT
FF
CR
SO
SI
DLE
DC1
Null, or all zeros
StartHeading
StartText
EndText
EndTransmission
Enquiry
Acknowledge
Bell
Backspace
HorizontalTab
LineFeed
VerticalTab
FormFeed
CarriageReturn
ShiftOut
ShiftIn
DataLinkEscape
DeviceControl1(XON)
R
S
T
U
V
W
X
Y
Z
[
\
]
^
_
DC2
DC3
DC4
NAK
SYM
ETB
CAN
EM
SUB
ESC
FS
GS
RS
US
SP
DeviceControl2
DeviceControl3(XOFF)
DeviceControl4
Neg.Acknowledge
SynchronousIdle
EndTrans.Block
Cancel
EndofMedium
Substitute
Escape
FileSeparator
GroupSeparator
RecordSeparator
UnitSeparator
Space
?
DEL
Delete
88
4.1.2 EBCDIC - Tabelle
 Extended Binary Coded Decimals Interchange Code
nul
soh
stx
etx
pf
ht
lc
del
ge
rlf
smm
vt
ff
cr
so
si
dle
dc1
dc2
tm
res
nl
bs
il
can
em
00
001
002
003
004
005
006
007
008
009
00a
00b
00c
00d
00e
00f
010
011
012
013
014
015
016
017
018
019
cc
cu1
ifs
igs
irs
ius
ds
sos
fs
01a
01b
01c
01d
01e
01f
020
021
022
023
byp 024
lf
025
etb 026
esc 027
028
029
sm
02a
cu2 02b
02c
enq 02d
ack 2e
bel
2f
030
031
syn 032
033
pn
rs
uc
eot
cu3
dc4
nak
sub
Sp
¢
.
>
(
034
035
036
037
038
039
03a
03b
03c
03d
03e
03f
040
041
042
043
044
045
046
047
048
049
04a
04b
04c
04d
+
|
&
!
$
*
)
;
/
04e
04f
050
051
052
053
054
055
056
057
058
059
05a
05b
05c
5d
5e
5f
060
061
062
063
064
065
066
067
068
069
| 06a
, 06b
% 06c
06d
< 06e
? 06f
070
071
072
073
074
075
076
077
078
` 079
: 07a
# 07b
@ 07c
' 07d
= 07e
" 07f
080
a 081
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
082
083
084
085
086
087
088
089
08a
08b
08c
08d
08e
08f
090
091
092
093
094
095
096
097
098
099
09a
09b
~
s
t
u
v
w
x
y
z
09c
09d
09e
09f
0a0
0a1
0a2
0a3
0a4
0a5
0a6
0a7
0a8
0a9
0aa
0ab
0ac
0ad
0ae
0af
0b0
0b1
0b2
0b3
0b4
0b5
{
A
B
C
D
E
F
G
H
I
0b6
0b7
0b8
0b9
0ba
0bb
0bc
0bd
0be
0bf
0c0
0c1
0c2
0c3
0c4
0c5
0c6
0c7
0c8
0c9
0ca
0cb
0cc
0cd
0ce
0cf
}
J
K
L
M
N
O
P
Q
R
0d0
0d1
0d2
0d3
0d4
0d5
0d6
0d7
0d8
0d9
0da
0db
0dc
0dd
0de
0df
\ 0e0
0e1
S 0e2
T 0e3
U 0e4
V 0e5
W 0e6
X 0e7
Y 0e8
Z 0e9
0ea
0eb
0ec
0ed
0ee
0eF
0 0f0
1 0f1
2 0f2
3 0f3
4 0f4
5 0f5
6 0f6
7 0f7
8 0f8
9 0f9
| 0fa
0fb
0fc
0fd
0fe
eo 0ff
89
4.1.2 EBCDIC - Sonderzeichen
 Die Bedeutung der Sonderzeichen
Char
Description
Char
Description
Char
Description
ACK
Acknowledge
EOT
End of Transmission
PN
Punch On
BEL
Bell
ESC
Escape
RES
Restore
BS
Backspace
ETB
End of Transmission Block
RS
Reader Stop
BYP
Bypass
ETX
End of Text
SI
Shift in
CAN
Cancel
FF
Form Feed
SM
Set Mode
CC
Cursor Control
FS
Field Separator
SMM
Start of Manual Message
CR
Carriage Return
HT
Horizontal Tab
SO
Shift Out
CU1
Customer Use 1
IFS
Interchange File Separator
SOH
Start of Heading
CU2
Customer Use 2
IGS
Interchange Group Separator
SOS
Start of Significance
CU3
Customer Use 3
IL
Idle
SP
Space
DC1
Device Control 1
IRS
Interchange Record Separator
STX
Start of Text
DC2
Device Control 2
IUS
Interchange Unit Separator
SUB
Substitute
DC4
Device Control 4
LC
Lower Case
SYN
Synchronous Idle
DEL
Delete
LF
Line Feed
TM
Tape Mark
DLE
Data Link Escape
NAK
Negative Acknowledge
UC
Upper Case
DS
Digit Select
NL
New Line
VT
Vertical Tab
EM
End of Medium
NUL
Null
ENQ
Enquiry
PF
Punch Off
90
4.1.3 Unicode
 Aktuelle Version 5.0.0 (siehe auch www.unicode.org)
 Buchstaben und Symbole aus allen wichtigen geschriebenen Sprachen
der Welt




Amerika, Europa, Mittlerer Osten, Afrika, Indien, Asien, Pazifik
Symbole
Satzzeichen
Sonderzeichen
 Wird genormt in ISO/IEC 10646
 Kompatibilität mit ASCII
 0000 - 007F: identisch mit 7-bit ASCII
 007F - 00FF: Latin-1 Supplement (nationale Sonderbuchstaben)
 2500 - 25FF: Blockgraphikzeichen (Box Drawing: ╘╚╞╬└┴├...)
91
4.1.3 Unicode (www.wikipedia.org, Dez-3-06)


Unicode reserves 1,114,112 (= 220 + 216 or 17 × 216, hexadecimal 110000) code points.
As of Unicode 5.0.0, 101,063 (9.1%) of these codepoints are assigned, with another 137,468 (12.3%)
reserved for private use, leaving 875,441 (78.6%) unassigned. The number of assigned code points is
made up as follows:






The first 256 codes correspond with those of ISO 8859-1, the most popular 8-bit character encoding in
the Western world. As a result, the first 128 characters are also identical to ASCII.
The Unicode code space for characters is divided into 17 planes, each with 65,536 (= 216) code points,
although currently only a few planes are used:








98,884 graphemes
140 formatting characters
65 control characters
2,048 surrogate characters
Plane 0
Plane 1
Plane 2
Planes 3 to 13
Plane 14
Plane 15
Plane 16
(0000–FFFF):
(10000–1FFFF):
(20000–2FFFF):
(30000–DFFFF)
(E0000–EFFFF):
(F0000–FFFFF)
(100000–10FFFF)
Basic Multilingual Plane (BMP)
Supplementary Multilingual Plane (SMP)
Supplementary Ideographic Plane (SIP)
unassigned
Supplementary Special-purpose Plane (SSP)
Private Use Area (PUA)
Private Use Area (PUA)
The cap of 220 code points (excluding Plane 16) exists in order to maintain compatibility with the UTF16 encoding, which addresses only that range. Currently, about ten percent of the Unicode code space
is used. Furthermore, ranges of characters have been tentatively blocked out for every known
unencoded script, and while Unicode may need another plane for ideographic characters, there are ten
planes available if previously unknown scripts with tens of thousands of characters are discovered. This
20 bit limit is unlikely to be reached in the near future.
92
4.1.3 Unicode: Beispiele
 05F1
 FA0E
 2603
 20AC
 xxD0 - xxDF
93
4.1.3 Unicode Bereiche
Black = Latin scripts and symbols
Light Blue = Linguistic scripts
Blue = Other European scripts
Orange = Middle Eastern and SW Asian scripts
Light Orange = African scripts
Green = South Asian scripts
Purple = Southeast Asian scripts
Red = East Asian scripts
Light Red = Unified CJK Han
Yellow = Aboriginal scripts
Magenta = Symbols
Dark Grey = Diacritics
Light Grey = UTF-16 surrogates and private use
Cyan = Miscellaneous characters
White = Unused
94
4.2
Darstellung von Zahlen
 Die Darstellung von Zahlen spielt in der Informatik nach wie vor eine wichtige
Rolle. Dabei gibt es unterschiedliche Mengen von Zahlen und auch
unterschiedliche Operationen auf Zahlen.
Dieses Unterkapitel beschreibt die Grundlagen der Zahlenkodierung, gibt für
alle Mengen von Zahlen eine konkrete Kodierung an und führt in die
Computerarithmetik ein.
 Inhalt
1.
2.
3.
4.
5.
6.
7.
8.
Zahlensysteme
Konvertierung
Arithmetik
Ganze positive Zahlen
Ganze negative Zahlen
Gebrochene Zahlen
Gleitpunktzahlen
Standards
95
4.2.1 Zahlensysteme
 Nicht systematische Zahlendarstellungen, z.B.:
 Strichliste: I, II, III, IIII, IIII, IIII I, ...
 römische Zahlen:
MIM, IX, ....
 Systematische Zahlendarstellungen in einem Stellenwertsystem
 Jede Zahl N lässt sich als Sequenz von Zeichen a i darstellen
 Die Anzahl der notwendigen unterscheidbaren Zeichen ist B
 Nai* Bi
 Im Dezimalsystem ist B = 10 und die unterscheidbaren Zeichen sind:
0,1,2,3,4,5,6,7,8,9
 Im Binärsystem ist B = 2 und die unterscheidbaren Zeichen sind: 0,1
96
4.2.1 Zahlensysteme - Beispiele
 Dezimalsystem: (Basis 10)
 199910
= 1*103 + 9*102 + 9*101 + 9*100
 Binärsystem: (Basis 2)
 199910
= 1*210+1*29+1*28+1*27+1*26+1*23+1*22+1*21+1*20
111110011112
 Hexadezimalsystem (Sedezimalsystem) (Basis 16)
 Zeichen: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
 199910 = 7*162 + 12*161 + 15*160 =
7CF16 = 0x07CF = H‘07CF
 4 Zeichen einer Binärzahl lassen sich durch eine Hexadezimalziffer darstellen (4
Binärziffern nennt man auch NIBBLE)
 Oktalsystem (Basis 8)
 Zeichen: 0,1,2,3,4,5,6,7
 199910 = 3*83 + 7*82 + 1*81 + 7*80 = 37178
 3 Zeichen einer Binärzahl lassen sich durch eine Oktalziffer darstellen
97
4.2.2 Konvertierung: „Intuitivmethode“
 Addition von geeigneten Zweierpotenzen (Dezimalzahl  Dualzahl)
 positive Zweierpotenzen für Vorkommaanteil
 negative Zweierpotenzen für Nachkommaanteil
 Vorgehen (getrennt nach Vor- und Nachkommateil)
 Suche größte Zweierpotenz, die noch in die Zahl passt
 Subtrahiere die Zweipotenz von der Zahl
daraus ergibt sich die neue Zahl für die Suche der Zweierpotenz
 Dieses Vorgehen terminiert ...
 ... beim Vorkommateil: wenn die Zahl = 0
 ... beim Nachkommateil: wenn die Zahl erreicht ist, vielleicht nie
 Beispiel:
39
7
3
1
25 39 - 32 = 7
22
7-4 =3
21
3-2 =1
20
1-1 =0
0,8125
0,3125
0,0625
2-1 0,8125 - 0,5
= 0,3125
2-2 0,3125 - 0,25
= 0,0625
2-4 0,0625 - 0,0625 = 0
0,1101
100111
 39,0812510=100111,011012
98
4.2.2 Konvertierung: Restwertmethode
 Erzeugen des Hornerschemas (Ausklammern der Basis b)
c0 = anbn + an-1bn-1 + ... + a2b2 +a1b1 + a0b0 
c0 = (( ... (anb + an-1) b + ... + a2) b +a1) b + a0 
c1
c0 / b = c1 Rest a0 , mit c1= ( ... (anb + an-1) b + ... + a2) b +a1 ,
c1 / b = c2 Rest a1 , mit c2= ... (anb + an-1) b + ... + a2 ,
...
cn / b = 0 Rest an ( terminiert mit cn+1 = 0 )
 Konversion der Nachkommastellen (folgt aus Hornerschema):
1. Multiplikation mit Basis (bis ganzzahliges Ergebnis oder gewünschte Genauigkeit)
2. Abspalten der Vorkommastelle des Ergebnisses, weiter mit 1.
 Beispiel
19 : 2 =
9:2=
4:2=
2:2=
1:2=
9
4
2
1
0
Rest 1
Rest 1
Rest 0
Rest 0
Rest 1
10011
0,6875 * 2 =
0,375 * 2 =
0,75 * 2 =
0,5 * 2 =
1,375
0,75
1,5
1
1 abspalten
0 abspalten
1 abspalten
1 abspalten
0,1011
99
4.2.2 Arithmetik
 Addition
 Subtraktion
 Multiplikation
 Division
0
0
1
1
+
+
+
+
0
1
0
1
=
=
=
=
0
1
1
0 Übertrag 1
1011
+ 1110
0
0
1
1
-
0
1
0
1
=
=
=
=
0
1 Übertrag 1
1
0
1101
- 1010
0
0
1
1
*
*
*
*
0
1
0
1
=
=
=
=
0
0
0
1
1101 * 11
1101
+ 1101
100111 : 11 = 01101
100
-11
0011
-11
0011
-11
00
111
Überträge
11001
1
Überträge
0011
1 1
Überträge
100111
100
4.2.3 Ganze positive Zahlen
 Positive ganze Zahlen werden meist direkt in ihrer binären Darstellung kodiert.
 Die BCD (Binary Coded Digits) - Darstellung von Zahlen ist eine Mischform aus
Dezimal- und Binärdarstellung:




Jede Ziffer der Dezimalzahl wird binär dargestellt.
Die Darstellung jeder Ziffer erfolgt mit 4 Bits.
Die Reihenfolge der Ziffern bleibt erhalten.
Beispiele:
 7
0111
 53
0101 0011
 1234
0001 0010 0011 0100
 1999
0001 1001 1001 1001
0
1
2
3
4
5
6
7
8
9
Pseudotetraden
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
101
4.2.4 Ganze negative Zahlen: Probleme
 Darstellung des Vorzeichens im ersten Bit, z.B.
0000
0001
0010
0011
0100
0101
0110
0111
=
=
=
=
=
=
=
=
0
1
2
3
4
5
6
7
1000
1001
1010
1011
1100
1101
1110
1111
=
=
=
=
=
=
=
=
0
-1
-2
-3
-4
-5
-6
-7
 Nachteil durch Redundanz der Darstellung der 0
 Nachteil durch Probleme beim formalen Addieren
1011
+ 0001
1100
-3
+1
-4
102
4.2.4 Ganze negative Zahlen:
Zweierkomplement
 Zweierkomplementdarstellung
-2n ... +(2n-1)
 Negative Zahl durch bitweise Komplementierung und Addition von 1
(eventl. Überlauf weglassen)
 0000 = 0
Beispiel: 3
0001 = 1
1001 = -7
0011 Binärdarstellung
0010 = 2
1010 = -6
1100 Komplement
0011 = 3
1011 = -5
1101 Komplement + 1 = -3
0100 = 4
1100 = -4
0101 = 5
1101 = -3
0110 = 6
1110 = -2
0111 = 7
1111 = -1
 Vorteile
 Darstellung des Vorzeichens im ersten Bit
 Abdeckung von 16 Zahlen, also keine Redundanz
 Kein Nachteil durch Probleme beim formalen Addieren
 Subtraktion durch Addition des Zweierkomplements
-3 1101
+1 +0001
-2 1110
-1 1111
-1 +1111
-2 11110  1110
1.
2.
3.
4.
5.
Auf gleiche Länge bringen
Bitweise Komplementbildung
1 Addieren
Addieren (wie bei Binärzahlen)
Überlauf ggf. weglassen
103
4.2.5 Gebrochene Zahlen: Binärdarstellung
 Darstellung mit Vor- und Nachkommateil
 Beispiele
Gebrochene Binärzahl
0.1
0.01
111.111
0.0001 1001 1001 1001 ....
Gebrochene Dezimalzahl
0,5
0,25
7,875
0,1
 Mit 32 Bit lassen sich nur 232 verschiedene Zahlen darstellen.
 Problem: extrem große und extrem kleine Zahlen lassen sich mit wenigen Bits
nicht darstellen
 Bei 8 Bit mit 4 Vorkomma und 4 Nachkommastellen (ohne Vorzeichen):
0000.0001 < n < 1111.1111
0,0675 < n < 15,9425
104
4.2.5 Gebrochene Zahlen: Exponentialdarstellung
 Anforderung
 sehr große und sehr kleine Zahlen sollen darstellbar sein
 Masse Elektron = 9 * 10-28 g
 Anzahl Moleküle pro Mol = 6,022 * 1023
 die relativen Genauigkeiten sind wichtiger als die absoluten
 Ältere Quellen geben die Anzahl der Moleküle pro Mol mit 6,065 * 1023 an
 Eine Änderung in der Mantisse von  0,04 entspricht einer Toleranz von 6,065 /
6,022  1,0071 also ca. 0,7%.
 Fixkommadarstellung wäre große Verschwendung
 zur Darstellung dieser beiden Größen wären 194 Bit nötig
 87 Bit Vorkommateil
 107 Bit Nachkommateil
 Idee: Signifikante Stellen und Größenordnung werden getrennt
 Signifikant Masse Elektron: 9
 Größenordnung Masse Elektron: 10-28
105
4.2.5 Gleitpunktzahlen: Real Darstellung
 Darstellung durch Real-Zahlen, bestehend aus drei Teilen:
 Vorzeichenbit V
Gibt an, ob die Zahl positiv oder negativ ist
 Mantisse M
Wird mit dem Exponenten multipliziert
 Die Normalform wird erreicht, indem das Komma soweit nach links oder rechts
geschoben wird, bis die erste Stelle nach dem Dezimalpunkt die erste von Null
verschieden Ziffer ist.
Der Exponent wird entsprechend der Verschiebungen erhöht oder vermindert.
 Exponent E
Potenz einer Basiszahl (2) mit der die Mantisse multipliziert wird
 wird oft in „BIAS“-Darstellung abgelegt, d.h. wird mit 126 addiert um negatives
Vorzeichen zu vermeiden.
 Vorsicht: 126 (nicht 128).
Asymmetrisch, da 21 bei der Normalisierung zweimal geschoben wird, 2-1 gar
nicht
 Vorsicht: Bei manchen Maschinen wird so normalisiert, dass die erste Stelle vor
dem Komma gleich 1 wird, dann ist der BIAS 127
106
4.2.5 Gleitpunktzahlen: Umwandlung
 Umwandlung Dezimalzahl in binäre Gleitpunktzahl (nach IEEE 754)
 Umwandlung der Dezimalzahl in Binärzahl mit Nachkommateil
 Verschieben des Kommas nach links oder rechts bis zur Normalform
 Damit ist erste Nachkommastelle = 1 und daher redundant, kann also in der
Mantisse weggelassen werden. 2 * größere Genauigkeit der Mantisse
 Erhöhen oder Erniedrigen des Exponenten
 Umwandlung des Exponenten in binäre Form
 Addition des BIAS =12610 (um negative Exponenten zu vermeiden)
auf den Exponenten
 Das Vorzeichen der Mantisse wird bestimmt: positiv 0, negativ 1
 IEEE 754 sieht noch eine optionale Rundung der Mantisse vor
 Nicht jede gebrochene Dezimalzahl lässt sich endlich als gebrochene Binärzahl
darstellen (und umgekehrt).
 Dadurch entstehen Rundungsfehler
107
4.2.5 Gleitpunktzahlen: Beispiele
 Beispiel: 148,62510
1.
2.
Konvertieren:
Normalisieren:
3.
4.
5.
Bias addieren
Vorzeichen
Ergebnis:
10010100,101
10010100,101 = 0,10010100101*2+8 Exponent ist 8.
M
= 0010100101
(die führende 1 ist in Normalform redundant)
E
= 12610 + 810 = 13410 = 100001102
V
= 0
VEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
01000011000101001010000000000000
 Beispiel: -2,7510
1.
2.
Konvertieren:
Normalisieren:
3.
4.
5.
Bias addieren
Vorzeichen
Ergebnis:
-10,11
-10,11 = -0,1011*2+2 Exponent ist 2.
M
= 011
(die führende 1 ist in Normalform redundant)
E
= 12610 + 210 = 12810 = 100000002
V
= 1
VEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
11000000001100000000000000000000
108
4.2.5 Gleitpunktzahlen: Arithmetik
 Addition/Subtraktion
 Die Exponenten werden angeglichen, indem die Mantisse des Operanten mit dem
kleineren Absolutbetrag entsprechend verschoben wird.
 Anschließend werden die Mantissen addiert
 Beim Verschieben können Stellen verloren gehen.
 Multiplikation
 Die Mantissen der Operanten werden multipliziert
 Die Exponenten werden addiert
 Sind die Exponenten zu groß, kann es zu Exponenten-Overflow kommen
 Division
 Die Mantissen der Operanten werden dividiert
 Der Exponent ergibt sich aus der Differenz des Dividenden und Divisors
 Ist der Divisor zu klein und/oder der Dividend zu groß kann es zu einem ExponentenUnderflow kommen.
Das Ergebnis wird dann zu 0, alle Ziffern sind verloren
 Nach allen Operationen wird die Normalform ggf. wiederhergestellt
109
4.2.6 Standards





Short
Integer
Unsigned Int
LongInt
Real nach IEEE 754
-128 ... 127
-32768 ... 32767
0 ...65535
-2147483648 ... 2147483647
(8Bit)
(16Bit)
(16Bit)
(32Bit)
 Float
1 VZ-Bit, 8 Bit E, 23 Bit M
 Double
1 VZ-Bit, 11 Bit E, 52 Bit M
 zwei Varianten 0,5  M < 1 bzw. 1  M < 2
Number
(32Bit)
(64Bit)
sign
exponent
mantissa
normalized number
0/1
01 to FE
any value
denormalized number
0/1
00
any value
zero
0/1
00
0
infinity
0/1
FF
0
NaN
0/1
FF
any value but 0
110
4.2.6 Standards: Beispiel (Delphi)
 In Borlands Delphi (Pascal) sind folgende Typen festgelegt:







Typ
Real48
Single
Double
Extended
Comp
Currency
Bereich
2,9 x 10^-39
1,7 x 10^38
1,5 x 10^-45
3,4 x 10^38
5,0 x 10^-324
1,7 x 10^308
3,6 x 10^-4951
1,1 x 10^4932
-2^63+1
2*63-1
-922337203685477.5808
+922337203685477.5808
Signifikant
11-12
7-8
15-16
10-20
10-20
10-20
Größe (Byte)
6
4
8
10
8
8
 Der generische Typ Real ist in der aktuellen Implementierung mit dem Typ
Double identisch.
http://de.wikipedia.org/wiki/Borland_Delphi#Elementare_Datentypen
(7.5.2007)
111
4.3
Zusammenfassung des Kapitels
 Darstellung von Zeichen
 ASCII
 EBCDIC
 UNICODE
 Darstellung von Zahlen








Zahlensysteme
Konvertierung
Arithmetik
Ganze positive Zahlen
Ganze negative Zahlen
Gebrochene Zahlen
Gleitpunktzahlen
Standards
112
Kapitel 5 Strukturen
… da schied Gott das Licht von der Finsternis
1. Mose 1.4


Information aus der realen Welt werden in einem informationsverarbeitenden System als
Daten abgelegt. Diese stellen also eine (vereinfachte) Abstraktion der Wirklichkeit dar und
spiegeln in vielen Fällen die Strukturen der Wirklichkeit wider.
In diesem Kapitel wird ein Überblick über die wichtigsten abstrakten Datenstrukturen
gegeben, wobei dieser Begriff zum Begriff des „Datentyps“ erweitert wird.
Anmerkung: Dieses Kapitel abstrahiert die Objekte mit denen Sie in „Einführung in die
Programmierung“ umgehen. Dort werden diese abstrakten Objekte konkret für Java
vorgestellt.
Inhalt
1.
2.
3.
4.
Datenstrukturen - Datentypen
Datentypen: Ein Überblick
Konkrete Datentypen
Abstrakte Datentypen
113
5.1
Datenstrukturen - Datentypen
 In der Literatur wird meist der Begriff „Datenstruktur“ verwendet. In diesem
Unterkapitel soll der Unterschied zwischen diesem Begriff und dem Begriff des
„Datentyps“ erläutert werden.
 Inhalt
1. Datenstrukturen
2. Datentypen
3. Variablen eines Datentyps
114
5.1.1 Datenstrukturen
 In der Informatik werden Objekte der realen oder abstrakten Welt erfasst
 Bei der Erfassung beschränkt man sich möglichst auf die für den weiteren Transport
/ Speicherung/Verarbeitung/Umsetzung notwendige Information
 Zur internen Repräsentation werden diese Objekte abstrahiert
 Zur Abstraktion gehört die Erkennung von Strukturen - zunächst im Sinne einer
Aggregation.
 Also
 Aus welchen Teilobjekten bestehen Objekte ?
 In welchem Verhältnis stehen die Teilobjekte zueinander ?
 Welches sind die „atomaren“ Teilobjekte ?
 es existieren noch weitere strukturelle Beziehungen (z.B. Vererbung)
 Anschließend werden diese Objekte typisiert.
 Typisierung ist die Einteilung von abstrakten internen Objekten in Gruppen mit
gleichen oder ähnlichen Eigenschaften.
115
5.1.2 Datentypen
 Typen sind also nicht die intern repräsentierten Objekte, sondern beschreiben
die Eigenschaft einer Gruppe von Objekten.
 Zu diesen Eigenschaften gehören:






Struktur
Wertebereich
anwendbare Operatoren, Funktionen, Relationen
Beziehungen zu anderen Typen
interne Repräsentationsweise
…
Beispiel:
Imaginäre Zahlen
 Einige Anmerkungen::
 Der Begriff „Datentyp“ ist weitergehend als der Begriff „Datenstruktur“
 In der Objektorientierten Programmierung wird statt „Datentyp“ auch der Begriff
„Klasse“ verwendet (Klassen beschreiben mehr Eigenschaften)
 Konkrete Repräsentanten eines Datentyps werden (u.a) „Variable“ oder
- bei OO-Sprachen - „Instanz“ genannt
116
5.1.3 Variable eines Datentyps
 Einen speziellen (rechnerinternen) Repräsentanten eines Datentyps bezeichnet
man als Variable. Die Festlegung, von welchem Datentyp eine Variable ist,
bezeichnet man als Variablendeklaration.
 Die Zuordnung eines Typs „Typ“ an eine Variable X wird (zunächst) wie
folgt notiert:
var x : Typ;
 Eine Variable hat alle Eigenschaften eines Datentyps.
Zusätzlich dazu hat eine Variable:
 einen konkreten Wert.
 Der Wert muss aus dem Wertebereich des Datentyps sein (oder undefiniert)
 Die Zuweisung eines Wertes „Wert“ an eine Variable X sei (zunächst) wie folgt
notiert:
x = Wert;
 einen konkreten Speicherplatz
 Dieser Speicherplatz ist so dimensioniert, dass die Struktur der Variable
abgebildet werden kann
 Dieser Speicherplatz wird (meist) implizit durch die Deklaration zugeordnet
 Beispiel:
var x : Datentyp; // x ist vom Typ: „Datentyp“
x = 531;
// Zuweisung von 531 an X
117
5.2
Datentypen: Überblick
 Nachdem sich nun der Begriff des „Datentyps“ als Oberbegriff der
„Datenstruktur“ erwiesen hat, konzentrieren wir uns im Rest des Kapitels auf
wichtige Datentypen.
In diesem Unterkapitel wird ein Klassifikationssystem für die in der Informatik
verwendeten Datentypen aufgestellt und kurz erläutert
 Inhalt
1. Klassifikation der Datentypen
2. Erläuterung der Klassifikation
118
5.2.1 Klassifikation der Datentypen
Datentypen
Konkrete
Einfache
Abstrakte
Pointer(Zeiger)
Idealisierte
Strukturierte
...
Ordinale
Boolean
(Wahrheitswert)
Integer
(Ganzzahl)
Real
(Fließkomma)
Char
(Zeichen)
Array
(Feld)
Record
Union
(Verbund) (Variantenverb.)
...
Enumeration
(Aufzählung)
119
5.2.2 Erläuterung der Klassifikation
 Idealisierte Datentypen
 aus der Mathematik bekannte Datentypen: R, N, Z, ...
 Variablen dieser Typen sind oft nicht endlich darstellbar (Bsp: 2)
 In einem Computer-Algebra-System symbolisch darstellbar (Bsp: 2^( 1/2))
 Konkrete Datentypen
 in einem Rechner von Hard- oder Software bereitgestellte Datentypen
 entweder vordefiniert oder durch den Benutzer definierbar
 Abstrakte Datentypen
 verbergen ihren inneren Aufbau vor dem Benutzer
 bestehen aus beliebigen Strukturen über konkrete/idealisierte Datentypen, sowie aus
Zugriffsfunktionen bzw. Prozeduren
 Beispiel: Baum
13
insert (Element)
6
2
61
12
15
delete (Element)
79
search (Element)
120
5.3
Konkrete Datentypen
 Die am häufigsten abstrahierten Objekte der realen Welt sind, zumindest was
die für eine weitere Verarbeitung notwendigen Informationen betrifft, einfach
strukturiert und lassen sich demnach mit konkreten Datentypen abbilden.
Dieses Unterkapitel gibt einen Überblick über alle konkreten Datentypen und
beschreibt diese.
 Inhalt
1. Einfache Datentypen
2. Strukturierte Datentypen
3. Verweise
121
5.3.1 Einfache: Boolean (Wahrheitswert)
 zur Darstellung von Wahrheitswerten
 Wertebereich: true, false
 intern in manchen Programmiersprachen als 1 bzw. 0 dargestellt
 Operatoren: und, oder, nicht, Vergleiche, ...
 Operatoren entsprechend der bool‘schen Algebra
 oft auch allgemeine arithmetische Operationen möglich
 Vorsicht vor Integer-Arithmetik mit Boolean-Variablen
 Notation:
 Beispiel:
var booleanVar : boolean;
var switch : boolean;
switch = false;
switch = not(switch);
switch = switch and not(switch);
switch = switch or not (switch);
//
//
//
//
=
=
=
=
0 „Bool-Literal“
not(0) = 1
1 and 0 = 0
0 or 1 = 1
Wir müssen uns gleich angewöhnen die „Dinge“ so zu bezeichnen, wie sie in der Informatik
bezeichnet werden:
Schlüsselwort var (Variablen)Bezeichner switch Schlüsselzeichen(-wort) :
(Typ)Bezeichner boolean Schlüsselzeichen(-wort);
Bezeichner switch Operator = (Boolean)Literal false Schlüsselzeichen(-wort);
122
5.3.1 Einfache: Integer (Ganzzahl)
 zur Darstellung ganzer Zahlen mit oder ohne Vorzeichen
 Wertebereich: Unterschiedlich
 unsigned integer: Ganze Zahlen ohne Vorzeichen ( 0... 65535 )
 oft 16 bit bzw. 32 bit als ‚short int‘ bzw. ‚long int‘ bezeichnet
 Vorsicht:
16 bit Integer ist verdammt wenig ((± 32267)
Speicherplatz ist nicht mehr teuer  benutzen Sie ‚long int‘
(Ausnahmen bestätigen die Regel)
 Operatoren: Grundrechenarten, Vergleiche
 Operatoren entsprechend der „klassischen“ Algebra
 Notation:
 Beispiel:
var integerVar : integer;
var
i =
i =
i =
i =
i :
1;
i +
i /
i +
integer;
32;´
17;
65535;
//
//
//
//
= 1 „Integer-Literal“
= 1 + 32 = 33
= 33 / 17 = 1 !
bei unsigned Int.: Fehler !
123
5.3.1 Einfache: Char (Zeichen)
 zur Darstellung von Zeichen
 Vorsicht:
Typischerweise wird die ASCII-Codierung zugrundegelegt,
kann aber auch Unicode sein
 Wertebereich: Alle Zeichen
 Intern codiert als ASCII oder - neuerdings immer öfter - als Unicode
ASCII: 8 Bit (7 benutzt), Unicode: 16 Bit
 Intern oft als Integer repräsentiert
 Operationen: Vergleich
 oft auch allgemeine arithmetische Operationen möglich
 Vorsicht vor Integer-Arithmetik mit char-Variablen
 Notation:
 Beispiel:
var charVar : char;
var symbol : char;
symbol = „A“;
symbol = symbol + 32;´
symbol = symbol - 128;
// = „A“ „Char-Literal“
// = „A“ + 32 = „a“
// = „a“ - 128 = Fehler
124
5.3.1 Einfache: Enum (Aufzählung)
 zur Darstellung endlicher benutzerdefinierter Wertebereich
 Es ist guter Stil, Mengen mit (garantiert) kleiner Mächtigkeit (<10) als Enum-Type zu
deklarieren, anstatt sie z.B. als Integer zu kodieren.
 Intern werden Enum-Werte oft als Integer abgelegt
 Operatoren: Vergleich
 oft auch allgemeine arithmetische Operationen möglich
 Vorsicht vor Integer-Arithmetik mit Enum-Variablen
 Notation:
 Beispiel:
var enumVar : enum { Wertemenge };
var ampelfarbe : enum {gruen,gelb,rot} ;
ampelfarbe = gruen;
// = gruen „Enum-Literal“
// Vorsicht: C++ erlaubt das
ampelfarbe = ampelfarbe +1 ; ´ // = gruen + 1 = gelb
ampelfarbe = ampelfarbe +1 ; ´ // = gelb + 1 = rot
ampelfarbe = ampelfarbe +1 ; ´ // = rot + 1 = Fehler !
125
5.3.1 Einfache: Real (Fließkomma)
 zur näherungsweisen Darstellung reeller Zahlen
 Wertebereich: Unterschiedliche Genauigkeiten und Wertebereiche
 Wertebereich entspricht typischerweise der IEEE 754 Norm, also:
 Float: 32 bit
 Double: 64 bit
 Operationen: Grundrechenarten, erweiterte Arithmetik, Vergleich
 Notation: var realVar : real;
 Beispiel: //--- Variable declaration -------------------------var pi, flaeche, radius : real;
// all real !
//--- Initialisation -------------------------------pi
= 3,141; // needs not to be more accurate
radius = 5;
// might be changed by user
//--- Computation of surface -----------------------flaeche = 2 * pi * (radius ^ 2);
// common formula
126
5.3.2 Strukturierte: Array (Feld)
 Arrays sind eine Aggregationen von Daten des gleichen Typs
(des „Basistyps“) Aggregation := Zusammenfassung, Anhäufung, Angliederung
 Die Grenzen des Arrays sind (meist) statisch bestimmt
 Operation: Auswahl
 Die Auswahl eines Datenelementes erfolgt über einen ganzzahligen Index über den
(Auswahl-)Operator „ [ ] “
 Vorsicht: Zugriff außerhalb des deklarierten Bereiches führt zu Fehlern
 Notation:
 Beispiele
var arrayVar : array[min .. max] of Datentyp
 Eindimensionales array:
 Zweidimensionales array:
var Vektor : array[1..4] of real;
 Operator
var m : array[1..3]
array[1..2]
var v : array[1..4]
v[3] = 5,03; v[4] =
m[1][2] = v[3] * 12
var Matrix : array[1..3] of
array[1..2] of real;
of
of real;
of real;
4,12;
- v[4];
127
5.3.2 Strukturierte: Record (Verbund)
 Verbunde sind Aggregationen von Daten möglicherweise unter-schiedlichen
Typs
 manchmal auch „structure“ oder „struct“ genannt
 Operation: Auswahl
 Die Auswahl erfolgt durch Angabe des Komponentennamens
(durch einen Punkt vom Variablennamen getrennt)
 Notation:
var recordVar : record
{
komponent1 : type1;
...
};
 Beispiel:
var d :
{
tag
monat
};
d.monat
d.tag
record
: Integer;
: Integer;
= 10;
= 20;
128
5.3.2 Strukturierte: Variant Record (Variantenverb.)
 Verbunde, deren Struktur mögliche Alternativen zulassen
 manchmal auch „union“ genannt
 lassen „Varianten“ eines Record-Types zu
 Operation: Auswahl (wie bei records über Punkt-Operator)
 Notation: var recVar :
record {
komponent1 : type_1;
...;
case variant (variant1,...) of {
variant1 : type_n;
...
}
TAGGED TYPE
}


Unterelement „variant“ implizit definiert bei „tagged type“
Nur ein Unterelement aus variant1, ... (sinnvoll) verwendbar
 Beispiel:
var adam,eva : record {
name : array [1..20] of char;
case sex (m,f) of {
f: {IQ: integer};
m: {muscle: real}; // in cm
}
adam.sex
adam.muscle
eva.sex
eva.IQ
=
=
=
=
m;
20,5;
f;
132;
129
5.3.2 Strukturierte: Variant Record


var adam,eva : record
name
case
f:
m:
}
adam.sex
adam.muscle
eva.sex
eva.IQ
=
=
=
=
m;
20,5;
f;
132;
Umsetzung:
name

{
: array [1..20] of char;
sex (m,f) of {
{IQ: integer;}
{muscle: real;}}
sex IQ /
muscle
Variant Records mit „Untagged Types“ (z.B. C, C++ : Union)
struct {
char[20] name;
enum {m,f} sex; // ...
union {
int IQ;
real muscle;} // in cm
} adam, eva;
(2. Variante)
adam.sex
adam.muscle
eva.sex
eva.IQ
=
=
=
=
m;
20,5;
f;
132;
130
5.3.2 Vereinfachung der Notation („type“)

var Person : record { surname : array [1..20] of char;
forename : array [1..20] of char;
birthday : record { year : integer;
month : enum {jan,...};
day
: integer; };
};
var Akt_Datum : record { year : integer;
month : enum {jan,feb,...};
day
: integer; };
 In (fast) allen Programmiersprachen ist es möglich, beliebig strukturierte
Datentypen neu zu bezeichnen und diese Typ-Bezeichner wie vordefinierte
Typen zu verwenden:
 Notation:
 Beispiel:
type NeuTyp : Typ;
type Datum : record { year : integer;
month : enum {jan,feb,...};
day
: integer; };
var Person: record {surname : array [1..20] of char;
forename : array [1..20] of char;
birthday : Datum };
var Akt_Datum: Datum;
131
5.3.3 Pointer (Zeiger, Verweis)
 Zeiger-Datentypen sind durch folgende Eigenschaften gekennzeichnet:
 Die Struktur ist identisch der eines Integer-Datentyp (also oft 16,32,... Bit)
 Der Wertebereich ist der des Adressbereiches eines Rechnersystems,
der zusätzliche Wert „nil“ bezeichnet einen ungültigen Zeiger.
 Operatoren sind:
 Erzeugen eines Zeigers (Referenzierung &)
 Zugriff auf verwiesenen Bereich (Dereferenzierung *)
 Integer-Operatoren (Vorsicht !!!!)
 Notation:
 Beispiel:
var pointerVar : *Type;
var x : *Integer;
// Deklaration
var y,z : Integer;
// Deklarationen
y = 5; // Initialisierung der Variablen y
x = &y; // Referenzieren: x ist Zeiger auf y
x* = 2; // Derefenzierung: das worauf x zeigt
wird zu 2
z = y; // Variable z bekommt den Wert von
Variable y zugewiesen.
// z hat jetzt den Wert 2
132
5.3.3 Pointer: Beispiel
Vorsicht:: Werte oft undefiniert
 Bsp.: x : *Integer; // Deklaration
y : Integer;
// Deklaration
1 2 3 4 5 6 7 8 9
23 24 25 26 27 28
Wortadressen
nil
0
...
y = 5; // Initialisierung der Variablen y
1 2 3 4 5 6 7 8 9
23 24 25 26 27 28
nil
5
...
x = &y; // Referenzieren: x ist Zeiger auf y
1 2 3 4 5 6 7 8 9
23 24 25 26 27 28
25
5
...
x* = 2; // Dereferenzierung: das worauf x zeigt
1 2 3 4 5 6 7 8 9
23 24 25 26 27 28
25
2
...
x = 2; // Zuweisung ohne Dereferenzierung !
1 2 3 4 5 6 7 8 9
23 24 25 26 27 28
2
2
...
133
5.3.3 Pointer: Dynamische Datentypen
 Mit konkreten, d.h. einfachen und strukturierten Datentypen lassen sich nur
statische Struktur aufbauen
 d.h. Strukturen, deren Speicherbedarf beliebig aber fest sind
 Bem.: Die Beliebigkeit ist begrenzt durch die Gesamtspeicherkapazität
 Mit Zeiger-Datentypen lassen sich Strukturen aufbauen, die sich dynamisch
auf- und abbauen lassen
 d.h. Strukturen, deren Speicherbedarf sich dynamisch verändern kann
 d.h. der Speicherplatz muss auch dynamisch organisiert werden.
 Bem.: Auch hier ist die Beliebigkeit begrenzt durch die Gesamtspeicher-kapazität
 Beispiel:
type knoten : record
{
symbol : char;
links : *knoten;
rechts : *knoten;
}
var wurzel : knoten
Huffman
(Bsp. aus Kap.2)
B
C
E
D
A
134
5.3.4 Beispiel: Kombinierte Datentypen
 Um nun beliebig komplexe Strukturen der „realen“ Welt in einem Rechensystem
abbilden zu können, kann man die vorgestellten Datentypen beliebig
miteinander Kombinieren
 Beispiel.:
type Person : record {
surname : array [1..20] of char;
forename : array [1..20] of char;
birthday : Date;
next
: *Person;
previous : *Person;
}
type Date
year :
month :
day
:
}
: record {
integer;
enum {jan,feb,...};
integer;
135
5.4
Abstrakte Datentypen
 Grundsätzlich lassen sich alle Objekte der realen Welt ausschließlich mit Hilfe
einfacher Datentypen abbilden. Diese Abbildung ist aber meist „unnatürlich“,
weil sie die Struktur realer Objekte nicht ausreichend berücksichtigt. Abhilfe
schaffen hier strukturierte Datentypen, die allerdings grundsätzlich nur endliche
Objektmengen repräsentieren können. Hier schaffen Zeigertypen Abhilfe.
 Kann man nun mit diesen Mitteln Strukturen realer Objekt natürlich abbilden, so
fehlen diesen abstrakten Datentypen einige der Eigenschaften, die konkreten
Datentypen von Datenstrukturen unterscheiden, dies sind insb.
 Operationen und
 Beziehungen zu anderen Typen.
 Einen vertieften Einblick in die bunte Welt abstrakter Datentypen bietet die
Vorlesung des 2. Semesters
Datenstrukturen
136
5.5
Zusammenfassung des Kapitels
Datentypen
Konkrete
Einfache
Abstrakte
Pointer(Zeiger)
Idealisierte
Strukturierte
...
Ordinale
Real
(Fließkomma)
Array Record Union
(Feld) (Verbund) (Variantenverb.)
...
Enumeration
Boolean
Integer
Char
(Wahrheitswert) (Ganzzahl) (Zeichen) (Aufzählung)
 Wir sind damit auch an die Grenzen dessen gelangt, was in dieser Vorlesung
über die „Statik“ von Objekten gesagt werden soll und wenden uns einem noch
spannenderem Themenbereich zu ;-)
137
Kapitel 6 Algorithmus
… und Vögel sollen fliegen auf Erden
1. Mose 1.20


In den vorangegangenen Kapiteln wurde, aufbauend auf dem Begriff der Information,
beschrieben, wie die statischen Objekte der Informatik aussehen und notiert werden
können.
In diesem Kapitel wird aufgezeigt, wie man die Verarbeitung dieser Objekte (also die
Dynamik) beschreiben kann. Wesentlicher Begriff dabei ist der Begriff des Algorithmus
Inhalt
1.
2.
3.
4.
5.
6.
7.
Ein Beispiel
Definition
Die Strukturelemente
Strukturierung
Blockung
Iteration und Rekursion
Zusammenfassung
Teile dieses Kapitels sind aus:
R.Manthey: Vorlesung Informatik 1, Uni Bonn,138
2001
6.1
Ein Beispiel
 Zunächst soll ein kleines Beispiel in eine mögliche Aufgabenstellung aus dem
(bekannten) Bereich der Mathematik einführen und dadurch auch eine
(eingeschränkte) Vorstellung über die Aufgaben und Elemente eines
Algorithmuses geben.
 Inhalt
1.
2.
3.
4.
5.
6.
7.
Das Problem (Beispiel)
Ein Algorithmus I
Ein Algorithmus II
Vergleich der Algorithmen
Ein Algorithmus III
Fragestellungen
Ein weiterer Algorithmus
139
6.1.1 Das Problem
 Eine quadratischen Gleichung:
x2 + 8x + 7 = 0
 Allgemeine Darstellung der quadratischen Gleichung
x2 + px + q = 0
 Allgemeine Lösung der quadratischen Gleichung
x1,2= -p/2 +- p2/4 - q
 Lösung der quadratischen Gleichung
x1,2 = -8/2 += -4
+
82/4 - 7
- 3
x1 = -1
x2 = -7
140
x1,2= -p/2 +- p2/4 - q
6.1.3 Ein Algorithmus I
 Ein Algorithmus
Zuweisungen
Berechnungen
Eingaben
1. Lies die Zahlen p und q ein
2. Berechne die Zahl w = p2/4 - q
Konstante
3. Berechne die Zahl x1 = -p/2 + w
4. Berechne die Zahl x2 = -p/2 - w
5. Gib x1 und x2 als Ergebniss aus
Ausgaben
Variable
141
6.1.4 Ein Algorithmus II
x1,2= -p/2 +- p2/4 - q
 Ein zweiter Algorithmus
1. Lies die Zahlen p und q ein
2. Berechne die Zahl p/2; Nenne diese Zahl a
3. Berechne die Zahl a2 ; Nenne diese Zahl b
4. Berechne die Zahl b-q ; Nenne diese Zahl c
5. Berechne die Zahl c ; Nenne diese Zahl d
6. Berechne die Zahl -a ; Nenne diese Zahl e
7. Berechne die Zahl e + d ; Nenne diese Zahl x1
8. Berechne die Zahl e - d ; Nenne diese Zahl x2
9. Gib x1 und x2 als Ergebniss aus
FHSymbol1
Es gibt (oft unendlich) viele Algorithmen zur
Lösung eines Problems
142
6.1.5 Vergleich der Algorithmen
Berechne die Zahl w = p2/4 - q
Berechne die Zahl p/2; Nenne diese Zahl a
Berechne die Zahl x1 = -p/2 + w
Berechne die Zahl a2 ; Nenne diese Zahl b
Berechne die Zahl x2 = -p/2 - w
Berechne die Zahl b-q ; Nenne diese Zahl c
Berechne die Zahl c ; Nenne diese Zahl d
Berechne die Zahl -a ; Nenne diese Zahl e
Berechne die Zahl e + d ; Nenne diese Zahl x1
Berechne die Zahl e - d ; Nenne diese Zahl x2
Anzahl Berechnungen
Anzahl Zuweisungen
Anzahl Variablen
A1
10
3
5
A2
7
7
9
FHSymbol1
Welcher
Algorithmus
ist besser ?
Warum ?
143
6.1.6 Ein Algorithmus III
 Problem: Negatives Wurzelargument
1.
Lies die Zahlen p und q ein
2.
Berechne die Zahl a = p/2
3.
Berechne die Zahl b = a2
4.
Berechne die Zahl c = b-q
5.a Wenn c negativ ist brich den
Algorithmus ab
Ansonsten mache mit nächstem
Schritt weiter
6.
Berechne die Zahl d = c
7.
Berechne die Zahl e = -a
8.
Berechne die Zahl x1 = e + d 1
9.
Berechne die Zahl x2 = e - d
5.b Wenn c negativ ist
gehe zu Schritt 1
Bedingte
Ausführung
Schleife
10. Gib x1 und x2 als Ergebniss aus
144
6.1.7 Fragestellungen
1.
Lies die Zahlen p und q ein
2.
Berechne die Zahl a = p/2
3.
Berechne die Zahl b = a2
4.
Berechne die Zahl c = b-q
6.
Berechne die Zahl d = c
7.
Berechne die Zahl e = -a
8.
Berechne die Zahl x1 = e + d 1
9.
Berechne die Zahl x2 = e - d
10. Gib x1 und x2 als Ergebniss aus
 Wer gibt p und q ein ?
 Wie wird p und q eingegeben ?
 Werden p und q in endlicher Zeit
eingegeben ?
 Sind p und q im richtigen Format ?
 Ist Variable a im richtigen Format ?
 Gibt es die Quadrat-Funktion ?
 Ist c positiv ?
 Ist Variable e im richtigen Format ?
 Sind die restlichen Variablen im
richtigen Format
 Reicht die Genauigkeit der Darstellung
?
 Wo wird das Ergebnis ausgegeben ?
 Ist ausreichend Variablenkapazität für
den Algorithmus vorhanden ?
 Läuft der Algorithmus schnell genug ?
 ...
145
6.1.8 Ein weiterer Algorithmus
146
6.2
Definition
 Der Begriff des Algorithmus ist zentral in der Informatik und soll in diesem
Unterkapitel formal definiert werden
 Inhalt
1.
2.
3.
4.
5.
Herkunft
Der Algorithmus
Weitere Prinzipien
Algorithmen und Programme
Ausflug: Algorithmus und WinOSe
147
6.2.1 Herkunft
 Muhammad ibn Musa abu Djafar al-Choresmi (ca. 780-850 n.Chr)
 arabischer Mathematiker, geboren in Choresmien (heute: Usbekistan)
 lebte und wirkte in Bagdad im „Haus der Weisheit“
(Noah Gordon: „Der Medicus“)
 war beteiligt an der Übersetzung der Werke griechischer Mathematiker
ins Arabische
 schrieb ein „Kurzgefasstes Lehrbuch für die Berechnung durch
Vergleich und Reduktion“
 die lateinische Übersetzung dieses Buches („liber algorismi“) kam durch
Kreuzfahrer nach Europa
 verfasste auch ein Buch mit dem Titel „Al-Mukhtasar fi Hisab al-Jahr va
l-Muqabala“
Algorithmus
Algebra
148
6.2.2 Der Algorithmus: Definition

Ein Algorithmus (algorithm) ist die Beschreibung eines Verfahrens, um aus gewissen
Eingabegrößen bestimmte Ausgabegrößen zu berechnen.
Dabei müssen folgende Bedingungen erfüllt sein
 Spezifikation
 Es muss spezifiziert sein, welche Eingabegrößen erforderlich sind und welchen
Anforderungen diese Größen genügen müssen, damit das Verfahren funktioniert
(Eingabespezifikation)
 und welche Ausgabegrößen bzw. Resultate) mit welchen Eigenschaften berechnet werden
(Ausgabespezifikation)
 Durchführbarkeit
 Endliche Beschreibung: das Verfahren muss in einem endlichen Text vollständig
beschrieben sein
 Effektivität: Jeder Schritt des Verfahrens muss effektiv (d.h. tatsächlich) „mechanisch“
ausführbar sein. (Bem.: „Effektivität“ ist nicht zu verwechseln mit „Effizienz =
Wirtschaftlichkeit“)
 Determiniertheit: Der Verfahrensablauf ist zu jedem Zeitpunkt fest vorgeschrieben
 Korrektheit
 partielle Korrektheit: Jedes berechnete Ergebnis genügt der Ausgabespezifikation, sofern
die Eingaben der Eingabespezifikation genügt haben
 Terminierung: Der Algorithmus hält nach endlich vielen Schritten mit einem Ergebnis an,
sofern die Eingaben der Eingabespezifikation genügt haben

Algorithmen, die eine oder mehrere dieser Eigenschaften nicht besitzen werden dann als
Nicht-<Eigenschaft> Algorithmen bezeichnet (Bsp: Nicht-Deterministische Algorithmen)149
6.2.3 Weitere Prinzipien
 Neben den in der Definition angegebenen Eigenschaften gibt es weitere
wichtige Prinzipien, die bei der Erstellung eines Algorithmussees zu beachten
sind:
 Effizienz
 Der Algorithmus soll möglichst wenig Aufwand verursachen
– Das Ergebnis mit möglichst wenig Rechenschritten (oder mit möglichst wenig
Speicherbedarf) erzielen
 Wartbarkeit
 Ein Algorithmus sollte so verständlich sein, dass ihn Personen, die ihn nicht
entwickelt haben zumindest so weit verstehen, umm ggf. Fehler zu beheben
 Erweiterbarkeit
 Unter Erweiterbarkeit versteht man die Anwendbarkeit eines Algorithmus auch
für Anwendungen, die zunächst nicht vorgesehen sind. Man sollte daher bei der
Eingabespezifikation von Spezialfällen abstrahieren.
 Robustheit
 Unter Robustheit versteht man „gutartiges“ Verhalten auch für Eingabewerte
außerhalb der Eingabespezifikation, Man sollte daher die Eingabemenge der
Eingabespezifikation gleich möglichst so definieren, dass auch „exotischere“
Eingabewerte betrachtet werden..
150
6.2.4 Algorithmen und Programme: Der Weg
Algorithmierung
Programmierung
Problem
Algorithmus
Programm
Spezifizieren
Verifizieren
Testen
 gegeben: das Problem
 durch Spezifizieren wird das Problem formal beschrieben
 Durch Algorithmierung (Algorithmenentwurf) wird ein Algorithmus erzeugt
 durch Verifizieren kann der Algorithmus auf Übereinstimmung mit der Spezifikation
überprüft werden
 Durch Programmieren wird aus den Algorithmus ein Programm erzeugt
 durch Testen kann das Programm auf Übereinstimmung mit der Spezifikation und
dem Algorithmus überprüft werden.
151
6.2.4 Algorithmen und Programme:
Beziehungen
Algorithmierung
Problem

Programmierung
Algorithmus
Programm
Programmieren setzt Algorithmenentwicklung voraus
 Kein Programm ohne Algorithmus !


Jedes Programm repräsentiert einen bestimmten Algorithmus.
Ein Algorithmus kann durch viele Programme repräsentiert werden.
Problem
Algorithmus1
Algorithmus2
Programm21
Programm22
...
...
152
6.2.5 Ausflug: Algorithmus und WinOSe
Klassische
Programmierung
Windows
Programmierung
OS
Eventqueue
Algorithmus
OS
153
6.3
Strukturelemente
 Um die Dynamik - also die Abfolge von Aktionen - eines Algorithmu-ssees zu
beschreiben, benötigt man formale Beschreibungsmittel, sowie eine
Festlegung, wie diese Beschreibungsmittel zu notieren und zu interpretieren
sind.
Dieses Unterkapitel stellt die formalen Beschreibungsmittel für Algorithmen
vor. Diese Beschreibungsmittel sind dabei gleichzeitig
Strukturierungselemente für Algorithmen, denn sie definieren die Struktur von
Algorithmen.
 Inhalt:
1.
2.
3.
4.
Die Elemente
Folge
Auswahl
Wiederholung
154
6.3.1 Die Elemente: Aus dem Beispiel
EINGABE



Zuweisungen
Berechnungen
 Mathematische Grundoperationen
 komplexe Funktionen
 ...



Bedingte Ausführungen
Schleife
...
Variable
 Texte
 Zahlen ...

Konstanten
(Literale)
 Texte
 Zahlen ...
AUSGABE
155
6.3.1 Die Elemente: Notation
 Für die Beschreibung von Algorithmen gibt es viele Möglichkeiten
 Alltagssprache
 Konkrete Programmiersprache
 Dazwischen gibt es eine Vielzahl von Notationen, die den Übergang zwischen
Problembeschreibung und Programm erleichtern sollen
 Eine mögliche - eindimensionale - Notation ist Pseudocode:
 // Dies ist eine Zuweisung
x = 42;
 Kommentare werden (hier) mit vorangestellten Slashes „//“ gekennzeichnet
 Aktionen werden (hier) mit Semikolon „;“ getrennt
 Visualisierung durch graphische - zweidimensionale -Notation
 Flussdiagramme
 Struktogramme (=Nassi-Shneiderman-Diagramme)
Aktion
Aktion
156
6.3.1 Die Elemente: atomare Elemente
 Anweisungen sind die atomaren Elemente eines Algorithmus‘, die Elemente
also, aus denen ein Algorithmus aufgebaut ist.
 Es gibt (zunächst) drei Arten dieser „atomaren“ Elemente
 Zuweisung:
 Pseudocode
x = y;
 Auf der linken Seite der Zuweisung steht eine Variable auf der rechten Seite der
Zuweisung steht entweder eine Variable, ein Literal oder eine Berechnung aus
Variablen und Literalen
 Eingabe
 Pseudocode: x << <Eingabegerät> ;
 Als Eingabegerät kann ein geeignetes physikalisches Gerät (Tastatur,
Schnittstelle, ...) angegeben werden.
 Ausgabe
 Pseudocode: x >> <Ausgabegerät> ;
 Als Ausgabegerät kann ein geeignetes physikalisches Gerät (Bildschirm,
Drucker, Schnittstelle, ...) angegeben werden
 Ein- und Ausgabe können auch als Zuweisung verstanden werden.
157
6.3.1 Die Elemente: Kontrollelemente
 Die atomaren Elemente eines Algorithmussees können durch drei einfache
Strukturierungsmethoden, den „Kontrollelementen“, zueinander in Beziehung
gesetzt werden:
1. Folge (Sequenz)
2. Auswahl (Selektion, Fallunterscheidung)
3. Wiederholung (Iteration, Schleife)
 Die Kontrollelemente bestimmen die Reihenfolge von Aktionen in Algorithmen
 Eine Aktion (Ai) - auch Verarbeitung genannt - ist ein atomares Element oder
eine durch die Strukturmethoden zusammengefasste Menge mehrerer Aktionen
158
6.3.2 Folge
 Folgen bestimmen die lineare Reihenfolge von Aktionen in Algorithmen:
 Flussdiagramm
Struktogramm
Pseudocode:
A1
A2
..
.
A1
A2
{
..
.
An
}
A1;
A2;
...
An;
An
159
6.3.3 Auswahl : bedingte Verarbeitung
 Eine Aktion wird, in Abhängigkeit einer bool‘schen Bedingung ausgeführt oder
nicht
 auch „einarmiges if“ genannt.
 Flussdiagramm
Struktogramm
Pseudocode:
f
B
w
w
B
f
if B then A1;
A1
A1
 Beispiel:
if (x<0) then x = -x;
160
6.3.3 Auswahl : einfache Alternative
 In Abhängigkeit einer bool‘schen Bedingung wird entweder eine Aktion oder
eine andere Aktion ausgeführt
 auch „zweiarmiges if“ genannt.
 Flussdiagramm
w
B
Struktogramm
f
w
A1
A1
 Beispiel:
Pseudocode
B
f
A2
if B then A1
else A2;
A2
if (x<0) then x=-x else x=0;
161
6.3.3 Auswahl : mehrfache Alternative
 In Abhängigkeit einer Bedingung (mit mehreren möglichen Werten w1, w2, ...,
wn) wird eine Aktion aus einer Menge möglicher Aktionen ausgewählt und
ausgeführt
 Flussdiagramm
Struktogramm
Pseudocode
B
w1
w2
A1 A2
 Beispiel:
w1
wn
B
A1 A2
wn
An
An
switch
{
case
case
...
case
}
B:
w1: A1;
w2: A2;
wn: An;
switch x: {
case 0: x = x/2;
case 1: x = x+1;
}
 Oft auch mit „else“-Alternative (statt wn)
162
6.3.4 Schleife: mit vorausgehender Prüfung
 Solange eine bool‘sche Bedingung erfüllt ist, wird eine Aktion ausgeführt.
 Die Bedingung wird vor der ersten Ausführung der Aktion geprüft
 heißt auch: abweisende Schleife (While-Schleife)
 Flussdiagramm
Struktogramm
f
B
B
A1
w
A1
 Beispiel:
Pseudocode
while B
{
A1
}
while x < 100 {
x = x + 1;
}
163
6.3.4 Schleife: mit nachfolgender Prüfung
 Solange eine bool‘sche Bedingung nicht erfüllt ist, wird eine Aktion ausgeführt.
 Die Bedingung wird (erst) nach der ersten Ausführung der Aktion geprüft
 heißt auch: Repeat-Schleife
 Manchmal auch als Variante „Do-While-Schleife“ - z.B. in C++ - aber:
Die „ Do-While-Schleife“ wird solange ausgeführt solange eine bool‘sche Bedingung
erfüllt ist.
 Flussdiagramm
A1
B
Struktogramm
B
w
A1
Pseudocode
repeat
{
A1
} until B
f
 Beispiel:
repeat { x = x + 1; } until x == 100
164
6.3.4 Schleife: Beispiel (abweisende Schleife)
 Untersuche ob eine gegebene natürliche Zahl Primzahl ist.
 p > 2 ist Primzahl, falls sie durch kein t mit 1<t<p teilbar ist (p mod t  0)
 Idee:
 wenn p Primzahl, dann ist p ungerade
 es genügt, nur ungerade t zu untersuchen
 es genügt, nur solche t zu untersuchen die kleiner p sind,
 Algorithmus:
p << Tastatur;
if ((p>2) and (p mod 2 != 0)) then {
t = 3; // initialize t
while ((t*t<p) and (p mod t != 0)) {
t = t + 2;
} // nach Schleife ist t*t >=p oder p mod t == 0
if (t*t>p) then „p ist Primzahl“ >> Bildschirm;
else „p ist keine Primzahl“ >> Bildschirm;
}
else
{ „p <= 2 oder p gerade“ >> Bildschirm; } // Primzahl ?
165
6.3.4 Schleife: Beispiel (Vergleich while  repeat)
 Sind diese Schleifen im Ergebnis identisch ?
while x < 100
{
x = x + 1;
}
 und jetzt ?
 Letzer Versuch:
repeat
{
x = x + 1;
} until x < 100
repeat
{
x = x + 1;
} until x >= 100
if (x < 100) then {
repeat {
x = x + 1;
} until x >= 100
}
 Welche Lösung ist eleganter ?
 aber: oft wird eine erstmalige Aktion benötigt, um ein Datum überhaupt überprüfen zu
können.
166
6.3.4 Schleife: Beispiel (Vergleich repeat  while)
 Ausdrucken einer Datei
repeat
{
x << Datei;
if (x != eof) x >> Drucker;
} until x == eof //endoffile
 ... das Ganze als while-Schleife ?
while (x != eof )
{
x << Datei;
x >> Drucker;
}
 Noch‘n Versuch:
x << Datei;
while (x != eof )
{
x >> Drucker;
x << Datei;
}
167
6.3.4 Schleife: Beispiel (Schleife mit Zählern)
 Sehr häufig werden Schleifen verwendet, deren Bedingung abhängig von
Zählerwerten sind.
 Die Zählerwerte werden vor Eintritt in die Schleife initialisiert
 Die Bedingung prüft den Zählerwert
 Im Schleifenkörper wird der Zähler erhöht (increase) oder erniedrigt (decrease)
 Vorsicht mit: dem Zählertyp, dem Additionswert, der Bedingung
 Algorithmus:
// --- Initialisierung -----------------------------s = 0;
i = 1; // Initialisierung des Schleifenzählers
// --- Schleife (Berechnet Summe 1..n) ------------while ( i <= n )
{
s = s + i;
i = i + 1; // Erhöhung des Schleifenzählers (oft um 1)
}
168
6.2.4 Schleife: Die „For“-Schleife
 Da Schleifen mit Zähler sehr häufig auftreten, stellen viele
Programmiersprachen ein eigenes sprachliches Mittel dafür zur Verfügung: Die
„For“ Schleife
 Pseudocode:
Beispiel:
for var=start_value to end_value
for i=1 to 10
{
{
A;
x = x + i;
}
}
 Der Zähler (var) wird pro Schleifendurchlauf implizit um 1 erhöht
(Bei manchen Sprachen - z.B. Basic, C, C++ - kann man dies ändern)
 Dieser Code ist äquivalent mit folgender Schleife:
i = start_value
while i <= end_value
{
A;
i = i+1;
}
169
6.3.4 Schleife: Beispiel (Endlosschleife)
 Manchmal macht es Sinn, Schleifen endlos laufen zu lassen:
 z.B. bei der zyklischen Abprüfung von Systemzuständen (Windows Event-Queue)
 manchmal macht das keinen Sinn - passiert aber trotzdem ;-)
 Flussdiagramm
Struktogramm
B
A1
A1
 Beispiel:
Pseudocode
while true
{
A1
}
while true {
„Druckerpapier ist teuer“ >> Drucker;
}
170
6.4
Strukturierung
 Mit Hilfe atomarer Elemente und der Kontrollelemente lassen sich Algorithmen
strukturieren. In diesem Kapitel sind einige Begriffe zur Strukturierung erläutert.
Insbesondere wird ein weiteres - viertes - Kontrollelement vorgestellt (und auch
gleich wieder verworfen)
 Inhalt
1.
2.
3.
4.
Control Flow
Strukturierung durch Sprung
Strukturiert-iterative Beschreibungsform
Strukturierungstypen
171
6.4.1 Control Flow
 Mithilfe der Kontrollelemente können die „atomaren“ Elemente (Anweisungen)
strukturiert werden
 Die Anordnung der Anweisungen (als atomare Elemente) eines Algorithmus, die
bestimmt, in welcher Reihenfolge Dinge geschehen, heißt
 control flow (Steuerungsverlauf, Kontrollfluss) des Algorithmus genannt
 Manchmal wird auch der Programmablauf oder Kontrollfaden (thread of control,
thread), also die tatsächlich abgespulten Schritte und Anweisungen so bezeichnet
172
6.4.2 Strukturierung durch Sprung
 Bei der Vorstellung der Kontrollelemente wurde (aus hinterhältig, didaktischen)
Gründen auf ein viertes Element verzichtet:
Der Sprung („Goto“-Anweisung)
 Die Konstruktion „fahre fort mit Schritt x“ (goto x) stellt einen solchen Sprung
(jump) im Steuerungsverlauf dar
 Zur Anwendung von goto werden Schritte mit einer Marke (Label) versehen, um das
Ziel des Sprunges zu kennzeichnen
 Dies ist die elementarste Form, eine Wiederholung oder sonstige Verzweigung im
Ablauf auszudrücken
 Dadurch erhalten wir die elementar-iterative Beschreibungsform von Algorithmen, die
die Strukturierung mit ein-/mehrfacher Auswahl und Schleifen funktional abdeckt.
 Beispiel:
while x<100 {
x = x+1
}
1: if x>=100 goto 2
x = x+1;
goto 1;
2: ...
173
6.4.2 Strukturierung durch Sprung
 Anwendung von Sprüngen ist sehr gefährlich!
 Sprünge strukturieren komplexe Programm nicht ausreichend - der
Steuerungsverlauf kann verworren und unübersichtlich sein
 Um den Steuerungsverlauf auch bei komplexen Algorithmen übersichtlich zu
halten, schränkt man die Sprünge ein:
 Schleifen der Flussdiagramme sind höchstens ineinander geschachtelt
 Schleifen überkreuzen sich nicht!
 Bei gut strukturierten Algorithmen würde man z. B. nur wieder eine
geschlossene Schleife oder einen (vorzeitigen) Sprung bedingt durch die
Behandlung des Trivialfalls erlauben
 Wir sprechen in diesem Fall von strukturierten Sprüngen im Gegensatz zu freien
Sprüngen, die prinzipiell beliebige Ziele haben können
174
6.4.3 Strukturiert-iterative
Beschreibungsform
 Sprünge können alle „höhere“ Strukturierungsarten funktional abbilden.
Hier gilt auch der Umkehrschluss
 In der strukturiert-iterativen Beschreibungsform kommen Sprünge nur
noch implizit bei der Ausführung höherer Iterationsstrukturen vor
 Dieses sind Fallunterscheidungen (Auswahl) wie if-then-else
 oder insbesondere Schleifenkonstrukte
 Diese bewirken, dass der Programmfluss
 In einer Auswahl zu genau einer Auswahl geht.
 in einer Schleife von einer Prüfung zu den Aktionen des Schleifenkörpers und
wieder zurück zur Prüfung geht.
 Viele höhere Programmiersprachen (Pascal, C, C++) erlauben jedoch die
Verwendung von Sprüngen
 Aus Optimierungsgründen (Nähe zur Maschinensprache)
 Aus Strukturierungsgründen)
175
6.4.4 Strukturierungstypen
 Beispiel: Schemen einiger Kontrollflüsse
Strukturiert-iterativ
Elementar-iterativ
Spaghetti-Code
176
6.5
Blockung
 Mit Hilfe der bislang vorgestellten Kontrollelemente lassen sich die atomaren
Elemente (Anweisungen) eines Algorithmus‘ zu einem Kontrolfluss strukturieren.
Wie wir gesehen haben, kann dieser Kontrollfluss mehr oder weniger
„wohlstrukturiert“ sein.
In diesem Unterkapitel wird eine Element beschrieben, mit dem Aktionen
statisch nochmals zusammengefasst werden können. Diese Zusammenfassung
hat auch Einfluss auf das dynamische Verhalten von Verarbeitungsobjekten
(Variable).
 Inhalt:
1.
2.
3.
4.
5.
6.
7.
8.
9.
Die Idee
Notation
Formale Parameter
Aufruf
Beispiel: Ein einfacher Block
Eigenschaften
Beispiel: Seiteneffekte
Vorzeitiges Verlassen
Goldene Regeln
177
6.5.1 Die Idee
 Idee:
Eine Zusammenfassung von Aktionen bekommt einen Namen und kann durch
das Nennen des Namens (Aufruf) aktiviert werden.
 In einen Block sollen Daten formal hinein und herausgelangen
 Ein Block soll eigenen Daten besitzen
 Vorteile:
 Gliederung des Algorithmus‘ durch hierarchische Dekomposition
(„Divide et impera: Teile und herrsche“)
 Wiederverwendbarkeit durch mehrfachen Aufruf statt durch mehrfaches notieren.
 universeller ( Anzahl muss nicht bekannt sein)
 fehlerunanfälliger
 Kapselung unwichtiger Details („information Hiding“)
 Vorteile bei der Organisation von Programmiertätigkeit durch Verteilbarkeit der
Aufgaben.
178
6.5.2 Notation
 Ein Block ist die Zusammenfassung von Aktionen und wird wie folgt
beschrieben:
Flussdiagramm
 Pseudocode:
blockname (IN:
x1:Type1, … ;
OUT:
y1:Type2, … ;
THROUGH: z1:Type3, …
)
{
var w1:Type41; w2:Type42; … ;
A;
}
 blockname ist der Name des Blockes
 xi,yi,zi heißen formale Parameter und sind typisiert
 wi heißen lokale Variable
blockname
Struktogramm
blockname
 A ist eine Menge von Aktionen.
 Blöcke werden in vielen Sprachen als Funktion (nur ein OUT-Parameter) bzw.
Prozeduren umgesetzt
 oft steht der Block-Bezeichner selbst für einen OUT-Parameter (und wird daher auch
oft mit einem Typ versehen. (Bsp ?)
179
6.5.3 Formale Parameter
 IN-Parameter (Eingabeparameter) sind Parameter, die an den Block
übergeben werden
 Dazu werden beim Aufruf des Blockes an die Stelle der Eingabeparameter
Variable, Literale oder Ausdrücke (Berechnungen) notiert. Diese werden beim
Aufruf zu Werten transformiert, die an den entsprechenden Variablen zugewiesen
werden.
(call by value)
 OUT-Parameter (Ausgabeparameter) sind Parameter, die aus dem Block
durch Zuweisung an Variable zurückgegeben werden.
 Dazu werden beim Aufruf des Blockes an die Stelle der Ausgabeparameter
Variablen notiert, die nach dem Aufruf die zurückgegeben Werte beinhalten
(call-by reference)
 THROUGH-Parameter (Ein-/Ausgabeparameter) sind Parameter die Werte in
den Block hinein und hinaus übermitteln.
 Eingabe wie bei IN-Parametern (aber: nur Angabe einer Variable)
 Rückgabe wie bei OUT-Parametern
180
6.5.4 Aufruf
 Ein Block wird über seinen Namen aufgerufen
 Die Parameter werden als Argument übergeben:
 IN-Parameter werden als Wert übergeben, können also Variablenbezeichner,
Literale oder komplexe Ausdrücke aus Variablenbezeichner und Literalen sein
 OUT- und THROUGH-Parameter werden „by reference“, meist durch einen
Variablenbezeichner übergeben
 Meist wird die Zuordnung der übergeben Variablen zu den formalen Parametern
über die Reihenfolge implizit vorgegeben.
In manchen Programmiersprachen …
 … kann das auch explizit, z.B. über eine Zuweisung erfolgen
 … kann die Anzahl der übergebenen Variablen kleiner der Anzahl der formalen
Parametern sein – dann werden die fehlenden Parameter von rechts nach links nicht
übergeben
 … können formale IN-Parameter mit einem Standardwert initialisiert werden.
 Die Zuordnung der übergebenen Parameter zu den formalen Parametern nennt
man Bindung.
181
6.5.4 Beispiel: Ein einfacher Block
 Ein Block zur Berechnung von Summen (mit Aufrufzähler)
summe (IN:
value1 : Integer; value2 : Integer;
OUT:
result : Integer;
THROUGH: counter : Integer;
)
{
var i : integer;
// lokale Variable
result = 0;
// Initialisierung
for i=1 to value2
// ein wenig umständlich
value1 = value1 + 1;
result = value1; counter = counter + 1;
}
 Aufruf
anzahl = 1;
// schon erste Summe hat zwei Summanden
initial = 5;
summe(initial, 9, ergebnis, anzahl);
summe(ergebnis, 9, ergebnis, anzahl);
ergebnis/anzahl >> Bildschirm;
// Mittelwert
182
6.5.5 Eigenschaften
 Jeder Block kann über einen Satz lokaler Variable verfügen, die außerhalb des
Blockes nicht sichtbar sind
 Die Variablenbezeichner können also außerhalb ohne Einfluss auf den Block
verwendet werden
 Auch die in der Blockdefinition als formale Parameter verwendeten
Variablenbezeichner sind nur im Block sichtbar:
 Auch sie können außerhalb ohne Einfluss verwendet werden,
 Aber Vorsicht: die Veränderung von OUT und THROUGH-Parametern bewirkt
(oft) eine Veränderung der beim Aufruf verwendeten zugehörigen Parameter
(der zugehörigen „gebundenen“ Parameter).
 Variable, die in einem Block verwendet aber nicht deklariert werden, werden als
„global“ angenommen
 Viele Sprachen erlauben die Definition von Blöcken innerhalb von Blöcken
 Variablen, die in einem Block nicht deklariert sind, werden im umgebenden Block
vermutet.
183
6.5.6 Beispiel: Seiteneffekt
 Das (ungewollte) implizite Verändern von „äußeren“ Parametern durch
Veränderung „innerer“ Parameter nennt man „Seiteneffekt“
summe (THROUGH: value1 : Integer; value2 : Integer;
result : Integer;
)
{
value1 = value1 + value2;
result = value1;
}
 Aufruf
x = 5; y = 7;
summe (x,y,z);
„Die Summe von „ >> Bildschirm;
x >> Bildschirm;
„und“ >> Bildschirm;
y >> Bildschirm;
„ ist „ >> Bildschirm;
z >> Bildschirm;
Die Summe von
12
und
7
Ist
12
184
6.5.7 Vorzeitiges Verlassen
 Manchmal ist es sinnvoll, die Abarbeitung eines Blockes vorzeitig zu beenden
 Dies wird oft im Fehlerfall gemacht, wenn eine Weiterbearbeitung nicht mehr sinnvoll
erscheint - z.B. nach einer negativen Überprüfung der Eingabeparameter
 Flussdiagramm
Block
 Beispiel:
Struktogramm
Block
Pseudocode
Return;
wurzel(IN: argument:real; OUT: result:real)
{
if (argument<0) return; // return already here
else result = sqrt(argument);
}
185
6.5.8 Goldene Regeln
 Namen so lokal wie möglich deklarieren
 Möglichst keine globalen Variablen verwenden
 Wenn doch:
 Ganz wenige - nur eine (z.B. strukturiert)
 Auffällig kennzeichnen: z.B. global_error_handle
 Nach Möglichkeit „call by value“ verwenden
 Wird nicht von allen Programmiersprachen unterstützt
 Probleme bei der Rückgabe umfangreicher Daten (wg. Umkopieren)
 Blöcke sind so zu wählen dass:
 Der innere Zusammenhang stark ist
 Der äußere Zusammenhang schwach ist (minimale Schnittstellen, keine
Datenteilung , z.B. durch globale Variable)
186
6.6
Iteration und Rekursion
 Im Bereich der Datenstrukturen haben wir es oft mit rekursiven Strukturen z.B.
Bäumen zu tun. Auch in der Mathematik sind rekursive Definition weit
verbreitet.und finden über zugehörige Algorithmen Einzug in die Informatik.
Das Konzept der Rekursion wird in der Informatik allerdings teilweise mit
Skepsis umgesetzt, führt es doch, in ungeeigneten Fällen, zu inakzeptablen
Laufzeiten. Hinzu kommt, dass einige Programmier-spachen (z.B. FORTRAN)
Rekursion nicht unterstützen.
In diesem Unterkapitel soll auf die Möglichkeiten der Verwendung von
Rekursion bzw. Iteration eingegangen werden
 Inhalt
1.
2.
3.
4.
5.
Definition
Beispiele
Aufrufverwaltung
Wo nicht
Wo nicht und wo
187
6.6.1 Definition: Rekursion
 Ein Objekt heißt rekursiv, wenn es sich selbst als Teil enthält oder mit Hilfe von
sich selbst definiert ist.
 Wesentlich ist die Möglichkeit, unendliche Mengen von Objekten durch eine endliche
Aussage zu definieren.
 Bsp.: Definition natürlicher Zahlen:
 0 sei eine natürliche Zahl
 Der Nachfolger (n+1) einer natürlichen Zahl ist wieder eine natürliche Zahl
 Ein Algorithmus heißt rekursiv, wenn er sich selbst als einen seiner Aktionen
(Verarbeitungsschritten) enthält.

 In der Regel enthält er sich mit „verkleinerter“ Aufgabenstellung.
 Damit er terminiert, muss er einen Zweig beinhalten, der einen (den) elementaren
Wert nicht rekursiv bestimmt. (den Basisfall)
Objekte (Algorithmen), die andere Objekte (Algorithmen) enthalten, die wiederum die
ursprünglichen Objekte (Algorithmen) enthalten, heißen indirekt rekursiv
188
6.6.2 Beispiel: Fakultät
 Mathematisch rekursive Definition:
n!
=
 1

 n x (n - 1) !
n=0
n>0
 Algorithmisch rekursive Definition:
fakultaet (IN: n:integer, OUT: result:integer)
{
if (n == 0) then result = 1;
else
{
fakultaet (n-1, result);
result = result x n;
}
}
189
wir müssen wissen,
wir werden wissen
6.6.2 Beispiel: Hilbert Kurven


Die Hilbert Kurve ist eine stetige Kurve, die jeden beliebigen Punkt einer quadratischen
Fläche erreichen kann, ohne sich zu schneiden – und damit ein Fläche beliebig dicht
füllen kann. „D.Hilbert: Über stetige Abbildungen einer Linie auf ein Flächenstück, Math. Annalen, 1891“
Idee: Die Kurve wird aus vier Grundformen und vier Bildungsgesetzen generiert, die sich
direkt und indirekt rekursiv aufrufen
 Grundformen:
A
 Bildunggesetze:

A:
B:
C:
D:
B
B
A
D
C




C
A
B
C
D




D
A
B
C
D




C
D
A
B
Beispiel:
B
C
A
A
A
t=1
t=2
t=3
t=3
190
6.6.2 Beispiel: Hilbert Kurven
A (IN: t:integer)
{
if (t>0)
B(t-1); S(); A(t-1);
}
B (IN: t:integer)
{
if (t>0)
A(t-1); O(); B(t-1);
}
C (IN: t:integer)
{
if (t>0)
D(t-1); W(); C(t-1);
}
D (IN: t:integer)
{
if (t>0)
C(t-1); N(); D(t-1);
}
A
B
C
D
O(); A(t-1); N(); C(t-1);
S(); B(t-1); W(); D(t-1);
A: B
B:
D
C: D
D: C

A
A  A
 B 
 C
 D
 C
 D

B
C

 A
 B
N(); C(t-1); O(); A(t-1);
W(); D(t-1); S(); B(t-1);
// S(), N(), W(), O() sind Blöcke, die eine
// Linie nach Süden, Norden, Westen und Osten
// zeichnen
191
6.6.3 Aufrufverwaltung
fakultaet(3,x)
result=6
fakultaet(2,x)
fakultaet(1,x)
fakultaet(0,x)
result=2
result=1
result=1
 Eine Aktivierung der Tiefe n wird erst verlassen, wenn die von ihr erzeugte
Aktivierung der Tiefe n+1 schon verlassen wurde 
Verwaltung der Aktivierung als Stapel (Stack)
192
6.6.4 Wo nicht: Modulo-Berechnung
 Alle Grundrechenarten - und vergleichbar einfache mathematische Operationen lassen sich mit Hilfe sog. „Primitiv Rekursiver Funktionen“ beschreiben (siehe
Beispiel. „Algorithmenbeweis“)
mod(a,b)
=
 a

 mod(a-b,b)
falls a < b
falls a  b
 In gängiger mathematischer Notation könnte ein Verfahren zur Berechnung der
Modulus-Funktion a mod b wie folgt aussehen:
modulo (IN a,b: integer, OUT result: integer)
{
if (a<b) result = a;
else
modulo (a-b,b,result);
}
 Offenbar einfacher ist: result = a - (a/b) x b
193
6.6.4 Wo nicht: Fibonacci-Zahlen
 Fibonacci definiert im 13.Jahrhundert eine Zahlenfolge mit der
die Verhältnisse des „goldenen Schnitts“ ebenso beschrieben
werden können, wie die Populationsentwicklung in einem
Kaninchenstall:
 0
n=0
fib(n)
=  1
n=1
 fib(n-2)+fib(n-1)
n>1
 fib(IN: n:integer, OUT: result:integer)
{
r,s : integer;
if (n==0) then result = 0
else
if (n==1) then result = 1
else
{
fib(n-1,r); fib(n-2,s); result = r + s;
}
}
0
1
1
2
3
5
8
13
21
34
55
89
144
233
...
194
6.6.4 Wo nicht: Fibonacci-Zahlen
 fib(IN: n:integer, OUT: result:integer)
{... fib(n-1,r); fib(n-2,s); result = r + s; ...}
 n Aufrufe
Rechenzeit (1 Aufruf = 1 nsec)
0
1
n Zeit
1
1
10 0,18 sec
2
3
20 22 sec
3
5
50 41 sec
4
9
100 36000 Jahre
5
15
6
25
 Die Anzahl der Aufrufe verhält sich offenbar selbst ähnlich
der Fibonacci-Reihe:
 Anzahl (n) = 2 x fib(n+1) - 1
 Anstieg ist praktisch exponentiell also nicht verwendbar
0
1
1
2
3
5
8
13
21
34
55
89
144
233
...
195
6.6.4 Wo nicht: Fibonacci-Zahlen
 Idee: Merken von zwei Folgewerten in Variablen und Aufsummieren
in Schleife, wobei die Werte immer umgespeichert werden:
fib (IN: n:integer, OUT: result:integer)
{
a,b,z : integer;
a = 0; b = 1;
// fib0, fib1
while (n > 0) do
{
z = a + b;
// Berechnung der nächsten fib
a = b; b = z;
// Umspeichern der fibs
n = n - 1;
// dicrease n
}
result = a;
// das Resultat steht in a
}
 Anzahl (n) = n
 Zeit (n=100) = 1 sec (anstatt 36000 Jahre !)
0
1
1
2
3
5
8
13
21
34
55
89
144
233
...
196
6.6.5 Wo nicht und wo?
 Man sollte überall dort auf Rekursion verzichten, wo es eine offensichtliche
Lösung mit Iteration gibt.
 Jeder rekursive Algorithmus lässt sich in eine iterative Form umwandeln
(z.B. über explizites Ausformulieren einer Stackverwaltung)
 Es gibt allerdings einige Fälle, in denen Rekursion angewandt werden sollte:
 Rekursion ist überall dort sinnvoll anwendbar, wo sich ein Problem in mehrere (oft:
zwei) nicht überlappende Teilprobleme aufspalten lässt und sich die Teilprobleme
leicht rekombinieren lassen.
 Rekursion sollte dort verwendet werden, wo die zugrunde liegenden Datenstrukturen
selbst rekursiver Art sind (z.B.: Bäume)
 Für einige Probleme gibt es keine direkte Vorschrift zur Berechnung. Diese
können oft nur durch „Trial and Error“ gelöst werden. Oft lassen sich diese
Versuche (Trials) durch Untersuchung eines Teilproblems natürlich in rekursiver
Form darstellen.
Dieses Vorgehen nennt man „Backtracking“
197
6.6.6 Beispiel: Backtracking
 Weg des Springers
 Gegeben sei ein n x n Spielbrett (z.B. n=8). Ein Springer - der nach den
Schachregeln bewegt werden darf - wird auf das Feld mit der Anfangskoordinate
(x0,y0) gestellt (z.B. (1,1)).
 Zu finden ist ein Weg des Springers, der genau einmal über jedes der Felder des
Schachbrettes führt.
198
6.6.6 Beispiel: Backtracking
 Ansatz eines Algorithmus (in unvollständiger Notation)
track (IN: kandidat, OUT: erfolgreich)
// ohne Typ
{
trage_ein(kandidat);
// erst mal eintragen
erfolgreich = false;
// Initialisierung
if (fertig) then erfolgreich = true;
// Abbruchfall
else
// weitersuchen
{
repeat
{
wähleKandidat(neukandidat);
// wie auch immer
if (neukandidat) then
// es geht weiter
track (neukandidat, erfolgreich) // Rekusion
else
// Sackgasse !
trage_aus (kandidat);
// wieder austragen
} until (erfolgreich) or (not neukandidat)
}
}
199
6.7
Zusammenfassung des Kapitels
1. Ein Beispiel
 Drei Algorithmen im Vergleich zur Lösung einer quadratischen Gleichung
2. Definition des Algorithmenbegriffes
 Definition und dessen Anwendung im Beispiel. Weitere Prinzipien und der
Zusammenhang von Algorithmen und Programmen.
3. Strukturelemente:
 Die „atomaren“ Elemente und die Konstruktionselemente Folge, Auswahl,
Wiederholung
4. Strukturierung
 Der Begriff des Control Flows, das Problem der Strukturierung mit Sprung und
Blockung
5. Blockung
 Prinzip und Beispiele, Probleme und Regeln
6. Iteration und Rekursion
 Definition, Realisierung, wo und wo nicht
200
Kapitel 7 Algorithmentheorie
 Die algorithmische Beschreibung von Problemlösungen ist (wahrscheinlich) die
wesentliche Aufgabe eine Informatikers.
Doch, welche Probleme lassen sich algorithmisch lösen, wie kann man zeigen
dass ein Algorithmus ein Problem tatsächlich löst und wie aufwändig ist dann
die Problemlösung.
Diese drei Fragen stehen im Mittelpunkt der Algorithmentheorie und sind die
Fragen nach den Begirffen Berechenbarkeit, Korrektheit und Komplexität.
 Inhalt
1. Berechenbarkeit
2. Korrektheit
3. Komplexität
Teile dieses Kapitels sind aus:
201
R.Manthey: Vorlesung Informatik 1, Uni Bonn, 2001
7.1
Berechenbarkeit
 Wir haben den Begriff und die Elemente eines Algorithmus vorgestellt und
Algorithmen zur Lösung von Problemen verwendet.
In diesem Unterkapitel werden nun einige Fragen zur Anwendbar- und
Sinnhaftigkeit von Algorithmen gestellt und beantwortet.
 Inhalt:
1.
2.
3.
4.
5.
6.
Einige Fragen
Das Entscheidungsproblem
Die Turing-Maschine
Berechenbarkeit
Rekursive Funktionen
Church‘sche These
H. Ernst:“Grundlagen und Konzepte der Informatik“,Vieweg-Verlag,2000
202
7.1.1 Einige Fragen
1. Kann jedes Problem durch einen Algorithmus beschrieben werden, d.h.
prinzipiell - bei genügender Sorgfalt - gelöst werden ?
2. Kann jeder Algorithmus in ein Programm übertragen werden ?
 Welchen Anforderungen muss eine Programmiersprache genügen, damit jeder
Algorithmus damit formuliert werden kann ?
3. Ist ein Computer grundsätzlich in der Lage, einen bekannten, als Programm
formulierten Algorithmus auszuführen ?
4. Ist ein solcher Computer formalisierbar ?




Wie sieht ein solches abstraktes Model aus ?
Gibt es genau ein Model oder mehrere ?
Sind diese Modelle äquivalent ?
Gibt es andere Modelle oder Beschreibungsformen, die diesem formalisierten
Computermodell entsprechen ?
 Frage 1 und Frage 4 sind wesentlich für den Begriff der Berechenbarkeit, Frage
2 wird im anschließenden Kapitel behandelt, Frage 4 ist Gegenstand der
Vorlesung „Compilerbau“
203
7.1.2 Das Entscheidungsproblem
 Bis weit ins 20ste Jahrhundert war die Mehrzahl der Mathematiker (insb. David
Hilbert: 1862-1942) der Ansicht, dass man von jeder Aussage algorithmisch
beweisen könne, ob sie wahr oder falsch sein.
 Anders ausgedrückt: Es sei entscheidbar, ob ein Problem lösbar oder unlösbar ist.
 Die Frage, ob dies entscheidbar ist oder nicht ging als Entscheidungsproblem in die
Geschichte der Mathematik (und Informatik) ein.
 Kurt Gödel wies in seinem Unvollständigkeits-Theorem 1931 nach, dass alle
widerspruchsfreien axiomatischen Formulierungen der Zahlentheorie
unentscheidbare Aussagen enthalten.
 damit wurde insb. belegt, dass streng algorithmisch arbeitende Computer prinzipiell
nicht jedes Problem lösen können.
 Auf fast schon philosophischer Ebene wurde damit auch belegt, dass Wahrheit
eine andere Qualität als Beweisbarkeit besitzt.
 nicht alle „wahren“ Aussagen können auch bewiesen werden.
204
7.1.3 Definition: Berechenbarkeit
 Ein Problem ist genau dann algorithmisch lösbar, wenn es durch eine TuringMaschine darstellbar ist.
 Eine Funktion f(x) heißt berechenbar, genau dann wenn es einen Algorithmus
(eine Turing-Maschine) gibt, der bei gegebenem x das Ergebnis f(x) liefert
 Ein Computer ist äquivalent zu einer universellen Turing-Maschine.
 d.h. ein Computer ist äquivalent zu einer Turing-Maschine, die jede andere TuringMaschine simulieren kann.
 Zur Simulation einer beliebigen Turing-Maschine muss auf dem Eingabeband eine
Beschreibung der zu simulierenden Maschine codiert werden und außerdem deren
Eingabeband gespeichert sein.
 Die Menge verschiedener universeller Turing-Maschinen ist abzählbar - denn
das Band ist binär codiert, jede Kombination lässt sich auf eine natürliche Zahl
abbilden. Die Menge aller Funktionen f(x) ist überabzählbar (z.B. Funktionen
die auf eine reelle Zahl abbilden) 
Es gibt (unendlich viele) nicht berechenbare Funktionen
205
7.1.4 Rekursive Funktionen
 Es gibt innerhalb der mathematischen Funktionen zwei Unterklassen:
 primitiv-rekursive Funktionen:
 jede primitiv-rekursive Funktion ist berechenbar
 es gibt berechenbare Funktionen, die nicht primitiv-rekursiv sind
 primitiv-rekursive Funktionen lassen sich genau mit Algorithmen ohne
Schleifenkonstrukte (aber mit Blockung) darstellen.
 -rekursive Funktionen
 jede -rekursive Funktion ist berechenbar
 es gibt berechenbare Funktionen, die nicht -rekursiv sind
 -rekursive Funktionen lassen sich mit Algorithmen mit Schleifenkonstrukte
(und Blockung) darstellen.
 Es gilt folgende Beziehung innerhalb von Funktionen:
berechenbare Funktionen
-rekursive Funktionen
primitiv-rekursive Funktionen
206
7.1.5 Church‘sche These
 Wir haben bislang verschiedene Äquivalenzen gefunden:
 Primitiv und -rekursive Funktionen sind Teilmengen von berechenbaren Funktionen.
 Eine Funktion ist genau dann berechenbar, wenn es eine Turing-Maschine zu deren
Berechnung gibt,.
 Die Darstellung mit Hilfe einer Turing-Maschine ist äquivalent mit der einer
universellen Turingmaschine, die wiederum eine Abstraktion eines Computers
darstellt
 Dies legt die Formulierung einer der Church‘schen These nahe:
Alle im intuitiven Sinn vernünftigen Formalisierungen von Problemlösungen sind
äquivalent
 Wenn ein Problem nicht durch eine Turing-Maschine gelöst werden kann, so ist es
algorithmisch überhaupt nicht lösbar
 Da Begriffe wie „intuitiv“ und „vernünftig“ nicht definiert sind, ist die Church‘sche
These nicht beweisbar.
207
7.2.2 C.A.R. Hoare: Logik zur Verifikation
 C.A.R. Hoare formulierte 1969 ein Kalkül zum Beweis von Aussagen über
Algorithmen und Programme
 damit sind - im Gegensatz zum Test - statische Aussagen über Zustände des
Algorithmus ( Werte der Variablen) möglich. Diese Aussagen gelten für alle
Ausführungen des Algorithmus
 Durch logische Schlüsse über die Elemente eines Algorithmus kann gezeigt
werden, dass
 an einer bestimmten Stelle im Algorithmus eine bestimmte Aussage gilt.
 eine Aussage an jeder Stelle eines Teils des Algorithmus invariant gilt
 Schleifen terminieren.
Also:
 ein Algorithmus aus jeder zulässigen Eingabe die geforderte Ausgabe berechnet
 Hoare verknüpft „mathematisches Schließen“ (Methoden der Aussagenlogik) mit
„informatischem Schließen“ (Hoar‘sches Kalkül)
208
7.2.2 C.A.R. Hoare: Beispiel

min (IN: a,b: integer, OUT min:integer)
// Vorbedingung: a,b > 0 (nicht unbedingt notwendig)
// Nachbedingung: (min=a  min=b)  (mina)  (minb)
{
if a<b then {
//  Z1: a<b
min = a;
//  Z2: a<b  min=a  Z3: min=a  mina  minb
//  Z4: ((min=a  min=b)  mina  minb)
} else {
//  Z5: ba
min = b;
//  Z6: ba  min=b  Z7: min=b  minb  mina
//  Z8: ((min=a  min=b)  mina  minb)
} // Z4 = Z8
//  Z9 : (min=a  min=b)  (mina)  (minb) = Q
}
 Damit ist aus der Vorbedingung P mit Hilfe der Anweisung in min() die
Nachbedingung Q formal abgeleitet worden.
209
7.2.2 C.A.R. Hoare: Vorgehen
 Aussagen über den Algorithmenzustand, über Werte von Variablen werden in
den Algorithmus eingefügt:
 { P } A1 { R } A2 { Q }
 bedeutet: R gilt immer zwischen der Ausführung von A1 und der Ausführung von
A2
 Beispiel: { i + 1  0} i := i + 1; { i  0 } a [i] := k; {...}
 Zur Verifikation eines Algorithmus muss für jede Anweisung S ein Nachweis
geführt werden:
 { Vorbedingung P } S { Nachbedingung Q }
 nachweisen: Wenn vor der Ausführung des Schrittes S die P gilt, dann gilt Q nach
der Ausführung von S, falls S terminiert.
 Beispiel: { i + 1  0} i := i + 1; {i  0} mit Zuweisungsregel nachweisen
 Die Aussagen werden entsprechend der Struktur von S verknüpft. Für jede
Anweisungsform wird eine spezielle Schlussregel angewandt.
 Die Spezifikation liefert Vorbedingung und Nachbedingung des gesamten
Algorithmus:
210
7.2.3 Zuweisung
 Betrachten wir eine Zuweisung eines Ausdruckes (expr) an eine Variable (x)
x := expr
Die Bedeutung der Zuweisung ist wie folgt:
 x erhält den Wert von expr, nach Ausführung der Zuweisung hat x also den Wert
von expr, wobei expr ein komplexer Ausdruck sein kann, eine Variable oder nur ein
Literal. In jedem Fall wird expr zu einem Wert evaluiert.
 der ursprüngliche Wert von x wird dabei überschrieben, d.h. nach Ausführung der
Zuweisung hat x möglicherweise einen anderen Wert als vor der Ausführung (in
einigen Fällen kann das auch der gleiche Wert sein, nämlich dann, wenn der Wert
von expr gleich dem ursprünglichen Wert von x ist)
 Alle anderen Variablen, bleiben unverändert ( auch die, die in expr vorkommen)
 Will man also beweisen dass aus einer Vorbedingung P (also einem logischen
Ausdruck über Variable) mit der Zuweisung x := expr die Nachbedingung Q
abzuleiten ist, so muss man diese Eigenschaften einer Zuweisung beachten:
1.
2.
3.
4.
Nach Ausführung gilt: x = expr
Alles was vorher für die rechte Seite der Zuweisung galt, gilt hinterher für die linke
Alles was vorher für die linke Seite der Zuweisung galt, gilt hinterher nicht mehr
Alle anderen Aussagen bleiben unberührt
211
7.2.3 Zuweisung: Regel
 Die Zuweisung x = expr wertet den Ausdruck expr aus und weist das Ergebnis
der Variablen x zu.
Es gilt dann:
{P[x/expr]} x := expr {P}
P[x/expr] steht für die Substitution von x durch expr in P
 Die Nachbedingung P erhält man dadurch, dass man jedes Vorkommen von expr in
der Vorbedingung durch x (die linke Seite der Zuweisung) ersetzt
 Wenn man also zeigen will, dass nach der Zuweisung eine Aussage P für x gilt, muss
man zeigen, dass vor der Zuweisung dieselbe Aussage P für expr gilt.
 Das bedeutet:
1. es gilt als neue (konjunktiv verknüpfte) Aussage der Nachbedingung: x = expr
2. alle Aussagen der Vorbedingung für expr, gelten für x in der Nachbedingung
 Die Nachbedingung P erhält man also dadurch, dass man jedes Vorkommen
von expr in der Vorbedingung durch x ersetzt. Die Vorbedingung ist ggf. so
umzuformen, dass expr explizit Teil der Vorbedingung ist – und zwar in allen
Aussagen, in denen Bestandteile von expr vorkommen.
3. Aussagen der Vorb. über x gelten in der Nachbedingung nicht mehr
4. Aussagen der Vorb. über Variablen  x gelten in der Nachbedingung unverändert
212
7.2.3 Zuweisung: Beispiele
 Regeln:
1. es gilt als neue (konjunktiv verknüpfte) Aussage der Nachbedingung: x = expr
2. alle Aussagen der Vorbedingung für expr, gelten für x in der Nachbedingung
 Die Nachbedingung P erhält man also dadurch, dass man jedes Vorkommen
von expr in der Vorbedingung durch x ersetzt. Die Vorbedingung ist ggf. so
umzuformen, dass expr explizit Teil der Vorbedingung ist – und zwar in allen
Aussagen, in denen Bestandteile von expr vorkommen.
3. Aussagen der Vorb. über x gelten in der Nachbedingung nicht mehr
4. Aussagen der Vorb. über Variablen  x gelten in der Nachbedingung unverändert
1.
2.
3.
4.
5.
6.
7.
8.
{a>0}
{y=5}
{a>0  x>7}
{a>0  z>0}
{i+1>0}
{i0}  {i+1>0}
{i=2}  {i+1=3}
{z=5}
x=a
x=y
x=a
x=a
i=i+1
i=i+1
i=i+1
x=1
{x>0}
{x=5}
{x>0  x>7}
{x>0  a>0  z>0}
{i>0}
{i>0}
{i=3}
{z=5  x=1}
falsch wg. Punkt 3
z und a nicht betroffen
passend umformen
passend umformen
z nicht betroffen, x neu
213
7.2.4 Rechenregel: Konsequenz
 Abschwächung der Nachbedingung
wenn gilt
{P} S {R}
Beispiel
{a+b>0} S {x>0}
und
{R}  {Q}
dann gilt auch
{P} S {Q}
{x>0}  {x0}
{a+b>0} S {X0}
 Verschärfung der Vorbedingung
wenn gilt
{P}  {R}
und
{R} S {Q}
dann gilt auch
{P} S {Q}
 Beispiel (Notation: Im Algorithmus können Implikationen () in
Ausführungsrichtung eingefügt werden)
{a+b>0}
x = a+b;
{x>0}  {2*x  0}
y = 2 * x
{y0}
// Abschwächung der Nachbedingung
214
7.2.4 Rechenregel: Sequenz
 Folgendes Schema lässt sich auf eine Sequenz von Aktionen (Statements)
anwenden:
wenn gilt
{P} S1 {R}
und
{R} S2 {Q}
dann gilt auch
{P} S1;S2 {Q}
 Beispiel:
{x>0  y>0}
a = x;
{a>0  y>0}
{x>0  y>0}
a = x;

{a>0  y>0}
b = y;
{a>0  b>0}

b = y;
{a>0  b>0}
 Bei trivialen Ableitungen können die Zwischenschritte (Zusicherungen,
Aussagen) demnach auch weggelassen werden:
{x>0  y>0}
a = x; b = y;
{a>0  b>0}
215
7.2.5 Bedingte Anweisung
 Betrachten wir eine bedingte Ausführung
if B then S
Die Bedeutung der Bedingten Ausführung ist wie folgt:
 falls die Bedingung B erfüllt ist, werden die Anweisungen S ausgeführt
 falls die Bedingung B nicht erfüllt ist, wird keine Anweisung ausgeführt
 Will man also allgemein beweisen, dass aus einer Vorbedingung P (also einem
logischen Ausdruck über Variable) mit der bedingte Ausführung if B then S die
Nachbedingung Q abzuleiten ist, so muss man beweisen, dass die
Nachbedingung erfüllt wird, egal ob
 die Bedingung erfüllt ist und somit die Anweisungen ausgeführt werden, oder
 die Bedingung nicht erfüllt ist und sich die Nachbedingung ohne Ausführung einer
Anweisung direkt aus der Vorbedingung mathematisch ableiten lässt.
216
7.2.5 Bedingte Anweisung: Regel
 Schema:
wenn gilt
{P B} S {Q}
und
{PB}  {Q}
dann gilt auch
{P} if B then S {Q}
 Um die Nachbedingung einer bedingten Anweisung zu beweisen, muss
1. aus der Vorbedingung und der Anweisungs-Bedingung über die Anweisung die
Nachbedingung nachgewiesen werden
2. aus der Vorbedingung und der Negation der Anweisung die Nachbedingung direkt
folgen
 Beispiel:
 Gegeben: if a<0 then a = -a
 Beweise, dass der Algorithmus a0 für alle a liefert:
1. {P  a<0}  {P -a>0} a=-a {P  a>0}  {P  a 0}
2. {P  (a<0)}  {P  a 0}
dann gilt auch
{P} if a<0 then a=-a {P  a 0}
217
7.2.5 Bedingte Anweisung: Notation
 Beispiel:
 Gegeben: if a<0 then a = -a
 Beweise, dass der Algorithmus a0 für alle a liefert:
1. {P  a<0}  {P -a>0} a=-a {P  a>0}  {P  a 0}
2. {P  (a<0)}  {P  a 0}
dann gilt auch
{P} if a<0 then a=-a {P  a 0}
 Da es im Programmtext keine Stelle gibt, in der die „Alternative“ notiert wird (da
es keinen „else“-Fall gibt, kann man eine „Dummyzeile“ z.B. mit folgender
Notation einfügen:
{P}
if a<0 then
{P  a<0}  {P -a>0}
a = -a
{P  a>0}  {P  a 0}
// leere Alternative:
{P  (a<0)}  {P  a 0}
{P  a 0}
218
7.2.5 Einfache Alternative
 Betrachten wir eine bedingte Ausführung
if B then S1 else S2
Die Bedeutung der Einfachen Alternative ist wie folgt:
 falls die Bedingung B erfüllt ist, werden die Anweisungen S1 ausgeführt
 falls die Bedingung B nicht erfüllt ist, werden die Anweisungen S2 ausgeführt
 Will man also allgemein beweisen, dass aus einer Vorbedingung P (also einem
logischen Ausdruck über Variable) mit der bedingte Ausführung if B then S1
else S2 die Nachbedingung Q abzuleiten ist, so muss man beweisen, dass die
Nachbedingung erfüllt wird, egal ob
 die Bedingung erfüllt ist und somit die Anweisungen S1 ausgeführt werden, oder
 die Bedingung nicht erfüllt ist und sich die Anweisungen S2 ausgeführt werden.
219
7.2.5 Einfache Alternative: Regel
 Schema:
wenn gilt
{P  B} S1 {Q}
und
{P  B} S2 {Q}
dann gilt auch
{P} if B then S1 else S2 {Q}
 Aus der gemeinsamen Vorbedingung P muss für beide Alternativen dieselbe
Nachbedingung Q nachweisbar sein
 Beispiel: Gegeben: a>0, b>0, ab und ein Algorithmus:
 Beweise, dass nach den Operationen immer noch gilt: a>0, b>0
{P  a>0  b>0  ab}
if a>b then
{P  B  a>0  b>0  ab  a>b}  {b>0  a-b>0}
a = a-b;
{b>0  a>0  Q}
else
{P  B  a>0  b>0  ab  ab}  {a>0  b-a>0}
b = b-a;
{a>0  b>0 = b>0  a>0  Q}
{a>0  b>0  Q}
220
7.2.6 Schleife: Einführungsbeispiel

Betrachten wir folgenden Algorithmus:
fill (int j) {
// Zusicherung P: j > 0
i = 1;
// A
while ( i < j) {
// B
a[i] = 0;
i = i+1;
// C
}
// D
//  Q
}

Um diesen Algorithmus zu beweisen, muss
man zeigen, dass aus Q aus P ableitbar ist,
egal wie groß j ist




man darf dabei die Zusicherung P (hier j>0) als
gegeben voraussetzen
die Schleife wird, in Abhängigkeit von j beliebig
oft, möglicherweise gar nicht durchlaufen
Der Beweis muss also “allgemein” geführt
werden, d.h. hier: jeden möglichen Wert von j
berücksichtigen
Um den Algorithmus “allgemein” zu beweisen,
formuliert (und beweist) man Aussagen die
gelten:


vor der Schleife (also bei “A”), wobei P
vorausgesetzt werden kann
nach dem Durchlauf jeder Schleife
(bei “C”)
Dabei kann man davon ausgehen dass:


bei “B” dasselbe wie bei “A” gilt und zusätzlich
die Schleifenbedingung.
bei “D” dasselbe wie bei “C” gilt und zusätzlich
die Negation der Schleifenbedingung.
Danach muss “nur” noch gezeigt werden, dass
aus Aussagen bei “D” auf die Nachbedingung
Q geschlossen werden kann.
221
7.2.6 Schleife: Einführungsbeispiel

Betrachten wir folgenden Algorithmus:
fill (int j) {
// Zusicherung P: j > 0
i = 1;
// A
while ( i < j) {
// B
a[i] = 0;
i = i+1;
// C
}
// D
// 
Q
}

Um den Beweis zu führen, müssen
einige Fragen beantwortet werden:
1. was will man eigentlich beweisen ?
 was macht dieser Algorithmus ?
 was ist demnach die
Nachbedingung Q
2. welche Aussagen gelten, egal ob die
Schleife betreten wird oder nicht ?
3. welche Aussagen gelten, egal in
welchem Schleifendurchlauf wir uns
befinden ?


Frage 2 und Frage 3 sind die Fragen
nach der Schleifeninvariante.
Antworten auf die Fragen:
1. Der Algorithmus füllt ein array, ab dem 1ten Element (einschließlich) bis zum
j-ten Element (ausschließlich)
also:
 x: 1 ≤ x < j : a[x] = 0
2.  x: 1 ≤ x < i : a[x] = 0
3.  x: 1 ≤ x < i : a[x] = 0
222
7.2.6 Schleife: Regel
 Schema:
wenn gilt
{P  I B} S {I}
dann gilt auch
{I} while B { S } {I  B  Q}
// I = Schleifeninvariante
 Schleifeninvarianten sind Zusicherungen in Schleifen, die beim Durchlaufen
des Schleifenkörpers erhalten bleiben. Es gelte





P
Q
I
B
S
Zusicherung über Variable vor Schleifeneintritt
Zusicherung über Variable nach Schleifenende
Schleifeninvariante
Wiederholbedingung der Schleife
Statements (Aktionen) im Schleifenkörper
 Die Nachbedingung einer Schleife ist über die Invariante nachgewiesen, wenn
gilt:
1. P  I
2. (I B)  I
3. (I B)  Q
die Invariante muss vor Schleifeneintritt wahr sein
die Invariante darf in Schleife nicht verändert werden
die Nachbedingung muss sich nach Verlassen der
Schleife aus der Invariante nachweisen lassen
223
7.2.6 Schleife: Schema
 Das Schema der Gültigkeit von Aussagen sei anhand des Flussdiagramms für
Schleifen verdeutlicht:
P

I muss aus
P ableitbar
sein
Um Q(V) zu beweisen, muss
man I(V) so wählen, dass
Q(V) aus I(V)  B(V) ableitbar
ist
I
I  B
B?
w

Q(V)
f
IB

S
I
Hier muss man beweisen,
dass sich I in S aus I  B
ableiten lässt
224
7.2.6 Schleife: Einführungsbeispiel
 Betrachten wir den einführenden Algorithmus:
fill (int j) {
// Zusicherung P: j > 0; j ganzzahlig
i = 1;
// A:  x: 1 ≤ x < i : a[x] = 0  i ≤ j
Invariante
while ( i < j) {
// B:  x: 1 ≤ x < i : a[x] = 0  i ≤ j  i < j
a[i] = 0;
//  x: 1 ≤ x ≤ i
: a[x] = 0  i+1 ≤ j
//  x: 1 ≤ x < i+1 : a[x] = 0  i+1 ≤ j
i = i+1;
// C:  x: 1 ≤ x < i : a[x] = 0  i ≤ j
}
// D:
 x: 1 ≤ x < i : a[x] = 0  i ≤ j  ¬(i<j)
//

 x: 1 ≤ x < i : a[x] = 0  i ≤ j  i ≥ j
//

 x: 1 ≤ x < i : a[x] = 0  i = j
//

 x: 1 ≤ x < j : a[x] = 0
}

Für die Invariante der Schleife werden folgende Aussagen herangezogen:



Der Algorithmus füllt ein array, ab dem 1-ten Element (einschließlich) bis zum
j-ten Element (ausschließlich), also:  x: 1 ≤ x < i : a[x] = 0
Der Algorithmus läuft in der Schleife solange i ≤ j ist.
Nach der Schleife gilt zusätzlich:

¬(i<j)
225
7.2.6 Schleife: Beispiel 1
 Algorithmus zum Potenzieren
 // Vorbedingung P: b  0 (positive Exponenten)
// Nachbedingung Q: z = ab
 { P  b  0 }
x=a, y=b, z=1;
{ x=a  y=b  z=1  y  0} 
{INV: z * xy = ab  y0}
while y>0
{
{ INV  y>0  z*x(y-1)+1=ab  (y-1)+1 > 0 }
y = y-1;
{ z*xy+1=ab  y+1>0 } 
{ ((z*x)/x)*xy+1 = ab  y  0 }
z = z*x;
{ z/x*xy+1 = ab  y  0 } 
{ z * xy = ab  y  0
 INV }
}
{ INV  B  z * xy = ab  y0  y0 
z * x 0 = ab  z = a b  Q }
P
I
I  B Q
B?
w
f
IB
S
I
226
7.2.6 Schleife: Tipps
 Das Finden der „richtigen“ Invariante kann ganz schön kniffelig sein:
 Ein paar „Tipps“:
 Wenn die Nachbedingung nicht gegeben ist, versuche die Semantik des
Algorithmus‘ zu verstehen, z.B. anhand von Beispielen (Notation über eine
Variablentabelle)
 interessant sind „eigentlich nur“ die EIngabevariablen und die Variablen, die
sich in der Schleife verändern
 in „Semantik“ der Schleife gibt einen Hinweis auf die mathematischen
Operationen bzw. aussagenlogischen Ausdrücke in Q.
 Betrachte die Anweisungen in der Schleife:
Meist wird etwas vergrößert (z.B. die Variable der Abbruchbedingung), während
etwas anderes verkleinert wird - oder umgekehrt. Kombiniere diese:
z * xy
 Setze Ein- und Ausgabevariablen in Bezug zueinander
z * xy = ab
 Verwende die Schleifenbedingung zum „Einklemmen“ der Schleifenvariable.
 Beachte, dass aus INV und B(V) Q(V) ableitbar sein soll Das bedeutet, dass
man die Invariante aus der Nachbedingung konstruieren kann, indem man die
negierte Bedingung mit berücksichtigt
z * xy = ab  y=0  z*x0 = z = ab  Q
227
7.2.6 Schleife: Beispiel 2

Multiplikation durch fortgesetzte Addition:
// Vorbedingung P: a0  b0, Beh.: Nachbedingung Q: z = a*b
x = a; y = b; z = 0; { x=a  y=b  x0  y0  z=0 } 
// Auch hier: Die Summe von x*y+z bleibt konstant a*b
{ INV: z+xy = ab, x0, y0 }
while x > 0 {
{ INV  B  z+xy
= ab, x0, y0 ,x>0 } 
P
rechte Seite der Zuweisung
{ (z+y)-y+xy
z = z + y;
= ab,
x>0
,y0 }
I
I  B  Q
linke Seite der Zuweisung
{
{
x
{
{
{
z-y+xy
z-y+((x-1)+1)y
= x - 1;
z-y+(x+1)y
z-y+xy+y = z+xy
INV }
= ab, x>0
,y0 } 
= ab, (x-1)+1>0 ,y0 }
= ab,
= ab,
x+1>0
x0
,y0 } 
,y0 } 
}
{ INV  B  z+xy
= ab, x0, y0  x0 }
{ z+xy=ab  x=0  z+0*y=a*b  Q }

B?
f
IB
w
S
I
228
7.2.6 Schleife: Beispiel 3
 Die ägyptische Bauernmultiplikation
// Vorbedingung P: a0  b0, Beh.: Nachbedingung Q: z = a*b
x = a; y = b; z = 0; { x,y0  z=0  x=a  y=b }
// Schleife verdoppelt x und halbiert y: Invariante:
 INV = { z+x*y = a*b  x,y0 }
while x > 0 {
{ INV  x>0 }
if (odd(x) then
{ odd(x) (z+y)-y+x*y = a*b)
 x>0,y0 }
z = z+y;
{ odd(x)  z-y+x*y = a*b  x>0,y0 }
 { odd(x)  z-y+x*y = a*b  x>0,y0 }  { even(x)  z+x*y = a*b  x>0,y0 }
// leere Anweisung { even(x)  z+x*y
= a*b  x>0,y0 }
 { odd(x)  z-y+x*y = a*b  x>0,y0 }  { even(x)  z+x*y = a*b  x>0,y0 }
{ ( odd(x)  z-(2y/2)+x*(2y/2) = a*b  x>0,(2y/2)0 ) 
( even(x)  z+x*(2y/2)
= a*b  x>0,(2y/2)0 ) }
y = y * 2;
{ ( odd(x)  z-y/2+x*y/2 = a*b  x>0,y/20 ) 
( even(x)  z+x*y/2
= a*b  x>0,y/20 )
} 
{ (odd(2(x div 2)+1)  z-y/2+(2(x div 2)+1)*y/2 = a*b  (2(x div 2)+1)>0,y0 ) 
(even(2(x div 2))  z+(2(x div 2))*y/2
= a*b  2(x div 2) >0,y0 ) }
x = x div 2; // div = Ganzzahldivision
{ ( odd(2x+1)  z-y/2+(2x+1)*y/2 = a*b  (2x+1)>0,y/20 ) 
( even(2x)  z+
2x
*y/2 = a*b  2x
>0,y/20 )
} 
{ TRUE  (z-(y - y(2x+1))/2  z-(y-2xy-y)/2 = z-(-2xy/2)= z+xy = a*b  x  0) 
TRUE  (z
+ 2x * (y/2) 
= z+xy = a*b  x  0) }  INV
}
{ INV  B = (z+x*y=a*b)  (x=0)  z+0*y=a*b  Q }
229
7.2.6 Schleife: Terminierung
 Das Hoar‘sche Kalkül kann nur die partielle Korrektheit eines Algorithmus
beweisen, d.h. die Terminierung einer Schleife muss separat nachgewiesen
werden
 Beweis der Terminierung
1. Gib einen ganzzahligen Ausdruck E an über Variablen, die in der Schleife
vorkommen und zeige, dass E bei jeder Iteration durch S verkleinert wird
2. Zeige, dass E nach unten begrenzt ist, z.B. dass 0E eine Invariante der Schleife ist
3. Zeige, dass die Grenze auch erreicht wird.
 E kann auch monoton vergrößert und nach oben begrenzt sein
 Beweis der Nicht-Terminierung: Beweise,
1. dass RB eine Invarianz der Schleife ist (also R in die Schleife geht) und dass es
eine Variablenbelegung gibt, so dass RB vor der Schleife gilt
2. dass R einen speziellen Zustand charakterisiert, in dem die Schleife nicht anhält
 Es gibt Schleifen, für die man nicht entscheiden kann, ob sie für jede
Vorbedingung terminieren.
{ a>0  b>0 }
while ab {
while a>b { a=a-b }
while a<b { b=b-a }
} // terminiert
{ a>0  b>0 }
while ab {
while ab { a=a-b }
while a<b { b=b-a }
} // terminiert
nicht immer (a = 2*b)
{ nN  n>1 }
while n>1
if n gerade then n = n/2
else n = 3*n+1
// Terminierung unbewiesen
230
7.2.7 (Kritische) Anmerkungen
 Die Verifikation entspricht einer mathematischen Beweisführung und kann
entsprechend kniffelig, aufwändig, wenn nicht gar unmöglich sein.
 Durch formale Überprüfung der Korrektheit, lassen sich Schlüsselstellen eines
Algorithmus‘ (eines Programms) verifizieren
 Durch das Denken mit Zusicherungen, Invarianten und mathematische
Folgerungen wird die Erstellung fehlerfreier Programme gefördert.
 Auch wenn es semi-automatische Systeme zur formalen Verifikation von
Algorithmen gibt, ist es praktisch nicht möglich, auch nur halbwegs komplexe
Programmsysteme damit zu verifizieren
 Selbst wenn es möglich wäre, Algorithmen vollständig formal zu beweisen, so
wäre dies keine Garantie, dass ein Programmsystem entsprechend den
Wünschen eines „Kunden“ funktioniert. Dazu gehören alle Mechanismen eines
ordentlichen Software-Engineering.
231
7.3
Komplexität
 In diesem Kapitel haben wir den Begriff „Berechenbarkeit“ definiert als all das,
was algorithmisch beschreibbar ist. Wir haben eine Methode vorgestellt, mit der
man (meist) zeigen kann, dass ein Algorithmus das tut was er soll. Was noch
fehlt - und hier behandelt werden soll - ist die Frage nach dem Zeit- und
Platzbedarf eines Algorithmus.
 Inhalt
1.
2.
3.
4.
5.
6.
Wie „gut“ ist ein Algorithmus
Die O-Notation
Häufige O-Ausdrücke
Einige Regeln
Quantitatives
Platzbedarf
232
7.3.1 Qualität eines Algorithmus
 Die Abarbeitung eines Algorithmus benötigt „Ressourcen“, vor allem:
 Zeit
 Platz
Laufzeit des Algorithmus
Speicherplatzbedarf des Algorithmus
 Problem bei der Ressourcenermittlung - der Ressourcenbedarf ist Abhängig
von:





der Problemgröße (z.B. Multiplikation einer 10x10 bzw. 100x100 Matrix)
der Eingabewerte (z.B. Sortieren einer bereits sortierten Menge)
der Fragestellung (bester, mittlerer, schlechtester Fall)
der Güte der Implementierung (z.B. (un-)geschickte Typwahl)
der Hard- und Software (z.B. Schneller Rechner, optimierter Compiler)
 Es gibt auch Qualitätsmerkmale eines Algorithmus, der sich nicht am
Ressourcenbedarf festmachen (aber das ist eine andere Geschichte ...)




Wartbarkeit, Wartungsintensität
Robustheit
Eleganz
...
233
7.3.2 Die O-Notation: Definition
 Definition:
Eine Funktion g(n) wird O(f(n)) genannt („Die Laufzeit, der Aufwand, die
Zeitkomplexität von g(n) ist O(f(n))“), falls es Konstanten c und n0 gibt, so dass:
g(n)  cf(n), für fast alle n  no ist
 f(n) ist damit eine obere Schranke für die Laufzeit des Algorithmus (allerdings nur
zusammen mit einem festen c und ab bestimmten n0) !
 Die Problemgröße kann der Umfang der Eingabemenge sein, die Größe des zu
verarbeitenden Objektes (z.B. der Zahl), …
L
a
u
f
z
e
i
t
g(n)  cf(n), für fast alle n  no
cf(n)
g(n)
f(n)
no
234
Problemgröße
7.3.2 Die O-Notation: Beispiel

Beispiel:
 Bei der Analyse eines Algorithmus hat sich herausgestellt, dass
die Laufzeit:
g(n) = 3n2 + 7n – 1
ist.
 Behauptung:
Die Laufzeit von g(n) ist O(n2), also
f(n)=n2,
 Beweis:
Es muss Konstanten c und n0
geben, so dass gilt:
3n2+7n-1  c n2, für alle n  n0
setze n0=7 und c=4, dann gilt:
3n2+7n-1  3n2+7n  3n2+n2 = 4n2

L
a
u
f
z
e
i
t
g(n)  cf(n), für fast alle n  no
cf(n) = 4 n2
g(n)
Allgemein:
f(n)=n2
 g(n) = amnm + am-1nm-1 + … + a0n0
 amnm + am-1nm + … + a0nm
= nm (am + am-1 + … + a0 )
also: g(n)  c nm
mit c = am + am-1 + … + a0
no
Problemgröße235
7.3.2 Die O-Notation: Schranken
 Die Notation gibt nur eine obere Schranke der Komplexität , das muss nicht
notwendigerweise die beste Schranke sein.
 Beispiel:
Eine weitere obere Schranke für g(n) = 3n2 + 7n - 1 ist auch O(n3), welche sicher nicht
die beste ist.
 Bei der Suche nach der Größenordnung von f(n) wird man versuchen, das
kleinste f(n) zu finden, für das g(n)  c . f(n)
 Dieses ist dann eine kleinste, obere Schranke für den Aufwand
 Zur Bestimmung des tatsächlichen asymptotischen Aufwands wird man also
noch eine größte, untere Schranke h(n) = (g(n)) suchen für die gilt: limn
h(n)/f(n) = 1
 Eine untere Schranke ist die Zeit, die jeder Algorithmus (ab einem n>n0) benötigt
 Das ist im Allgemeinen viel schwieriger !
236
7.3.2 Die O-Notation: Achtung
 Achtung !
Die Konstanten c und n0 werden üblicherweise nicht angegeben und können
sehr groß sein
 Beispiel:
Algorithmus A habe eine Laufzeit von O(n2)
Algorithmus B für das gleiche Problem eine Laufzeit von O(1,5n)
Welcher Algorithmus ist besser ?
 schnelle Antwort: A (das stimmt auch für große n)
 bessere Antwort: Wie groß ist n ? Wie groß sind die Konstanten ?
 z.B. für cA=1000 und cB=0,001
Bis hier ist B besser als A
n
cAn2
cB1,5n
1
10
20
50
100
103
105
4  105
2,5  106
107
1,5  10-3
1,8  10-2
3,3
6,4  105
4,1  1014
237
7.3.3 Konstanter Aufwand: O(1)
 Teile von Ausdrücken, die eventuell ein „paar“ Mal durchlaufen werden, wobei
die (maximale) Anzahl der Durchläufe nicht abhängig von den Eingabewerten
sind, haben konstante Laufzeit: O(1)  (c * 1)
 Beispiele:
i,j: integer;
max, i, y : integer;
i << Tastatur;
max = 0;
j = 7;
y << Tastatur;
if (i=j) then
if (y < 20) then max=10
j = j+1;
else
max=100;
i = i+1;
for i=1 to max
j = j+1;
{
j >> Bildschirm;
y = y+1;
i >> Bildschirm
}
 Algorithmen ohne Schleifen und Rekursion haben konstante Laufzeit
 der Umkehrschluss gilt nicht (siehe Beispiel):
Die Anzahl der Schleifendurchläufe ist zwar abhängig von y (entweder 20 oder 100),
die maximale Anzahl aber nicht (immer 100, egal wie groß oder klein y ist)
238
7.3.3 Rekursion: O(log n)
 Rekursive Algorithmen, die in jedem Schritt die Menge der Eingabedaten
halbieren haben eine Laufzeit von O(log n)
 eigentlich O(ld n), aber da ld n  3,322 log n = c log n ist O(ld n)=O(log n)
 Beispiel: Suche in einem sortierten Binärbaum
search (IN: x:integer; tree:*node; OUT: found:boolean)
{
if tree == nil then
{ // there is no tree to search => x not found
found = false;
return;
// ATTENTION: return already here
}
if (x < node.value) then
search(x,node.left, found)
else
if (x > node.value) then
search(x,node.right,found)
else if (n == node.value)
found=true;
}
239
7.3.3 Rekursion: O(log n) - Zeitbedarf
 Block mit rekursivem Aufruf der/s halben Eingabemenge/-Wertes
rek_block (IN: Eingabemenge OUT: Ausgabewert) {
if ( Trivialfall) then {
Ausgabewert = Trivialwert
}
// optional: Aktionen mit konstantem Aufwand
rek_block (Eingabemenge / 2);
}
 Bestimmung des Zeitbedarfs
 Der Zeitbedarf für das Durchlaufen ergibt sich aus:
 Abfrage des Trivialfalls und (optional) Aktionen  O(1)
 Rekursiver Aufruf mit Eingabemenge/Wert die/der halb so groß ist, also n/2.
 also : Tn = 1 + Tn/2 (Tn = Zeitbedarf für n, n2)
 T1= 0 (eigentlich 1, kann aber vernachlässigt werden)
 Annahme (o.B.d.A.): Eingabemenge/-wert ist Potenz von 2 also n = 2k,
 Diese Annahme kann man machen, denn falls n keine Zweierpotenz ist, erhöht
man die Eingabemenge/-wert auf die nächste 2er Potenz und bekommt noch
immer eine obere Schranke.
 T2k = T2k-1 +1 = T2k-2 +1+1 = ... = T20 + k = k  T2k = k  Tn= k = ld n
240
7.3.3 Rekursion: O(n)
 Rekursive Algorithmen, die in jedem Schritt die Menge der Eingabedaten
halbieren aber dazu jedes Element betrachten müssen haben eine Laufzeit von
O(n)
 Beispiel: Suche in einer sortierter Liste (array) mit 0 am Ende
search (IN: x:integer; list:*liste; OUT: found:boolean) {
i : integer;
if (list[1]==0) then found = false; // list with no element
i=1; while (list[i] != 0) i=i+1
// get length of list
if (x==list[i/2]) then found = true;
else
if (x<list[i/2]) then {
list[i/2+1]=0; search(x,&list[1],found} };
else
search(x,&list[i/2+1],found);
}
 Zeitbedarf: Tn = Tn/2+ n (Tn = Zeitbedarf für n, n2, T1=0)
Annahme (o.B.d.A.): n = 2k,
T2k = T2k-1 + n = T2k-2 + n/2+n = ... = T20 +n/2+n/4+ ... +n = 1+2n  O(n)
241
7.3.3 Rekursion: O(n)
 Rekursive Algorithmen, die die Eingabedaten in zwei Hälften aufspalten, und
beide Hälften getrennt abarbeiten, haben eine Laufzeit von O(n)
 Beispiel: Erstellen eines „Lineals“
lineal (IN: links,rechts,höhe:integer) {
mitte : integer;
if (höhe>0) then {
mitte = (links + rechts) / 2;
zeichne (mitte,höhe);
lineal (links,mitte,höhe-1);
lineal (mitte,rechts,höhe-1); }
}
 Zeitbedarf: Tn = 2Tn/2+ 1 (Tn = Zeitbedarf für n, n2, T1=0)
Annahme (o.B.d.A.): n = 2k,
:2
:2
T2k = 2T2k-1 + 1 
1/2 T2k = T2k-1 + 1/2 = 2T2k-2 + 1 + 1/2

1/4 T2k = T2k-2 + 1/2 + 1/4
 ... :2
1/2k T2k = T20 + 1/2 + 1/4 + ... + 1/2k = 2
*2k
 1/2k T2k = 2  T2k = 2 * 2k  Tn = 2n  Laufzeit O(n)
242
7.3.3 Rekursion: O(n log n)
 Rekursive Algorithmen, die die Eingabedaten in zwei Hälften aufspalten, und die
Eingabedaten einmal durchlaufen, haben eine Laufzeit von O(n log n)
 Beispiel: Sortieren einer Liste a : array[1..max] of integer (C.A.R. Hoare)
 Idee:
 Teile Liste
 laufe von rechts und links gleichzeitig und tausche Elemente so, dass alle Elemente
der linken Hälfte kleiner als die der rechten Hälfte sind.
 Sortiere dannach die „Hälften“.
sort (IN:l,r:integer) {
// l left, r right index
i,j,x : integer; // i,j: indexes, x,y: elements
i=l; j=r;
// initialize i with left, j with right index
x = a[(l+r)/2}] // get element in the middle
do { // walk with i from left, with j from right
while a[i]<x { i=i+1 }
// skip smaller elements from left
while a[j]>x { j=j-1 }
// skip larger elements from right
if (i<=j) then { exchange(a[i],a[j]); i=i+1; j=j-1 }
} while i<=j // i is now right of j -> stop loop
if l<j then sort(l,j);
// sort left part (only if exists)
if i<r then sort(i,r);
// sort right part (only if exists)
 Zeitbedarf: Tn = 2Tn/2+ n (Tn = Zeitbedarf für n, n2, T1=0)
Annahme (o.B.d.A.): n = 2k, (d.h. k = ld n)
k
 T2k = 2T2k-1 + 2k :2
 k 1/2k T2k = T2k-1/2k-1 + 1 = T2k-2/2k-2 + 1 + 1 = ... = k
 1/2k T2k = k x2 T2k = 2k k  Tn = n ld n  Laufzeit O(n log n)
243
7.3.3 Rekursion: O(n2)
 Rekursive Algorithmen, die die Eingabedaten jeweils um eins verringern, dabei
aber alle Daten betrachten müssen, haben eine Laufzeit von O(n2)
 Beispiel: Sortieren einer Liste a : array[1..max] of integer
StraightSelection (IN:l,r:integer) { // l left, r right index
i: integer;
// index
i = l;
// start with left element
while (i<r) {
// walk through complete list
// if an element is smaller, bring it to the left
if (a[i]<a[l]) then exchange(a[i],a[l]);
i = i+1;
}
if (l<r) then StraightSelection (l+1,r);
}
 Zeitbedarf: Tn = Tn-1+ n (Tn = Zeitbedarf für n, n2, T1=1)
Tn = Tn-1 + n = Tn-2 + n-1 + n = Tn-3 + n + n-1 + n-2 = ... = n+…+3+2+1
 Tn = (n(n+1))/2 = 1/2n2 + 1/2n  Laufzeit O(n2)
244
7.3.3 Rekursion: Vergleich
1.
O(log(n))
z.B. Suche in binären Bäumen
 Tn = Tn/2 + 1
Aufruf mit halber Menge
 T2k = T2k-1 +1 = T2k-2 +1+1 = ... = T20 + k = k  T2k = k  Tn= k = ld n
2.
O(n)
z.B. Sortieren 0-terminierter Arrays
 Tn = Tn/2+ n
Durchlaufen der Menge, Aufruf mit halber Menge,
 T2k = T2k-1 + n = T2k-2 + n/2+n = ... = T20 +n/2+n/4+ ... +n = 1+2n O(n)
3.
O(n)
z.B. Lineal-Algorithmus
 Tn = 2Tn/2+ 1
 T2k = 2T2k-1 + 1 
2-maliges Aufrufen mit halber Menge
1/2 T2k = T2k-1 + 1/2 = 2T2k-2 + 1 + 1/2
1/4 T2k = T2k-2 + 1/2 + 1/4
 ... 
1/2k T2k = T20 + 1/2 + 1/4 + ... + 1/2k = 2
 1/2k T2k = 2  T2k = 2 * 2k  Tn = 2n  Laufzeit O(n)
4.
O(n log(n))
 Tn = 2Tn/2+ n
 T2k = 2T2k-1 + 2k
 1/2k T2k = k
5.
O(n2)

z.B. Quick-Sort
Durchlaufen der Menge, 2-maliges Aufrufen mit halber Menge

1/2k T2k = T2k-1/2k-1 + 1 = T2k-2/2k-2 + 1 + 1 = ... = k

T2k = 2k k  Tn = n ld n  Laufzeit O(n log n)
z.B. Sortieren durch Voranstellen des kleinsten Elementes
 Tn = Tn-1+ n
Durchlaufen der Menge, Aufrufen mit verkleinerter Menge
 Tn = Tn-1 + n = Tn-2 + n-1 + n = Tn-3 + n-1 + n-2 + 1 = ... = n+…+3+2+2
 Tn = (n(n+1))/2 = 1/2n2 + 1/2n  Laufzeit O(n2)
245
7.3.3 Rekursion: Lehre
 Suche Algorithmen, die durch Teilung der Eingabemenge zu einer Lösung
kommen ( Binärsuche, Quicksort)
 Grundsatz der Algorithmierung: Divide et impera – Teile und Herrsche
 Dazu sind immer „günstige“ Eigenschaften der Eingabemenge auszunutzen
 Beispiel: Strukturierung als Baum, Sortierung, …
 Der Teilungsquotient ist dabei grundsätzlich egal
 … da logxn = c * logyn
 Beispiel: Suche in binären Bäumen, Suche in Hexadezimalbäumen (z.B.
Kennzahlbäume beim Telefonieren)
 Ein bloßes Verringern (als kein Teilen) der Eingabemenge ist oft nicht wirklich
geschickt ( Sortieren, durch Voranstellen des kleinsten Elementes)
 nur durch Anwendung von Rekursion wird eine Algorithmus nicht wirklich gut
(schnell)
 Vermeide bei rekursiven Algorithmen - wenn möglich - lineare Suche
( Sortieren 0-terminierter Arrays)
 In manchen Fällen kann so etwas aber Sinn machen ( siehe nächste Folie)
 Ausnahmen bestätigen diese Regeln
 insbesondere bei kleinen (nicht statistisch relevanten) Eingabemengen
 bei stark unterschiedlichen Laufzeiten von Einzelanweisungen
246
7.3.3 Iteration: O(n)
 Iterative Algorithmen die eine lineare Liste durchlaufen deren Länge abhängig
von der Menge der Eingabeelemente ist (einfache Schleife), haben die Laufzeit
O(n)
 Beispiel: Suche in einer sortierter Liste (array) mit 0 am Ende
search (IN: x:integer; list:*liste; OUT: found:boolean) {
i : integer;
found = false; // initialize OUT-value
i=1;
while ((list[i] != 0) and (not found)) {
if (list[i]==x) then found = true;
i=i+1;
}
}
 Anmerkung:
 Dieser Algorithmus funktioniert auch mit unsortierten Listen
 Warum dann einen rekursiven, teilenden Algorithmus ?
 Anzahl „eingeschränkter“ Vergleiche O(n)
 Anzahl „vollständiger“ Vergleiche O(log n)
247
7.3.3 Iteration: O(nx)
 Iterative Algorithmen die eine Liste - deren Länge abhängig von der Menge der
Eingabeelemente ist - (fast) sooft durchlaufen, wie die Liste lang ist (doppelt
verschachtelte Schleife), haben die Laufzeit O(n2)
 Beispiel: Sortieren einer Liste a : array[1..max] of integer
StraightSelection (IN:l,r:integer) { // l left, r right index
i: integer;
// index
i = l;
// start with left element
for i=1 to r-1
// walk through complete list
{
for j=i+1 to r // walk through rest of list
{
if (a[j]<a[i]) then exchange(a[i],a[j]);
}
}
}
 Dreifach verschachtelte Schleifen haben eine Laufzeit von O(n3)
 Beispiel: Multiplikation zweier Matrizen
 x-verschachtelte Schleifen haben (i.A.) eine Laufzeit von O(nx)
 x>3 macht keinen Sinn und deutet auf ein Strukturierungsproblem des
Algorithmus hin (i.A. !)
248
7.3.4 Einige Regeln
 Hat ein Algorithmus eine Laufzeit, die mit einem Polynom k-ten Grades
darstellbar ist (aknk + ak-1nk-1 + ... + a0) , so ist die Laufzeit O(nk)
 Beispiel:
Laufzeit: 9n3 + 7n - 1000  Laufzeit O(n3)
 Wird ein Teil A mit Laufzeit O(x) vor einem Teil B mit Laufzeit O(y) ausgeführt, so
ist die Gesamtlaufzeit das Maximum der Laufzeiten.
 Beispiel:
Laufzeit A ist O(n2), Laufzeit B ist O(n)
 Laufzeit A,B = O(n2) + O(n) = O(n2)
 Wird ein Teil A mit Laufzeit O(x) innerhalb eines Teiles B mit Laufzeit O(y)
ausgeführt, so ist die Gesamtlaufzeit das Produkt der Laufzeiten.
 Beispiel:
 Beispiel:
Laufzeit A ist O(n2), Laufzeit B ist O(n)
 Laufzeit A(B) = Laufzeit B(A) = O(n2)  O(n) = O(n3)
Eine Dreifach verschachtelte Schleife (O(n3)) ist eine
Schleife O(n) in einer zweifach verschachtelten
Schleife (O(n2)) : O(n3) = O(n2)  O(n)
249
7.3.5 Quantitatives
n
ld n
(ld n)2
n
n ld n
n2
10
100
1000
10000
100000
1000000
3
6
9
13
16
19
9
36
81
169
256
361
3
10
31
100
316
1000
30
600
9000
130000
1,6 106
19 106
100
1000
1000000
108
1010
1012
nicht gut
sehr gut
sehr gut
gut
gut
schlecht
… alles (viel) schlechter als n2, insbesondere schlechter als polynomial
( > nx ), ist praktisch nicht anwendbar, dies gilt insbesondere für n! und xn
250
7.3.6 Platzbedarf
 Unter „Aufwand“ wird i.A. der zeitliche Aufwand, also die Zeitkomplexität
verstanden
 Manchmal ist auch die Platzkomplexität bzw. Speicherbedarf relevant.
Darunter versteht man dann, ganz entsprechend zur Zeitkomplexität, eine
obere Schranke für den Speicherbedarf eines Algorithmus für ein Problem mit
einer Eingabemenge der Größe n.
 Auch beim Speicherbedarf von Algorithmen existieren die „Komplexitätsklassen“ (n,
n2, n log n, ...)
 Auch beim Speicherbedarf unterscheiden sich „geschickte“ und „ungeschickte“
Algorithmen für die Lösung eines gegebenen Problems.
 Da Computerspeicher endlich, die Zeit aber potentiell unendlich ist hat der
Speicherbedarf oft die höhere Priorität.
 Meist wird daher der Algorithmus gewählt, der sehr Nahe am minimal möglichen
Speicherbedarf bei möglichst optimalem Aufwand liegt.
251
7.3.6 Platzbedarf
 Oft kann man eine bessere Zeitkomplexität zu Lasten des Speicherbedarfs
erreichen (und umgekehrt)
 Beispiel: Trivialer Hashsort (Unsortierte Liste a: array [1..n] of type)
b: array [1..max(type)]
// max(type) is largest element in type,
// e.g. max(unsigned integer) = 65535
i,j : integer;
for i=1 to n {
b[a[i]] = a[i];
}
j = 1;
for i=1 to max(type) { // shift to beginning of list
if ((not_empty(b[i])) and (i<>j)) then
{ b[j]=b[i]; j=j+1;}
}
 1.Schleife + 2.Schleife: O(n) + O(1) = O(n)
 Man wägt daher Speicherbedarf und Zeitkomplexität gegeneinander ab.
252
7.4
Zusammenfassung des Kapitels
 Berechenbarkeit:
1. Einige Fragen und das Entscheidungsproblem
2. Die Turing-Maschine und der Begriff der Berechenbarkeit
3. Rekursive Funktionen und die Church‘sche These
 Korrektheit
1.
2.
3.
4.
Ansatz und Definition
Logik zur Verifikation: Die Hoare‘schen Regeln
Beispiele
Kritische Anmerkungen
 Komplexität
1.
2.
3.
4.
Wie „gut“ ist ein Algorithmus und die O-Notation
Häufige O-Ausdrücke und einige Regeln bei deren Anwendung
Quantitatives
Platzbedarf
253
Anhang ASpiel des Lebens
Das Spiel des Lebens findet in einer Welt statt, die einfachen Regeln gehorcht. Die
Welt besteht aus einem unendlich großen Schachbrett in dessen Feldern primitive
Tierchen, die “Nöpel” wohnen. Diese sitzen ein Jahr unbeweglich auf ihren Feldern,
unterhalten sich mit ihren Nachbarn - es gibt erhitzte Diskussionen,
Gedichtvorträge, Tratsch und Klatsch über andere Nöpel, politische Reden,
Deklamationen, Verleumdungen und Schmeicheleien.
Jedes Jahr genau um 12 Uhr in der Silvesternacht lösen sich Nöbel entweder in
Luft auf, bleiben sitzen oder werden aus dem Nichts erschaffen.
Dabei schlägt das Schicksal nicht blind zu:
 Hat ein Nöpel (von acht möglichen) keinen oder nur einen Nachbarn, so stirbt
er an Vereinsamung.
 Hat ein Nöpel vier oder mehr Nachbarn, so stirbt er an Erschöpfung ob der
vielen Plaudereien.
 Überleben tun Nöbel mit zwei und drei Nachbarn.
 Nöpel werden auf leeren Feldern geboren, wenn dort im Jahr zuvor genau drei
Nöpel gelebt haben
254
A.1
Die Generationen
 0,1,4,5,6,7,8
 2,3
3
255
A.2
Interessante Völker
 Der Gleiter
 Der Blinker
256
A.3
1.
2.
3.
4.
5.
6.
Rechnerdarstellung
Wie kann man strukturell und algorithmisch dieses Spiel auf einem Rechner
darstellen ?
Überlegen Sie sich Rahmenbedingungen für das Spiel des Lebens
Formalisieren Sie dieses Problem
Stellen sie einen umgangssprachlichen Lösungsansatz auf
Formalisieren Sie den Lösungsansatz als Algorithmus
Spielen Sie den Algorithmus anhand eines Beispieles durch
Bewerten Sie den Algorithmus bezüglich seine Laufzeit und seines
Platzbedarfes
257
A.4
Formalisierung
Gegeben ist:
Eine zweidimensionales „Spielfeld“
Annahme:
die Grenzen werden verbunden.
Auch möglich:
„Unendliche“ Grenzen, „abschneidende“ Grenzen
Anfangszustand:
beliebige Nöpelpositionen im Spielfeld
Regeln:
entsprechend der Spielregeln für „Spiel des Lebens“
Gesucht:
„Zwischenzustand“ nach beliebigen Generation (entsprechend der Regeln)
Optional: Erkennung von „Endzuständen“
258
A.4
Strukturen
Entwurf der Datenstrukturen - zwei Ansätze:
Der Spielfeldzustand wird als zweidimensionales Feld repräsentiert
act_state: array [1..max_reihen][1..max_spalten] of boolean;
0
0
1
0
0
0
0
0
1
1
1
0
0
0
0
0
1
0
0
0
0
...
...
Der Spielfeldzustand wird über die Positionen der Nöpel präsentiert
typedef struct nöpel {reihe: int;
spalte: int ; // next_nöpel: *nöpel
} ;
act_state: array [1..max_nöpel] of nöpel;
1
3
2
2
2
3
2
4
3
3
...
259
A.4
Algorithmus: Feld
act_state = Startzustand
solange kein Endzustand {
get_next_state (act_state, next_state);
}
 0,1,4,5,6,7,8
 2,3
3
get_next_state (In: act_state, Out: next_state)
{ // iterate fields an set nöpel accordingly
// determine survivors
durchlaufe act_state // zweifach-verschachtelte Schleife
{
falls act_state[act_field] hat 2,3 Nachbarn in act_state
setze next_state[act_field]
}
// determine babies
durchlaufe next_state // zweifach-verschachtelte Schleife
{
falls next_state[act_field] hat 3 Nachbarn in act_state
setze next_state[act_field]
}
}
260
A.4
Algorithmus: Liste
act_state = Startzustand
solange kein Endzustand {
get_next_state (act_state, next_state);
}
 0,1,4,5,6,7,8
 2,3
3
get_next_state (In: act_state, Out: next_state)
{ // iterate through list
durchlaufe act_state // einfache Schleife durch Nöpelliste
{
// determine survivors
find_neighbors(act_nöpel, no_of_neighbors)
falls no_of_neighbors = 2 oder 3
kopiere act_nöpel nach next_state
// determine babies
durchlaufe nachbar_nöpel von act_nöpel // max. 8
{
find_neighbors(nachbar_nöpel, no_of_neighbors)
falls no_of_neighbors = 3
kopiere nachbar_nöpel nach next_state
}
}
}
261
A.4
Komplexität
get_next_state (In: act_state, Out: next_state)
{
durchlaufe act_state // einfache Schleife durch Nöpelliste
{
// determine survivors
find_neighbors(act_nöpel, no_of_neighbors) // Durchsuche
// alle Nöpel
falls no_of_neighbors = 2 oder 3
kopiere act_nöpel nach next_state
// determine babies
durchlaufe nachbar_nöpel von act_nöpel // max. 8
{
find_neighbors(nachbar_nöpel, no_of_neighbors)
falls no_of_neighbors = 3
kopiere nachbar_nöpel nach next_state
}
} // Zeit: Nöpel * ( Nöpel + ( 8 * Nöpel ) ) = 9 * Nöpel 2
}
// Platz: 2 * Nöpel
262
263
Beispielklausur
… daran will ich euch prüfen
1. Mose 42.15
 In diesem Kapitel wird ein Beispiel für eine Klausur vorgestellt. Dabei sind
jeweils die Aufgaben und die Lösungen gegeben.
 Beachten Sie
 Diese Beispielklausur erhebt weder in Form, Inhalt noch Umfang einen Anspruch auf
Vollständigkeit.- dies betrifft insbesondere reine Wissensfragen, die hier etwas
vernachlässigt sind.
 Grundsätzlich ist der gesamte in der Vorlesung und den Übungen behandelte Stoff
möglicher Gegenstand der Prüfung
 Vorbereitung
 Arbeiten Sie die gesamten Folien nochmals durch
 Bearbeiten Sie alle Übungsaufgaben nochmals
 Arbeiten Sie das Skript von Herrn Geise durch
 Bearbeiten Sie dessen Übungsaufgaben
Bedenken Sie: In der Klausur sind keine Hilfsmittel zugelassen.
264
Informatik
 Informatik ist ...
Die Wissenschaft, die sich mit dem
(automatisierten)
Erfassen
Transportieren
Speichern
Verarbeiten
Umsetzen
von Information befasst
 Geben Sie für jede dieser 5 „Kernprozesse“ der Informatik jeweils 3 Beispiele an
265
Informatik
 Fehlt in dieser Beispielklausur:
a) weitere Wissensfragen
b) ...
266
Information

Eine Nachrichtenquelle sendet Zeichen aus dem Alphabet
X = {a,b,c,d,e} mit den Wahrscheinlichkeiten p(a)=1/2, p(b)=p(c)=p(d)=p(e)=1/8
a)
b)
c)
d)
e)
Wie groß ist der Informationsgehalt der einzelnen Zeichen
Wie groß ist der Informationsgehalt der Nachricht „abc“
Wie groß ist der mittlere Informationsgehalt einer Nachricht mit 1000 Zeichen
Finden Sie einen möglichst optimalen Code für dieses Alphabet
Angenommen die Wahrscheinlichkeiten wären
p(b)=1/2, p(a)=p(c)=p(d)=p(e)=1/8 .
Wie groß wäre dann die Redundanz Ihres Codes aus Aufgabe d) bzgl. der neuen
Wahrscheinlichkeiten
 Hamming
a) Codieren Sie die Binärzahl 1000 mit der Hamming-Methode
b) Wieviele Bits können als fehlerhaft erkannt werden ?
c) Wieviele Bits können korrigiert werden ?
267
Information
 Fehlt in dieser Beispielklausur:
a) „Textaufgaben“
b) Turing-Maschinen
c) …
268
Zahlensysteme
 Stellen Sie die Dezimalzahl 7,25
a) Binär
b) Hexadezimal
c) Oktal
dar
 Berechnen Sie im Binärsystem (mit Vollständiger Rechnung)
a) 1100100 : 101
b) Machen Sie schriftlich die Gegenprobe (auch im Binärsystem)
c) 10111 – 1010 (durch Addition des Zweierkomplements)
269
Zahlensysteme
 Fehlt in dieser Beispielklausur:
a) Gleitpunktzahlen
b) IEEE 754
c) ...
270
Datenstrukturen

Gegeben ist folgende Struktur
...
a)
b)
c)
d)
Vorname
Vorname
Vorname
Nachname
Nachname
Nachname
...
Definieren Sie Datenstrukturen, mit denen diese Struktur einer zweifach verketteten Liste
repräsentiert werden kann.
Begründen Sie, weshalb diese Datenstruktur als „dynamisch“ bezeichnet wird (im Gegensatz zu
statisch)
Geben Sie jeweils zwei Gründe für die Verwendung dynamischer bzw. statischer Datentypen an.
Definieren Sie statische Datenstrukturen, mit denen man die oben aufgezeichnete Struktur
möglichst vollständig abbilden kann.
271
Datenstrukturen
 Gegeben ist folgender Algorithmus:
x : *Integer; y : Integer;
x = &y;
x* = 2;
x = 2;
x* = 5;
a) Gehen Sie davon aus, dass der Compiler der Variablen x die Speicherstelle 4 und
der Variablen y die Speicherstelle 6 zugeordnet hat. Jede Variable belegt dabei
genau eine Speicherstelle:
Zeichnen Sie die Werte in den Speicherstellen 1 bis 8 jeweils nach den
Zuweisungen.
272
Datenstrukturen
 Fehlt in dieser Beispielklausur:
a) Wissensfragen (z.B. Überblick über Datenstrukturen)
b) spezielle Datenstrukturen (z.B. Variantenrecord)
c) ...
273
Algorithmus + Theorie
 Gegeben ist folgender Algorithmus:
x=a, y=5;
while (x>0)
{
y = y+1;
x = x-1;
}
a)
b)
c)
Formen sie die while Schleife in eine repeat-Schleife um
Bilden Sie die Funktion dieses Algorithmus‘ ohne Schleifen, mit Hilfe von Sprüngen und Marken
nach
Was macht dieser Algorithmus ?
Formulieren Sie Ihre Antwort als sinnvolle Nachbedingung, wobei Sie als Vorbedingung davon
ausgehen können, das aN+
274
Algorithmus + Theorie
 Gegeben ist folgender Algorithmus
test ( IN:
x:Integer;
THROUGH: y:Integer; b:Integer;
OUT:
z:Integer;
)
{
x = y + b;
b = y + x;
}
c = 3; d = 5; e = 7; f = 9;
test (f,e,c,d);
c >> Bildschirm;
d >> Bildschirm;
e >> Bildschirm;
f >> Bildschirm;;
a) Geben Sie die Bildschirmausgabe an
275
Algorithmus + Theorie
 Fehlt in dieser Beispielklausur:
a)
b)
c)
d)
e)
f)
Weitere Umformungen
Umwandlung Rekursion/Iteration
Wissensfragen (z.B. Überblick über Strukturierungselemente)
weitere Notationen (Nassi-Shneidermann, Flußdiagramm)
Komplexitätsbetrachtungen
...
276
Lösung: Informatik
 Information erfassen über:
 Kamera, Tastatur, Maus, Datenleitung, Tastsensoren, Gehirnsensoren, ...
 Information Transportieren über Ethernet:
 WLAN, ISDN, S/ADSL, Datenbus, Druckerkabel, VGA-Kabel, verschränkte
Quantenzustände, ...
 Information speichern auf:
 Festplatte, EPROM, RAM, ROM, CD, DVD, Tape, Tesa-Film, ...
 Information verarbeiten mit:
 Analogrechner/Digitalrechner, Parallelrechner, CPU, FPU, Mikro-Prozessor,
Turing-Maschine, ...
 Information umsetzen als:
 Ausgabe auf dem Bildschirm, Drucker, Braille-Zeile, Roboter-Aktion,
Schalten, optisches/akustisches Signal, Raketenstart, ...
277
Lösung: Information

Eine Nachrichtenquelle sendet Zeichen aus dem Alphabet
X = {a,b,c,d,e} mit den Wahrscheinlichkeiten p(a)=1/2, p(b)=p(c)=p(d)=p(e)=1/8
a)
b)
c)
d)
e)
h(a) = -ld(1/2) = 1bit. h(b)=h(c)=h(d)=h(e)=-ld(1/8)=3bit
1bit + 3bit + 3bit = 7 bit
1000 x Mittlerer Informationsgehalt: H(x)=p(xi)h(xi) =
1000 x ( 1/2x1 + 1/8x3 + 1/8x3 + 1/8x3 + 1/8x3 )bit = 1000 x 2bit = 2000 bit
Nach Huffmann: p(de)=1/4, p(bc)=1/4, p(debc)=1/2, p(a)=1/2). p(abcde)=1
also z.B.: a=1, b=000, c=001, d=010, e=011
Redundanz = L(x)-H
l(x)=1bit , l(b)=l(c)=l(d)=l(e)=3bit (entsprechend der Codierung in d.)
L(x) = p(xi)l(xi) = (0,125x1 + 0,5x3 + 0,125x3 + 0,125x3 + 0,125x3)bit = 2,75 bit
h(b) = 1bit, h(a)=h(c)=h(d)=h(e)=-ld(1/8)=3bit
H(x) = p(xi)h(xi) = (0,5x1 + 0,125x3 + 0,125x3 + 0,125x3 + 0,125x3 )bit = 2 bit
Redundanz = L(x)-H = 2,75bit – 2bit = 0.75 bit
 Hamming
a) 100P0PP (Relevant: Bit 3,5,7)  100P0P1 (even Parity: also 1 ergänzen)
100P0P1 (Relevant: Bit 3,6,7)  100P011 (even Parity: also 1 ergänzen)
100P011 (Relevant: Bit 5,6,7)  1001011 (even Parity: also 1 ergänzen)
b) Der Hamming-Abstand D ist 3bit, es können D-1 = 2bit Fehler erkannt werden
c) Es können (D-1)/2 = 1bit Fehler korrigiert werden.
278
Lösung: Zahlensysteme

Dezimalzahl 7,25
a)
b)
c)

Vorkommateil:
7 : 2 = 3 Rest: 1
3 : 2 = 1 Rest: 1
1 : 2 = 0 Rest: 1 -> 111
Binärzahl: 111.01
0111,01002 = 7,416 (7 * 160 + 4 * 16-1)
111,0102 = 7,28 (7 * 80 + 2 * 8-1)
Nachkommateil
2 · 0,25 = 0,5 --> Ziffer: 0
2 · 0,5 = 1
--> Ziffer: 1
->0,01
Berechnung

1100100 : 101 = 10100
101
--101
101
--000

10111 – 1010
10111 - 01010 auf gleiche Längen bringen
10111 + 10110 Binärkomplement 10101+ 1
= 101101
Lösung: 1101 Überlauf weggelassen
10100 x 101
10100
00000
10100
------1100100
279
Lösung: Datenstrukturen
 Doppelt verkettete Liste
a) Person : record
{ vorname : array[1..64] of char;
nachname: array[1..64] of char;
prev
: *Person;
next
: *Person;
}
b) Man kann aus diesen Strukturen beliebig lange Ketten von Personen bilden
c) Pro: Dynamisch: Verwaltung von Objekten, deren Anzahl zur Entwicklungszeit nicht
bekannt ist. Speicherverbrauch nur für die Objekte, die tatsächlich zur Laufzeit
existieren.
Pro Statisch: Einfach in der Realisierung, schnell in der Bearbeitung
(Fehlerunanfälliger)
d) Person : record
{ vorname : array[1..64] of char;
nachname: array[1..64] of char;
}
Personenliste: array[1...65534] of Person;
280
Lösung: Datenstrukturen
x : *Integer;
y : Integer;
x
x*
x
x*
=
=
=
=
&y;
2;
2;
5;
5
x
y
6
nd
6
2
2
2
2
2
281
Lösung: Algorithmus + Theorie
 Umformung der while-Schleife:
a)
b)
Als repeat-Schleife:
x=a; y=5;
if (x>0)
{
repeat
{
y = y+1;
x = x–1;
} until (x<=0)
}
Sprünge und Marken
x=a; y=5;
1: if (x<=0) goto 2
y = y+1;
x = x–1;
goto 1;
2: ...
do
{
y = y+1;
x = x-1;
} while (x>0}
x=a; y=5;
1: if (x>0)
{
y = y+1;
x = x–1;
goto 1
}
2: ...
282
Lösung: Algorithmus + Theorie
x=a; y=5;
while (x>0)
{
y = y+1;
x = x-1;
}
a
x
y
4
4
5
---------4
3
6
4
2
7
4
1
8
4
0
9
Invariant:
5 + a = x + y
------------5 + a = x + y
5 + a = x + y
5 + a = x + y
5 + a = x + y
------------Nachbed.: y = 5 + a
 { aN+  a>0 }
x = a; y = 5;
{ x=a, y=5, a>0 }  { 5+a=x+y, x≥0 }
while (x>0) {
{ 5+a=x+y, x≥0, x>0 }  { 5+a=x+y+1-1, x>0 }
y = y+1;
{ 5+a=x+y-1, x>0 }  { 5+a=x-1+1+y-1, x-1+1>0 }
x = x-1;
{ 5+a=x+1+y-1, x+1>0 }  { 5+a=x+y, x≥0 }
}
{ 5+a=x+y, x≥0, x≤0 }  { 5+a=x+y, x=0 }  5 + a = y
283
Lösung: Algorithmus + Theorie
 Gegeben ist folgender Algorithmus
test ( IN:
x:Integer;
THROUGH: y:Integer; b:Integer;
OUT:
z:Integer;
)
{
x = y + b;
Rechnung:
b = y + x;
(ROT = call by
}
c d e f
c = 3; d = 5; e = 7; f = 9;
3 5 7 9
test (f,e,c,d);
b z y x
c >> Bildschirm;
3 5 7 9
d >> Bildschirm;
3 5 7 10
e >> Bildschirm;
f >> Bildschirm;
17 5 7 10
reference)
test(f,e,c,d)
x = y + b
b = y + x
Ausgabe:
17
5
7
9
284
Herunterladen