Martin Rippel Wissenschaftliches Rechnen I Zusammenfassung der Vorlesung von Prof. Nicolas Gauger (WS 08/09) Inhaltsverzeichnis 1 Aufbau und Arbeitsweise eines Computers 1.1 Organisation des Arbeitsspeichers (Bits und Bytes) . . . . . . . . . . . . . 1.2 Organisation des Arbeitsspeichers (Adressen) . . . . . . . . . . . . . . . . . 3 4 6 2 Was ist eine Programmiersprache? 2.1 Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 9 3 Zahlendarstellung im Computer 10 4 Algorithmen und ihre Darstellung 4.1 Automatendefinition . . . . . . . . . . . . 4.2 wesentliche Eigenschaften von Algorithmen 4.3 Grundelemente beschränkter Algorithmen 4.4 effiziente Algorithmen . . . . . . . . . . . . . . . 12 12 12 13 15 5 Programmbeispiel: Zufallssumme 5.1 Bentfortsche Gesetz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 16 6 Datenstrukturen 6.1 Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 Graphen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3 Bäume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 17 18 19 7 Suchen 7.1 lineares Suchen . . . . . . . . 7.2 binäres Suchen . . . . . . . . 7.3 Hashing . . . . . . . . . . . . 7.4 Teilen + Herschen, Laufzeiten . . . . 19 19 20 20 21 . . . . 23 25 26 27 27 9 Grundlagen der Fehleranalyse 9.1 Normen, Vektoren und Matrizen . . . . . . . . . . . . . . . . . . . . . . . . 9.2 Kondition von Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3 Rundungsfehlerfortpflanzung . . . . . . . . . . . . . . . . . . . . . . . . . . 28 28 33 36 8 Sortieren 8.1 Bubble-Sort . . . 8.2 Quick-Sort . . . . 8.3 Merge-Sort . . . . 8.4 Übersichtstabelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vorbemerkung : Dies ist eine Zusammenfassung der wesentlichen Inhalte der Vorlesungen und zum Teil auch der Übungen des Moduls Wissenschaftliches Rechnen I gehalten von Prof. Nicolas Gauger im Rahmen des Diplomstudiengangs Mathematik an der Humboldt-Universität Berlin im Wintersemester 2008 / 2009. Sie erhebt weder Anspruch auf Richtigkeit noch auf Vollständigkeit. Urheberrecht : Diese Zusammenfassung steht unter der Creative Commons Lizenz (by-nc-sa). Es ist Ihnen somit gestattet das Werk zu vervielfältigen, verbreiten, öffentlich zugänglich machen und Abwandlungen bzw. Bearbeitungen des Inhaltes anzufertigen, solange Sie folgende drei Punkte beachten: 1. Namensnennung Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen. 2. Keine kommerzielle Nutzung Dieses Werk darf nicht für kommerzielle Zwecke verwendet werden. 3. Weitergabe unter gleichen Bedingungen Wenn Sie den lizenzierten Inhalt bearbeiten oder in anderer Weise umgestalten, verändern oder als Grundlage für einen anderen Inhalt verwenden, dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von Lizenzbedingungen weitergeben, die mit denen dieses Lizenzvertrages identisch oder vergleichbar sind. Weitere Informationen dazu finden sie unter: http://creativecommons.org/licenses/by-nc-sa/3.0/deed.de Dank : Mein Dank für Hilfe und Unterstützung geht an Dennis Groh und Paul Boeck. 2 1 Aufbau und Arbeitsweise eines Computers Begriffe und Erklärungen Computer: Rechner Datenverarbeitung: Egal, was ein Computer tut, er verarbeitet immer Daten Programm: Datenverarbeitungsregeln Dateneingabe: Ermöglicht Eingabe von Daten und Datenverarbeitungsregeln Dateneingabegeräte: Tastatur, Maus, .. Datenausgabe: Ermöglicht Weiterverwendung der vom Computer verarbeiteten Daten Datenausgabegeräte: Bildschirm, Drucker, Soundkarte, ... Speicher: Hier merkt“ sich der Computer die zu verarbeitenden Daten ” RAM: Random Access Memory, Teil des so genannten Arbeitsspeichers. Flüchtiger Speicher bedeutet, dass alle hier gespeicherten Daten nach dem Ausschalten des Computers verloren gehen. In der Regel werden im RAM alle vom Computer zu verarbeitenden Daten und Programme vor der Verarbeitung hierher übertragen CPU: Central Processing Unit = Zentraleinheit, wird auch Prozessor genannt, arbeitet im Arbeitsspeicher enthaltene Programme ab Nicht-flüchtiger Speicher: Festplatte, Diskette, CD-ROM, ... ROM: Read-only Memory, nicht-beschreibbarer Teil des Arbeitsspeichers, nicht-flüchtiger Speicher Betriebssystem: auch OS (Operating System) oder DOS (Disk Operating System) genannt. Ein sehr umfangreiches Programm, welches den Computer durch Menschen nutzbar macht, ermöglicht z.B. die Kommunikation Benutzer-Computer 3 1.1 Organisation des Arbeitsspeichers (Bits und Bytes) Alle Daten und Programme müssen vor ihrer Verarbeitung im RAM abgelegt werden. Auf der physikalischen Ebene ist das RAM aus unzähligen elektrischen Kondensatoren und Transistoren aufgebaut. Ein Kondensator kann dabei in einem von zwei Zuständen sein: entweder er trägt elektrische Ladung oder er ist entladen. Eine Speichereinheit, die nur zwei Zustände annehmen kann, nennen wir Bit, und die beiden Zustände eines Bits beziffern wir mit 0 und 1. Zum Beispiel könnte dem durch einen ungeladenen bzw. geladenen Kondensator repräsentierten Bit der Wert 0 bzw. 1 zugeordnet werden. Da ein Bit nur sehr kleine Informationsmengen speichern kann, werden mehrere Bits zu größeren Einheiten gruppiert. Sicher haben Sie auch schon Werbeslogans gehört, in welchen für 32-Bit-Betriebssysteme oder 32-Bit-Prozessoren geworben wird. Ein 32-Bit-Prozessor ist in der Lage immer 32 Bit auf einmal aus dem Speicher zu lesen und als Einheit zu verarbeiten. Ein älterer 16-Bit Prozessor hingegen verarbeitet Daten immer in 16-Bit-Portionen. Da ein 16-Bit-Prozessor nur 16 Bit auf einmal verarbeiten kann, müsste er zweimal auf den Speicher zugreifen, um 32 Bit zu lesen, und er müsste zwei Operationen ausführen, um 32 Bit zu verarbeiten. Die Anzahl von Bits, die ein Prozessor auf einmal verarbeiten kann, nennt man die BusBreite des Prozessors. Ein Bus ist ein Bündel von Leitungen, über das Daten transportiert werden. Wenn die zu verarbeitenden Daten in größeren Gruppen als 16 Bit vorliegen, kann ein 32-Bit-Prozessor also tatsächlich schneller sein als ein 16-Bit Prozessor. Allerdings müssen die benutzten Programme dazu auch wirklich eine Verarbeitung in 32-Bit-Portionen vorsehen. Beispiele : Wenn wir ein Bit verwenden, können wir nur die zwei Zustände 0 und 1 darstellen. Wenn wir zwei Bits verwenden, können wir die vier Zustände 00, 01, 10, 11 darstellen. Drei Bits können die acht Zustände 000, 001, 010, 011, 100, 101, 110, 111 darstellen. Es ist leicht zu sehen, dass n Bits genau 2n verschiedene Zustände annehmen können. Will man also N verschiedene Zustände beschreiben, benötigt man eine Anzahl von Bits, die sich durch Aufrunden von log2 N ergibt. Beispiele : Um jede Zahl von 0 bis 15 darstellen zu können, benötigt man log2 16 = 4 Bits. Zur Darstellung der Zahlen 0 . . . 100 sind 7 Bits nötig (log2 101 = 6, 66). Die wichtigsten Einheiten, zu denen Bits zusammengefasst werden, sind: • Byte: Ein Byte besteht aus 8 Bit und kann folglich 28 = 256 Zustände annehmen. 4 • Word: Die Größe eines Word hängt ursprünglich vom verwendeten Computer ab. Es besteht in der Regel aus so vielen Bits, wie der Computer zugleich erarbeiten kann. Heutzutage versteht man unter einem Word meist 8 Byte oder 64 Bit. Meist verwendet man die Begriffe Byte oder Word, um einen einzelnen Zahlenwert zu beschreiben. Jedem Zustand eines Bytes oder Words kann man eine Dezimalzahl zuweisen. Dazu fasst man die Zustände der einzelnen Bits als Binärzahl auf. Der Dezimalwert einer Binärzahl berechnet sich wie folgt: Die Bits der Zahl werden von rechts beginnend und mit der Zahl 0 startend durchnummeriert. Anschließend bildet man eine Summe, in welcher man für jedes an der Position i gesetzte Bit die Zahl 2i einsetzt. Beispiele : Die Binärzahl 010 hat die Dezimaldarstellung 21 = 2. Die Binärzahl 010100100 hat die Dezimaldarstellung 22 + 25 + 27 = 164. Computer verwenden meist Byte-Werte, um Buchstaben und andere Zeichen zu beschreiben. Dabei wird jedem Zeichen ein anderer Zahlenwert zugewiesen. Beispiele : Zeichen Zahlenwert (ASCII) a 97 b 98 c 99 binäre Darstellung 01100001 01100010 01100011 Zeichen Zahlenwert binäre (ASCII) Darstellung A 65 01000001 + 43 00101011 1 49 00110001 Wir haben nun die Grundeinheiten kennen gelernt, mit denen ein Computer operiert. Diese Einheiten werden Ihnen auch bei der Programmierung mit Java immer wieder begegnen, denn auch wenn Sie in Java mit Zahlen rechnen, müssen Sie manchmal angeben, in welcher Grundeinheit die Zahlen gespeichert werden sollen. Will man beschreiben, wie viele Daten ein Computer speichern kann, benützt man noch größere Einheiten: Größere Einheiten : Kilo-Byte (KB) : 1 Mega-Byte (MB) : 1 Giga-Byte (GB) : 1 Tera-Byte (TB) : 1 KB sind 210 MB sind 210 GB sind 210 TB sind 210 Byte = 1024 Byte KB = 1.048.576 Byte MB = 1.063.641.824 Byte GB = 240 Byte 5 1.2 Organisation des Arbeitsspeichers (Adressen) Sie haben soeben erfahren, dass der Arbeitsspeicher eines Rechners aus vielen Bits besteht, die zu Bytes oder größeren Gruppierungen zusammengefasst werden. Obwohl Sie dies zur Programmierung mit Java nicht unbedingt wissen müssen, möchte ich dennoch kurz erklären, wie der Prozessor Daten im Arbeitsspeicher verwendet. Jedes Byte des Arbeitsspeichers hat eine eindeutige Nummer – die Nummer eines Bytes nennt man seine Adresse. Der Prozessor kann über die Adresse Daten im Arbeitsspeicher auslesen und Daten in den Arbeitsspeicher schreiben. Beispiel : Wir können den Prozessor anweisen, eine Zahl in dem Byte an der Adresse 100 und eine weitere Zahl in dem an der Adresse 200 beginnenden Word zu speichern. Anschließend können wir anweisen, die beiden Zahlen zu addieren und das Ergebnis an der Adresse 300 abzulegen. Da hierbei ein Byte und ein Word addiert wird, sollte das Ergebnis mindestens Word-Größe haben. 6 2 Was ist eine Programmiersprache? Eine Programmiersprache ist eine formale Sprache, die zur Erstellung von Datenverarbeitungsanweisungen für Rechnersysteme verwendet wird. Als formale Sprachen bezeichnet man Sprachen, die durch formale Grammatiken erzeugt werden können. Als Grammatik bezeichnet man jede Form einer systematischen Sprachbeschreibung. Formale Grammatiken sind mathematische Modelle von Grammatiken. Die Theorie der formalen Sprachen ist ein eigenständiges Forschungsgebiet in der Theoretischen Informatik. Im Gegensatz zur Mathematik liegen die Objekte in den formalen Sprachen immer in kodierter Form vor. Beispiel : N Die natürlichen Zahlen = {0, 1, 2, . . . } sind zunächst ein gewissermaßen gedankliches Gebilde. In der Theoretischen Informatik wird aus ihnen durch die Kodierung in das Dezimalsystem, bestehend aus den 10 Ziffern 0 bis 9, eine formale Sprache. Wenn wir die Wörter einer natürlichen Sprache als Alphabetzeichen ansehen, dann bilden die Sätze der natürlichen Sprache eine formale Sprache über dem Alphabet der natürlichsprachlichen Wörter. Allerdings entzieht sich die natürliche Sprache einer vollständigen Definition, die festlegt, welche Sätze zu der natürlichen Sprache hinzugehören und welche nicht. Programmiersprachen dienen der Informationsverarbeitung. Informationsverarbeitung bedeutet in der Informatik alle Arten von Datenverarbeitung. Die äußere Form, in der sich eine Programmiersprache dem Programmierer repräsentiert, bezeichnet man als Syntax. Der Quelltext besteht aus Wörtern und Trennzeichen, ganz ähnlich zu einer natürlichen Sprache. Die Bedeutung eines speziellen Symbols in einer Programmiersprache nennt man dessen Semantik. Syntax und Semantik kann man der Spezifikation, teilweise auch der Dokumentation der Programmiersprache entnehmen. Der Quelltext (oder auch Quellcode oder Programmcode) der Programmiersprache wird anschließend in eine Anweisungsfolge für den Computer übersetzt, der Maschinensprache. Unter Maschinensprache versteht man ein System von Instruktionen und Daten, die der Prozessor eines Computers direkt ausführen kann. Maschinensprache ist nur für Experten zu lesen und von diesen mittels so genannter Maschinensprachmonitore zu bearbeiten. Das Programm wird in eine für den Computer verständliche Folge von Bits umgesetzt. Dies kann entweder offline durch einen Compiler oder zur Laufzeit durch einen Interpreter geschehen. In vielen Fällen wird mittlerweile eine Kombination aus Compiler und Interpreter gewählt, bei der der Quellcode in einen abstrakten Zwischencode übersetz wird. Der Zwischencode wird dann zur Laufzeit in einer so genannten Laufzeitumgebung durch einen Interpreter in den eigentlichen Maschinencode überführt. Das hat den Vorteil, dass ein und der selbe 7 Zwischencode auf sehr vielen verschiedenen Plattformen ausführbar ist. Beispiele für solche Zwischencodes sind der Java-Bytecode sowie die Common Intermediate Language. Eine Assemblersprache ist eine spezielle Programmiersprache, welche die Maschinensprache einer speziellen Prozessorarchitektur in einer für den Menschen leichter lesbaren Form repräsentiert. Jede Computerarchitektur hat folglich ihre eigene Assemblersprache. Eine Hochsprache oder höhere Programmiersprache ist eine für den Menschen geeignete Programmiersprache, die zwar maschinenunabhängig aber nicht unmittelbar für den Computer verständlich ist. Als weltweit erste höhere Programmiersprache gilt das Plankalkül von Konrad Zuse. Andere Beispiele sind Fortran (FORmula TRANslation), ALGOL (ALGOrithmic Language), LISP (LISt Processing), C (Nachfolger von B, benannt nach den Bell Labs), C++, Java, Perl, ... 8 2.1 Java Java sollte ursprünglich Oak (= Eiche) heißen, nach den Bäumen, die vor dem Büro des wichtigsten Entwicklers von Java, James Gosling, standen. Er fand jedoch heraus, dass es bereits eine Programmiersprache mit dem Namen Oak gab. So musste sich das Team etwas anderes einfallen lassen. Eine der Kaffeesorten des Ladens, in dem das Team seinen Kaffee kaufte, hieß Java. So kam Java zu seinem Namen. Java wurde von einem Team bei Sun Microsystems, Kalifornien, entwickelt. Java entstand aus der Notwendigkeit heraus, Software für elektronische Geräte wie VCRs, Fernseh-, Telefon- und Funkgeräte zu entwickeln, und vielleicht auch irgendwann einmal für einen Toaster. Die sich zunächst scheinbar hierfür anbietenden Sprachen C und C++ hatten Nachteile – es war nicht einfach, Software auf einen neuen Prozessor-Chip zu portieren. So entstand Java, mit dem Ziel, sehr kleine, schnelle, zuverlässige und transportable Programme zu erzeugen. Java ist eine objektorientierte höhere Programmiersprache. Objektorientiertes Programmieren ist die am häufigsten verwendete Programmiermethode seit der späten 90er Jahre. Java ist von Anfang an vollständig objektorientiert. Es ist keine Sprache, in die Objektorientiertheit als nachträgliche Idee implementiert wurde (vergleiche C → C++ ). Java unterstützt das Internet. Java ermöglicht Ihnen das Schreiben von Programmen, die das Internet (Abkürzung für Interconnected Networks) und das WWW nutzen. Das World Wide Web (kurz Web oder WWW) ist ein über das Internet abrufbares Hypertext-System. Java ist architekturunabhängig, d.h. es (genauer gesagt der Java-Zwischencode) läuft auf jedem Computer unverändert. 9 3 Zahlendarstellung im Computer Jedem Zustand eines Bytes oder Words kann man eine Dezimalzahl zuweisen. Dazu fasst man die Zustände der einzelnen Bits als Binärzahl auf. Der Dezimalwert einer Binärzahl berechnet sich wie folgt: 1. Die Bits der Zahl werden von rechts beginnend und mit der Zahl 0 startend durchnummeriert. 2. Nun bildet man eine Summe, in welcher man für jedes an der Position i gesetzte Bit die Zahl 2i einsetzt. Beispiele : Die Binärzahl 010 die Dezimaldarstellung 21 = 2. Die Zahl 010100100 hat die Dezimaldarstellung 22 + 25 + 27 = 164. Das höchstwertige Bit gibt in der Regel das Vorzeichen der Zahl an: Beispiele : 2=010 -2=110 164=010100100 -164=110100100 Der darstellbare Zahlenbereich wird von 264 auf +/-263 eingeschränkt! Eine Alternative bietet das so genannte Einerkomplement. Das Einerkomplement ist eine arithmetische Operation auf Binärzahlen. Dabei werden alle Ziffern bzw. Bits gekippt, d.h. aus 0 wird 1 und umgekehrt. Beispiel : Zu x = 108 ergibt sich das Einerkomplement x1 wie folgt: x = 01101100 (= 108) x1 = 10010011 x + x1 = 11111111 = 28 − 1 Wenn man zum Einerkomplement noch 1 addiert, so erhält man das so genannte Zweierkomplement x2 : x2 = x1 + 1 = 10010100 x + x2 = 100000000 = 28 = 0 10 Auch hier gibt das höchste Bit das Vorzeichen an. Ferner gilt: x − y = x + y2 d.h. wir haben die Subtraktion auf die Addition des Zweierkomplements zurückgeführt. Als nutzbarer Zahlenbereich stehen also für 2-Byte-Zahlen nur die Zahlen zwischen 0 und 216 = 65355 oder, wenn man das höchste Bit als Vorzeichenbit interpretiert, zwischen −32768 und +32767 zur Verfügung. Das sind die Zahlen, deren Zahlentyp man als INTEGER bezeichnet. Da dieser Zahlenbereich in der Regel nicht ausreicht, stellen höhere Programmiersprachen zusätzlich so genannte Gleitkommazahlen zur Verfügung. Gleitkommazahlen (Typ-Name float, double): Die Gleitzahldarstellung kennt man z.B. vom Taschenrechner: z.B. 1.234567E − 10 für 1.234567 · 10− 10 . 7-stellige Mantisse Die Bilder der vorhandenen Gleitkommazahlen sind auf der Zahlengeraden unterschiedlich dicht. Beispiel : Es wird mit 7-stelliger Mantisse gerechnet. Die Nachbarzahl von 1.0 · 10−10 ist 1.000001 · 10−10 , der Unterschied ist 10−16 . Die Nachbarzahl von 1.0 · 1010 ist 1.000001 · 1010 , der Unterschied ist 104 . 11 4 4.1 Algorithmen und ihre Darstellung Automatendefinition Seien A und B Alphabete für die o.B.d.A. gelte A = {1, 0} = B un Z eine Zustandsmenge, Eingabe a∈A Folge von Zuständen z∈Z Ausgabe b∈B Automaten : Automaten sind definiert durch eine Ausgabefunktion b := f (z, a) und eine Übergangsfunktion z := g(z, a). Wesentlich für endliche Automaten ist, dass die Zustandsmenge Z endlich ist, woraus o.B.d.A. folgt: Z = {0, 1}log2 |z| Turing-Maschine : Elaubt man Schreiben und Lesen auf ein Band, so ergibt sich die Turing-Maschine Sie erlaubt nur drei Operationen (Lesen, Schreiben, Kopf bewegen). Grundfunktionen wie die Addition lassen sich mit diesen drei Operationen ausführen bzw. berechnen. Eine Funktion die durch die Turing-Maschine berechnet werden kann heißt Turing-berechenbare Funktion 4.2 wesentliche Eigenschaften von Algorithmen Algorithmus : Unter einem Algorithmus versteht man eine genau definierte Handlungsvorschrift zur Lösung eines Problems bzw. einer Aufgabe. Für Algorithmen gibt es unterschiedliche formale Repräsentationen (→ endl. Spezifikationen), bis hin zu der Ansicht, Algorithmen seien gerade die Maschinenprogramme von Turing-Maschinen. 12 Eigenschaften : 1. endl. Spezifikationen z.B. durch ein Diagramm o. Quelltext 2. eindeutige Ausführbarkeit für spezifische Problemklasse 3. Determiniertheit (Bestimmtheit) (Selbe Eigabe erzeugt immer selbe Ausgabe) Eine vollständige Portierbarkeit ist fast unmöglich zu garantieren, z.B. wegen des Einflusses von Rundungsfehlern. 4. Nicht-Determiniertheit Der explizite Rückgriff auf Zahlen in zufallsbasierten Algorithmen ist oft einfacher zu beschreiben und im Erwartungswert effizienter als determinierte Algorithmen. 5. Endlichkeit Jede endliche Eingabe wird in endlich vielen Schritten abgearbeitet. Häufig ist dies nur durch sorgfältige Eingabe-Checks erreichbar, um unendliche Schleifen zu vermeiden. 6. Komplexität Zusammenhang zwischen Eingabe-Daten und (a) der Zahl der Berechnungsschritte (b) den maximale Speicherbedarf (c) der Zahl der Datenbewegungen Allgemein heißen Algorithmen, für die (a), (b) und (c) durch Potenzen der Eingabelänge beschränkt sind, polynomial. 4.3 Grundelemente beschränkter Algorithmen 1. ausführbare Einzelanweisungen z.B. sin x = y 2. Kontroll- und Steuerstrukturen (a) Sequenz (hinter einander Ausführen) (b) Selektion (Auswahl / Fallunterscheidung) (c) Zyklus (Schleife) 13 Beispiel Kreditabzahlung: Z Kneu = Kalt (1 + 100 )−R Z Kalt ( 100 ) < R Z R̃ = K(1 + 100 )≤R K:=Kredit (Euro) Z:=Zinsen (%) R:=Ratenzahlung (Euro) » ¾ START ½ ¼ ? ¡ ¡ ¡ Eingabe: K, Z, R ¡ ¡ ¡ ? ©HH © © H © H ©© K · Z < R HH HH 100 ©© © HH © HH©© nein - ¡nicht ¡ ¡ würdig ¡ ¡ ¡ ja ? jahr = 1 ? ©HH © © H HH ©© H -© K≥0 HH ©© HH © HH©©© ja ? nein - R=R+K ? ¡ ¡ Ausgabe: jahr, ¡ jahr = jahr++ ? ¡ K =K 1+ Z 100 ¢ −R 14 ¡ R ¡ ¡ 4.4 effiziente Algorithmen Beispiel Koordinaten der Punkte des Einheitskreises 1. naive Methode Berechne für α = 0, 1, . . . , 359 ³ α ´ x(α) = cos 2π ³ 360 α ´ y(α) = sin 2π 360 ⇒ 720 Aufrufe von Funktionen der Klasse Math 2. effizientere Methode 2π α mathematischer Hintergrund: Setze β := 360 und α̃ := 2π 360 µ ¶ α 2π Bemerkung : x(α + 1) = cos 2π + = cos(α̃ + β) 360 360 x(α + 1) = cos(α̃ + β) = cos α̃ cos β + sin α̃ sin β = y(α) + x(α) y(α + 1) = sin(α̃ + β) = sin α̃ cos β + cos α̃ sin β = x(α) + y(α) Quellcode: CA := cos α, SA := sin α, CB := cos β, SB := sin β α = 1, f or α = {1, . . . , 359} x = CA · CB + SA · SB, y = SA · CB + CA · SB, CA = x(α), CB = y(α), α = α + 1}, Vorteil: In der Schleife findet kein Funktionsaufruf statt. Folglich ist der Algorithmus wesentlich effizienter als die naive Methode. Nachteil: Es findet eine Fehlerfortpflanzung der Rundungsfehler in der Rekursion statt. 15 5 5.1 Programmbeispiel: Zufallssumme Bentfortsche Gesetz bitte nacharbeiten... 16 6 Datenstrukturen 6.1 Listen x[0], x[1], . . . , x[n − 1] mit n > 0 Einträgen Operationen : • Zugriff auf k-ten Eintrag • Einfügung vor dem k-ten Eintrag • Löschen des k-ten Elements • Vereinigung zweier Listen • Zerlegung in zwei Teillisten • Kopie einer Liste • Durchsuchen der Liste • Ordnen der Einträge • Länge der Liste bestimmen Typen : 1. Stack (Stapel: FiLo) 2. Queue (Schlange: FiFo) 3. Dequeue (Schlange mit 2 Enden: FiLo von beiden Seiten) Begriffe : 1. push (auf Stack legen / in Schlange stellen) 2. pop (von Stack nehmen) 3. eject (von vorne aus Schlange nehmen) 4. inject (von vorne in einen Schlange stellen) 17 6.2 Graphen Graph : Ein Graph kann durch ein Paar (V, E) aus der endlichen Knotenmenge V und einer Kantenmenge E mit E ⊆ V × V beschrieben werden. O.B.d.A. wird durchnummeriert und man setzt V = {1, 2, 3, . . . , n} mit n = |V |, so dass dann E aus Indexpaaren (i, j) mit 1 ≤ i ≤ n und 1 ≤ j ≤ n besteht. ¾» - 2 ½¼ µ ¡ ¡ 1 ½¼ I @ 6@ @ @ ¡ ¡ @¡ ¡@ @ ¡ ¡ ¡ ?¡ ¾» @ @ 3 Beispiel : Graph mit n = |V | = 4 und E {(1, 3), (3, 1), (1, 2), (4, 1), (2, 4), (2, 3)} ¾» ½¼ ? ¾» @ = Typen : 1. ungerichteter Graph E 3 (u, v) = (v, u) ∈ E 2. gerichteter Graph E 3 (u, v) 6= (v, u) ∈ E Begriffe : 1. Pfade gerichtete oder ungerichtete Verbindung über Zwischenpunkte z.B. p = (1, 2, 4) (a) gerichteter Pfad geordnete Teilmenge p = (v1 , v2 , . . . , vk ) ⊂ V mit (vi , vi+1 ) ∈ E für i = (1, . . . , k − 1) (b) ungerichteter Pfad p = {v1 , v2 , . . . , vk } ⊂ V mit {vi , vi+1 } ∈ E für i = (1, . . . , k − 1) 2. Zyklus ist ein geschlossener gerichteter Pfad, d.h. v1 = vk z.B. z = (1, 2, 4, 1) 3. Halbzyklus ein geschlossener ungerichteter Pfad z.B. h = (1, 3, 2, 1) 18 4 ½¼ 6.3 Bäume Bäume sind Graphen, die weder Halbzyklen, noch Zyklen enthalten. 7 Suchen 7.1 lineares Suchen Auftrag: Suche Wort W in Liste L der Länge n Lösung: Liste sequenziell durchlaufen (3 verschiedene Lösungsbeispiele) 1. set i = 1 if (i ≤ n){ if (L[i] 6= W ){ i++ }else (print W ) }else (print kommt nicht vor) durchschnittl. Dauer: n-Schritte 2. set i = 1 if (L[i] 6= W ){ if (i ≤ n){ i++ }else (print kommt nicht..) }else (print W ) durchschnittl. Dauer: n+1 -Schritte 2 3. set i = 1 L[n + 1] = W if (L[i] 6= W ){ i++ } if (i ≤ n){ print W }else (print kommt nicht vor) durchschnittl. Dauer: n+1 -Schritte 2 19 7.2 binäres Suchen In geordneten Strukturen ist Suchen schneller. Beispiel : Raten einer Zahl zwischen 1 und 100 Liste L = {1, 2, . . . , 100} 1. lineare Suche benötigt im Schnitt n+1 2 = 101 2 ≈ 51 Schritte 2. binäre Suche benötigt im Schnitt nur log2 100 ≈ 7 Schritte 7.3 Hashing Das Hashing ist eine Verallgemeinerung zur Effizienzsteigerung der Suche. Hierfür wird eine hash-Funktion h verwendet. Zum besseren Verständis folgen nun nähere Erläuterungen an einer beispielhaften Liste mit einer Menge Einträge E, die mittels hash-Funktion h auf eine Menge von Indizes I abgebildet werden. ½ h := E −→ I e 7−→ h(e) = i • Injektivität Die hash-Funktion muss nicht zwangsweise injektiv sein. • Effizienz Die Urbildmenge h−1 (i) sollte für alle i ungefähr gleichgroß sein, um die Suche effizient nutzen zu können. • hash-Tabelle nennt man die durch die Funktion definierte Indexstruktur • Erstellen der Tabelle Alle Einzeleinträge e mit dem gleichen hash-Wert werden in den selben “Behälter” h abgelegt. z.B. [Griewank, 5280] −−−−→ 6 • Ablauf der Suche Suche solange nach dem richtigen Behälter für den 1.(, 2., 3., . . . ) Buchstaben, bis das Ergebnis eindeutig ist. Gebe zum Schluss das Ergebnis aus. 20 7.4 Teilen + Herschen, Laufzeiten Das Ziel ist es nun, für ein Problem der Größe n eine obere Schranke T (n) für die benötigte Laufzeit der Suche zu finden. Wenn wir davon ausgehen, dass ein Problem zerlegbar in t Teilprobleme ist, die eine Größe von ns (s > n) und der Aufwand zum Zerlegen und Zusammensetzen mit z(n) beziffert werden kann, ergibt sich: ½ T (n) = Satz 7.1. : Für n = sk gilt T (n) = z(n) ,n=1 n t · T ( s ) + z(n) , n 6= 1 Pk i i=0 t z ¡n¢ si Beweis über Induktion: I.A. k = 0, k = 1, I.S. µ ¶ 0 X 1 i n = s = 1 =⇒ T (1) = z(1) = t =1 si i=0 0 n = s1 = s =⇒ T (n) = t · T + z(n) = t · z(1) + z(n) 1 ³n´ ³n´ ³n´ X 0 1 i T (n) = tz i =t ·z 0 +t ·z 1 s s s i=0 I.V. n = sk−1 I.B. k = z(n) + t · z(1) k−1 ³n´ X =⇒ T (n) = ti z i s i=0 n = s =⇒ T (n) = k X i tz ³n´ si µ k¶ ³n´ s T (n) = t · T i + z(n) = t · T + z(n) s si µ k−1 ¶ k−1 X s k−1 i = t · T (s ) + z(n) = t · tz + z(n) i s i=0 µ k−1 ¶ k−1 X s ·s =t· ti z + z(n) i s · s i=0 µ k ¶ µ k¶ k X s s 0 i+1 + t · z = t z si+1 s0 i=1 µ k¶ X k k ³n´ X s i i = = tz i tz si s i=0 i=0 i=0 21 (n) ,t<s (n · log n) , t = s Satz 7.2. : Gilt ferner z(n) = c · n, so ist T (n) = (nlogs t ) , t > s (n) → polynomialer Aufwand der Ordnung n (nlogs t ) → polynomial komplexer Aufwand, da s, t kosntant sind. Beweis: T (n) = = k X i=0 k X i tz i ³n´ si t ·c· ³n´ si k µ ¶i X t =n·c· s i=0 ∞ µ ¶i k µ ¶i X X t t t ≤ < 1 =⇒ s s s i=0 i=0 µ ¶ ∞ i X t 1 =: k = s 1 − st i=0 i=0 F all 1 : t < s =⇒ F all 2 : t = s =⇒ F all 3 : t > s T (n) = n · c · k ∈ (n) k µ ¶i X t t = 1 =⇒ =k+1 s s i=0 T (n) = n · c · (k + 1) ∈ (n · log n) ¡ ¢k+1 1 − st ¡ ¢ T (n) = c · n · 1 − st õ ¶ ! k t k =c·s · ∈ (tk ) s 22 8 Sortieren Definition 8.0.1. : Sei M eine Menge, der eine Relation R ⊆ M × M gegeben ist. Wir schreiben (M, R). Statt (a, b) ∈ R schreibt man a ∼ b ⇔ aRb, wenn gilt: 1. reflexiv, wenn gilt ∀a ∈ M : aRa 2. antisymmetrisch, wenn gilt aRb ∧ bRa ⇔ a = b 3. transitiv, wenn gilt aRb ∧ bRc ⇔ aRc heißt sie Ordnung. Definition 8.0.2. : Eine Relation R heißt vergleichbar, wenn ∀a, b ∈ M : aRb ∨ bRa gilt. Definition 8.0.3. : Eine Ordnung, die vergleichbar ist, heißt totale Ordnung. Beispiele : N Z R 1. totale Ordnung ( , ≤), ( , ≤), ( , ≤), . . . N 2. Ordnung nicht vergleichbar, aber 8.0.1. (1-3) gilt für ( , |) Ein Sortierungsproblem besteht darin zu einer gegebenen Eingabemenge {a1 , . . . , an } ⊆ M eine Ausgabefolge ai1 , ai2 , . . . ain zu bilden für die aip = aiq für p < q gilt. Anwendbar ist dies bei Problemen wie dem Zusammenbringen zusammengehöriger Dinge, dem Suchen eines bestimmten Elementes oder dem Finden gleicher Elemente. Das Suchen in geordneten Mengen ist leichter als das Suchen in ungeordneten. Ein Sortieralgorithmus kann mit Hilfe eines binären Entscheidungsbaumes dargestellt werden. 23 Beispiel : M = {a, b, c}, ≤ := totale Ordnung Niveau 0: Niveau 1: Niveau 2: a ≤ Niveau 3: ® © ­a ≤ b ª ¡@ @ ja ¡¡ @ nein @ ¡© R @ ª ¡ ® ® © b ≤ c ­ ª ­a ≤ c ª £B £B ja££ BB nein ja££ BB nein £°£ ®BBN £°£ ®BBN © © b ≤ c ­a ≤ c ªb ≤ a ≤ c ­ b ≤ c ª £B £B ja££ BB nein ja££ BB nein BBN BBN £°£ £°£ a≤c≤b c≤a≤b b≤c≤a c≤b≤a Der Baum hat die Tiefe 3 Satz 8.0.4. : Sei En ein binärer Entscheidungsbaum mit n zu sortierenden Elementen, dann ist die Tiefe von En mindestens (n log n). Beweis: Die Anzahl der Blätter ist mindestens n!, da es soviele Anordnungsmöglichkeiten gibt. Andererseits hat ein linearer Baum der Tiefe d höchstens 2d Blätter. 2d ≥ n! ≥ n · (n − 1) · . . . · ⇔ ⇒ ⇔ ³n´ 2 ≥ ³ n ´ n2 2 d ≥ log2 (n!) ³ n ´ n2 ³n´ n d ≥ log2 = · log2 2 2 2 n d ≥ · log2 (n − 1) ∈ (n log n) 2 Bemerkung: Ein vergleichsbasiertes Sortierverfahren kann nicht schwacher als (n log n) sein. 24 Definition 8.0.5 Ein Sortierverfahren heißt stabil, wenn die Reihenfolge der Datensätze, deren Sortierabstände gleich sind, bewahrt werden. Beispiele : • Daten Liste mit Personenamen (alphabetisch vorsortiert) • Aufgabe Neusortierung nach Geburtsdatum • Ergebnis alphabetische Reihenfolge bleibt nach Neusortierung für gleiche Geburtsdaten erhalten 8.1 Bubble-Sort Der Bubble-Sort-Algorithmus vergeicht mit einander benachbarte Elemente und tauscht gegebenenfalls. In der Regel sind bis zum erreichen einer sortierten Liste viele Durchläufe nötig. Bubble-Sort ist stabil. N Beispiel : ( , ≤) {55, 7, 78, 12, 42} 1. Durchlauf: {7, 55, 12, 42, 78} 2. Durchlauf: {7, 12, 42, 55, 78} 3. Druchlauf: {7, 12, 42, 55, 78} =⇒ Ziel erreicht Effizienz : günstigster Fall (n) ungünstigster Fall 12 (n2 − n) ∈ (n2 ) durchschnittlicher Fall 41 (n2 − n) ∈ (n2 ) (Liste ist bereits sortiert) (Liste ist genau invers sortiert) 25 8.2 Quick-Sort Der Algorithmus arbeitet nach dem Prinzip “Teilen und Herrschen” Ablauf : 1. Schritt Wähle (Pivot-)Element aus zu sortierender Liste 2. Schritt Zerlege die Liste in 2 Teillisten (a) Liste 1 enthält alle Elemente, die größer als Pivot-Element sind (b) Liste 2 enthält alle anderen Elemente 3. Schritt Schritt 1 & 2 rekursiv wiederholen in den Teillisten 4. Schritt Zusammenfügen in der richtigen Reihenfolge Beispiel : 1. Pivot-Element: ( ; ≤) { 5, 4, 3, 2, 1| 1. Element der Teilliste 4, 3, 2, 1, } 3, 2, 1| 5 2, 1| 4| 5 1| 3| 4| 5 2| 3| 4| 5 2. Pivot-Element: ( ; ≤) { 5, 2, 1| Median 4, 3, 1| 3| 2| 3| N N (ersten, mittelsten, letzen) 2, 1, } 5, 4 4| 5 Bemerkungen : Quick-Sort ist kein stabiler Algorithmus! Effizienz : Die Laufzeit ist stark von der Wahl des Pivot-Elementes abhängig. ungünstigster Fall (n2 ) durchschnittlicher Fall (n log n) (Pivot-Ele. stets größtes/kleinstes der Liste) 26 8.3 Merge-Sort Auch dieser Algorithmus beruht auf dem “Teilen und Herrschen”-Konzept. Ablauf : Beispiel : 1. Aufspalten in Teillisten anexample 2. Zusammenfügen durch vergleich der kleinsten Elemente (Reißverschluss-Prinzip) a n e x a m p l e a n e x a m p l e a n e x a m p l e ? ? ? ? ? ? ? ? a n e x a m l e ? ? e l ? ? e l p ? ? ? ? a e n x a e l m p ? ? a a e e l m n p x 8.4 Übersichtstabelle Aufwand Algorithmus ungünstig schnitt günstig stabil rekursiv √ 2 2 Bubble-Sort (n ) (n ) (n) × √ 2 Quick-Sort (n ) (n log n) (n log n) × √ √ Merge-Sort (n log n) (n log n) (n log n) 27 9 Grundlagen der Fehleranalyse 9.1 Normen, Vektoren und Matrizen Definition 9.1.1. : Ein metrischer Raum ist ein Paar (X, d) bestehend aus einer Menge X und einer Abbildung (Abstandsfunktion) d : X × X → [0, ∞) mit folgenden Eigenschaften: (a) d(x, y) = 0 ⇔ x = y (b) d(x, y) = d(y, x) (Symmetrie) (c) d(z, x) ≤ d(z, y) + d(y, x) (Dreiecksungleichung) Definition 9.1.2. : Rn → R heißt Norm in Rn falls, 1. kxk ≥ 0 ∀x ∈ Rn kxk = 0 ⇔ x = 0 ∈ Rn 2. kαxk = |α|kxk ∀x ∈ Rn , α ∈ R 3. kx + yk ≤ kxk + kyk ∀x, y ∈ Rn Eine Abbildung k·k : Satz 9.1.3. : Es sei k·k eine Norm in 1. d : Rn. Dann gilt Rn × Rn → R mit d(x, y) := kx − yk 2. |kxk − kyk| ≤ kx − yk ≤ kxk + kyk Beweis 1. Prüfe Metrischen Raum (a) d(x, y) = kx − yk = 0 ⇔ x − y = 0 ⇔ x = y (b) d(x, y) = kx − yk = k(−1) · (y − x)k = |−1|ky − xk = ky − xk = d(y, x) (c) d(z, x) = kz − xk = k(z − y) + (y − x)k ⇔ d(z, x) = d(z, y) + d(y, x) 2. z.z. |kxk − kyk| ≤ kx − yk kxk = kx(−y + y)k = k(x − y) + yk ≤ kx − yk + kyk kyk = ky(−x + x)k = k(y − x) + xk ≤ ky − xk + kxk = kx − yk + kxk ¾ kxk − kyk ≤ kx − yk ⇒ |kxk − kyk| ≤ kx − yk kyk − kxk ≤ kx − yk 28 Beispiele für Normen : ¯P ¯1 1. p-Norm kxkp := ¯ ni=1 |xi |p ¯ p 2. unendlich, Maximum- oder Tschebyschow-Norm kxk∞ := maxi=1,...,n |xi | ∀x ∈ n R R 3. endliche P Norm Für x, y ∈ n definieren wir das Skalarprodukt wie folgt: < x, y >:= 1 xT · y = ni=1 xi yi . Die sogenannte endliche Norm erhält man als kxk2 =< x, y > 2 . Sie ist die 2-Norm, also p = 2. Definition 9.1.4. : Rm×n eine (m × n)-Matrix, k·kX eine Norm im Rn und k·kY eine Norm im Rm. Es sei A ∈ Dann heißt kAXkY = sup kAXkY kXkX kXkX =1 kAkX = sup x6=0 die zu k·kX und k·kY zugeordnete Matrix-Norm. Lemma 9.1.5. : R R Es seien k·kX und k·kY Normen auf n bzw. m . Dann ist die zugeordnete Matrix-Norm eine Norm auf m×n , dem linearen Raum aller (m × n)-Matrizen. Ferner gilt R R R R 1. ∀A ∈ m×n , X ∈ n kAXkY ≤ kAkkXkX und kAk ist die kleinste aller Zahlen c > 0 mit kAXkY < c · kXkX ∀X ∈ n R 2. Sei außerdem k·kZ eine Norm auf k und B eine (k × m)-Matrix, dann gilt für die entsprechenden Matrixnormen kB · Ak ≤ kBk · kAk Beweis 1. Prüfe Normeneigenschaften (a) kAk ≥ 0 ∀A ∈ Rm×n kAk = 0 ⇔ kAXkY = 0 ∀X ∈ ⇔ A = ∈ m×n R (b) kαAk = sup kαAXkY kXkX =1 29 Rn (c) kA + Bk = sup k(A + B)XkY kXkX =1 ≤ sup (kAXkY + kBXkY ) kXkX =1 ≤ sup kAXkY + sup kBXkY kXkX =1 kXkX =1 ⇔ kA + Bk ≤ kAk + kBk R 2. Lemma 9.1.5.(1) nachweisen A ∈ m×n , X ∈ Die Behauptung ist für X = 0 richtig. z.z. X 6= 0 R kAXkY kAXkY ≤ = kAk kXkX kXkX ⇒ kAXkY ≤ kAkkXkX ist c > 0 eine Zahl kAXkY ≤ c kXkX , so gilt ∀ X ∈ n mit kXkX = 1|kAXkY ≤ c, das heißt kAk ≤ c R 3. Lemma 9.1.5.(2) nachweisen A B Rn ∈ X −→ AX ∈ Rm − → BAX ∈ Rk Sei X ∈ Rn mit kXkX = 1, dann gilt kBAXkZ ≤ kBkkAXkY ≤ kBkkAkkXkX ⇒ kBAk = sup kBAXkZ ≤ kBkkAk kXkX =1 Hölder-Ungleichung u, v ∈ n X j=1 Rn und p > 1 und p1 + 1q = 1 |uj vj | ≤ à n X ! p1 à n ! 1q X · |vj |q |uj |p j=1 j=1 30 Beispiele 9.1.6 : 1. Spaltensummennorm als zugeordnete Matrizennorm k·k1 = k·kX = k·kY 2. Für k·k2 = k·kX = k·kY gilt kAk2 = sup kAXk2 = p λmax (AT A) kXk2 =1 Dabei ist λmax (AT A) der größte Eigenwert der symmetrischen und semidefiniten Matrix (AT A). T • Symmetrie: (AT A)T = (AT AT ) = (AT A) • positiv semidefinit: Alle Eigenwerte λX sind größer (gleich) null. Bemerkung 9.1.7 : Die Spektralnorm kAk2 für A ∈ die folgenden oberen Schranken: Rn×m ist schwer zu berechnen. Deshalb nutzt man häufig à kAkF := m X n X ! 21 a2ij i=1 j=1 à kAkmax := Beide sind Normen auf √ ! n · m max aij i=1...m j=1...n Rn×m. Definition 9.1.8 : R Zwei beliebige Normen k·kX und k·kY in n heißen äquivalent, falls es Konstanten m, M > 0 gibt, so dass mkXkX ≤ kXkY ≤ M kXkX für alle X ∈ Rn gilt. 31 Satz 9.1.9 : Rn gilt nun die folgende Aussage: Alle Normen in Rn sind äquivalent. Beweis z.z. jede bel. Norm k·k ∈ Rn ist zur euklid. Norm k·k2 äquivalent Auf Denn dann sind auch je zwei beliebige Normen auf Grund der Transivität der NormenÄquivalenz äquivalent. Es sei ei = (0, . . . , 0, 1, 0, . . . , 0) der i-te kanonische Einheitsvektor. Dann gilt für beliebige x = (x1 , . . . , xn ) ∈ n R kxk := k n X xi e i k ≤ i=1 n X kxi ei k = i=1 |xi kei k| ≤ i=1 à n X 1 p + ! 21 à |xi |2 |xi |kei k = i=1 Mittels Hölderungleichung mit p = q = 2 ⇔ n X n X · 1 q = n X |xi kei k| i=1 1 2 1 2 + n X kej k2 = 1 ergibt sich ! 12 = kxk2 · M i=1 i=1 Zusammen mit der erweiterten Dreiecksungleichung gilt |kxk − kyk| ≤ kx − yk ≤ M kx − yk2 R (∀x, y ∈ Rn) R das heißt gerade, dass die Abbildung k·k : ( n , kxk2 ) → (Lipschitz-)stetig ist. Da die n Menge Sn := {x ∈ : kxk2 = 1} beschränkt und abgeschlossen ist, nimmt die Abbildung k·k dort ein Minimum an. Extremwert-Satz von Weierstraß: R ∃ x̂ ∈ Sn | m := kx̂k = inf kxk x∈Sn Wegen x̂ 6= 0 gilt m > 0 und es ist ferner ° ° ° x ° ° ° infkx̃k = m ≤ ° kxk2 ° m · kxk2 ≤ kxk ≤ M kxk2 ∀x ∈ Rn, x̃ ∈ Sn, x 6= 0 ∀x ∈ Rn Bemerkung 9.1.10 : Satz 9.1.9 gibt uns die Möglichkeit bei Fehlerabschätzung eine beliebige Norm zu verwenden. Die Aussagen bleiben bis auf Konstanten qualitativ richtig. 32 9.2 Kondition von Aufgaben Numerische Mathematik (Numerik) beschäftigt sich mit der Konstruktion und der Analyse von Algorithmen für mathematische Probleme. Hauptanwendung ist die (näherungsweise) Berechnung von Lösungen (mit Hilfe von Computern). Dabei spielen besondere Näherungsverfahren und Fehleranalysen, sowie deren rechentechnische Realisierung eine entscheidende Rolle. Die Numerische Lösung eines Problems ist die Berechnungen von Lösungen (Ergebnissen) aus gewissen Eingangsgrößen (Daten) nach wohlbestimmten Vorschriften. Wir bezeichnen die Daten mit d, die Ergebnisse mit s und die Vorschriften mit P . Wir schreiben s = P (d). Beispiel : Lösung linearer Gelichungssysteme Ax = b mit einer regulären Matrix A. Hierbei gilt d = (A, b); s = x; P (A) = A−1 · b Die Eingangsgrößen für numerische Rechnungen sind in der Regel fehlerbehaftet und folglich nur näherungsweise bekannt. Mit der Entscheidung darüber, was Daten sind, wird gleichzeitig impliziert, welche Größen als fehlerhaft anzusehen sind. Diese Fehler sind die sogenannten Datenfehler. Es gibt noch eine Reihe anderer unvermeidbarer Fehlerquellen: • Modellfehler Die Abbildungen eines realen Sachverhaltetes auf ein mathematisches Modell ist nur näherungsweise möglich. • Fehler im numerischen Lösungsprozess – Diskretisierungsfehler Abbildung kontinuierlicher Prozesse auf diskrete Größen – Darstellungsfehler z.B. Darstellung reeller Zahlen im PC – Abbruchfehler Aufgaben für die kein endlicher Algorithmus existiert, müssen durch suxessive unendliche Prozesse gelößt werden, die geeignet abgebrochen werden müssen. – Rundungsfehler siehe oben Es ist wichtig das Verhalten eines Problems P bei Störungen in den Eingangsdaten (d ∈ D) zu kennen. Die Nachfolgende Eigenschaft der korrekten Gestelltheit (well-postness) von D ist dabei wünschenswert. 33 Definition 9.2.1 : 1. Das Problem P heißt korrekt gestellt, falls eine Abbildung L : D × + → + existiert, so dass folgendes gilt ³ ´ ˜ ≤ L d, kd − dk ˜ kd − dk ˜ ~ kP (d) − P (d)k R R für alle d, d˜ ∈ D gilt (Lipschitz-)stetige Abhängigkeit von den Anfangsdaten und die Funktion L(d, ·) : + → + ist monoton wachsend. Andernfalls heißt P inkorrekt oder schlecht gestellt. R R 2. Die Zahl K(d) := L(d, 0) kPkdk heißt (relative) Konditionszahl des Problems P in (d)k den Daten d. 3. Das Problem heißt gut konditioniert (in D), falls K(d) nicht zu groß ist. Andernfalls heißt es schlecht konditioniert (d.h. K(d) À 1). 4. Die Zahl L(d, 0) heißt absolute Konditionszahl. Bemerkung 9.2.2 : Die Korrektheit des Problems ist also gelich bedeutend mit der totalen Lipschitz-stetigen Abhängigkeit der Lösung von den Daten (in einer Umgebung von d). Die Bedingung ~ ist äquivalent zur folgenden Eigenschaft des Problems P ³ ´ ˜ ˜ kP (d) − P (d)k ˜ kd − dk ≤ K d, kd − dk kP (d)k kdk in die die relativen Fehler von Längen und Daten eingehen. Dabei ist ³ ´ ³ ´ ˜ ˜ K d, kd − dk = L d, kd − dk kdk kP (d)k Ist P nach D stetig differenzierbar, so ist die Norm der Ableitung von P´ (nach dem ³ ˜ mit kleinen Mittelwertsatz) in d ein Orientierungspunkt für die Größe von L d, kd − dk ˜ Abweichungen der Daten, d.h. kd − dk 34 Beispiel 9.2.3 : Kondition der Addition bzw. der Subtraktion R2 →µ R ¶ a 7−→ P (d) = a + b d= b µ ¶ δP δP 0 P (d) = , = (1, 1) ∈ 1×2 δa δb P : R R R Wählen wir jetzt auf 2 und die k·k1 -Norm, so ergibt sich für die zugeordnete Matrixnorm die Spaltensummennorm (siehe Bsp. 9.1.6 (1)) kP 0 (d)k1 = k(1, 1)k1 = 1 Wir erhalten also insgesamt die relative Konditionszahl für die Addition (bzw. Subtraktion) als kdk1 kP 0 (d)k1 °µ ¶° ° a ° ° ° ° b ° = k(1, 1)k1 · |a + b| |a| + |b| =1· |a + b| K(d) = kP 0 (d)k1 · Für die Addition zweier Zahlen gleichen Vorzeichens ergibt sich also K(d) = 1. Die Addition ist gut konditioniert. Hingegen zeigt sich, dass die Addition zweier Zahlen bezüglich der relativen Kondition schlecht konditioniert ist, da in diesem Falle gilt |a + b| ¿ |a| + |b| ⇔ K(d) À 1 Wir erinnern uns an das Problem der Auslöschung führender Ziffern, dass in Kapitel 3 behandelt wurde. 35 9.3 Rundungsfehlerfortpflanzung R Für die Darstellung der Zahlen x ∈ \{0} haben wir die t-stellige Gleitkomma-Darstellung · 0, x−1 x−2 . . . x−t β N mit x−1 6= 0 festgelegt. Definition 9.3.1 : Die o.B.d.A gerade Zahl β ∈ N sei die Darstellungsbasis (β = 2 ⇒ Dualsystem, β = 10 ⇒ Dezimalsystem, . . . ), t die Mantissenlänge und o ∈ {−1, 1} das Vorzeichen für die Darstellung einer reellen Zahl x 6= 0 x=·β N ∞ X x−i β −i mit xi ∈ {0, 1, . . . , β − 1} ∀i i=1 Dann definieren wir die folgende Rundungsvorschrift ½ P · β N ¡ ti=1 x−1 β −i ¢ , f alls x−t−1 < 0, 5 · β Pt rdt (x) := −i t N + β , f alls x−t−1 ≥ 0, 5 · β ·β i=1 x−1 β rdt (x) heißt der auf t-Stellen gerundete Wert von x. Satz 9.3.2 : x ∈ R \ {0} besitze die Darstellung wie in Def. 9.3.1. 1. Für dem absoluten Fehler gilt dann |rdt (x) − x| ≤ 0, 5 · β N −t 2. Für den relativen Fehler gilt dann ¯ ¯ ¯ rdt (x) − x ¯ ¯ ¯ ≤ 0, 5 · β −t+1 ¯ ¯ x ¯ ¯ ¯ rdt (x) − x ¯ −t+1 ¯ ¯ ¯ rdt (x) ¯ ≤ 0, 5 · β 3. Die Rundungsfunktion erlaubt die Darstellung rdt (x) = x(1 − ε(x)) = x mit max {|ε(x)|, |η(x)|} ≤ 0, 5 · β −t+1 1 − η(x) Deshalb heißt die Zahl τ := 0, 5 · β −t+1 die relative Rechengenauigkeit der t-stelligen Gleitkommaarithmetik. 36 Beweis: 1. Für x−t−1 < 0, 5 · β ⇒ x−t−1 ≤ 0, 5 · β − 1 −(rdt (x) − x) = β N ∞ X x− iβ −i i=t+1 = x−t−1 β N −t−1 +β N ≤ x−t−1 β N −t−1 + β N ∞ X i=t+2 ∞ X x−i β −i (β − 1)β −i i=t+2 ≤ x−t−1 β N −t−1 + β N (β − 1)β −(t+2) ∞ X β −i i=t+2 à ≤ x−t−1 β N −t−1 ≤ x−t−1 β N −t−1 N + β (β − 1)β N + β (β − 1)β −(t+2) −(t+2) µ 1 1− ! 1 β β β−1 ¶ ≤ x−t−1 β N −t−1 + β N (β −(t+1) ) ≤ (0, 5 · β − 1)β N −t−1 + β N −t−1 ≤ 0, 5 · β N −t Für x−t−1 ≥ 0, 5 · β o(rdt (x) − x) = β N −t −β N ∞ X x−i β −i i=t+1 =β N −t −β N −t−1 x−t−1 − β N ∞ X x−i β −i i=t+2 à ≤ β N −t − β N −t−1 x−t−1 weil βN ∞ X ! x−i β −i i=t+2 ≤ 0, 5 · β N −t 2. x−1 ≥ 1 ⇒ |x| ≥ β N −1 ¯ ¯ ¯ rdt (x) − x ¯ |rdt (x) − x| |rdt (x) − x| ¯= ¯ ≤ ≤ 0, 5 · β N −t β 1−N = 0, 5 · β −t+1 ¯ ¯ x |x| β N −1 Zweite Abschätzung analog mit |rdt (x)| ≥ x−1 β −1 ≥ β N . 37 >0 3. Hierfür ist nur eine andere Schreibweise aus (2) nötig. Setze ε(x) := rdt (x) − x rdt (x) − x und η(x) := x rdt (x) Dann gelten die angegebenen Darstellungen und Abschätzungen. Es bezeichne ¤ eine der Rechenoperationen +, −, ×, \. Wenn nun x und y zwei Computerzahlen mit Mantissenlänge t sind so ist x ¤ y im allgemeinen nicht mit t-stelliger Mantisse darstellbar. Deshalb werden die Zahlen gerundet. Diese Operation wird in zwei Schritten ausgeführt. 1. möglichst genaue Berechnung von x ¤ y 2. Runden des Ergebnisses auf t Stellen Das Ergebnis dieser Operation wird mit f lt (x ¤ y) dargestellt. Postulat 9.3.3. : Die Computerarithmetik ist so organisiert, dass für zwei Computerzahlen x und y mit Mantissenlänge t stets gilt f lt (x ¤ y) = rdt (x ¤ y) Aus Satz 9.3.2. (3) ergibt sich f lt (x ¤ y) = (x ¤ y)(1 + ε) = (x ¤ y) (1 − η) |ε|, |η| ≤ τ Wir schreiben x̃ = x(1 + ε), ỹ = y(1 + ε) und betrachten f lt (x ± y) = x̃ ± ỹ, f lt (x ∗ y) = x ∗ y(1 + ε) = x ∗ ỹ = x̃ ∗ y Das Computerresultat einer arithmetischen Operation ist das exakte Resultat der selben Operation mit wenig gestörten Operanden. Bemerkung 9.3.4. : Probleme der Computerarithmetik Sei N ∈ [N− , N+ ] • Unterlauf Falls der Betrag des Ergebnisses einer Operation kleiner als β −N− −1 ist, wird häufig auf null gerundet. In diesem Fall beträgt der relative Fehler 100 Prozent. • Überlauf Falls der Betrag des Ergebnisses größer als β N+ ist, kann das Ergebnis nicht mehr dargestellt werden. 38 • Auslöschung • Fehlerfortpflanzung Sei PA ein Algorithmus zur numerischen Lösung eines Problems P auf einer Datenmenge D. Wir nehmen an, das sich PA an einer endlichen Folge P1 , . . . , PN von elementaren Schritten zusammensetze, das heißt PA = PN · . . . · P3 · P2 · P 1 Wie setzen sich die Rundungsfehler der einzelnen Operationen nun fort? Definition 9.3.5. : Es sei τ die relative Maschinengenauogkeit einer t-stelliger Gleitkommaarithmetik 1. Der Algorithmus PA heißt numerisch stabil für P auf D, falls es einen konstante FS > 0 gibt, so dass für alle d ∈ D gilt kP (d) − PA (d)k ≤ FS · τ · kdk 2. Der Algorithmus PA heißt numerisch gutartig für P auf D, falls es eine Konstante FG > 0 und für jedes d ∈ D eine Störung δd mit (d + δd ) ∈ D und kδd k ≤ FG · τ · kdk existiert, so dass PA (d) = P (d + δd ) Satz 9.3.6. : Es sei das Problem P korrekt gestellt auf der Datenmenge D, das heißt es existiert eine Funktion L : D × + → + mit der Eigenschaft, dass ∀d, d˜ ∈ D gilt R R ˜ ≤ L(d, kd − dk)kd ˜ ˜ kP (d) − P (d)k − dk und das L(d, ·) : R+ → R+ monoton wachsend (siehe Def. 9.2.1.). Ferner gelte sup L(d, ckdk) < ∞ ∀c > 0 d∈D Ist ein Algorithmus PA numerisch gutartig für P auf D, so ist er auch numerisch stabil mit FS := FG · sup L(d, FG · τ · kdk) d∈D 39 Beweis: Sei d ∈ D beliebig. Wir wählen die konstante Funktion FG und die Störung δd mit (d + δd ) ∈ D, kδd k ≤ FG · τ · kdk und PA (d) = D(d + δd ). Dann folgt aus der korrekten Gestelltheit von P , dass kP (d) − PA (d)k = kP (d) − P (d + δd )k ≤ L(d, kδd k) − kδd k ≤ L(d, FG · τ · kdk) · FG τ kdk ≤ FG sup L(d, FG · τ · kdk) · kdk · τ d∈D := FS · τ · kdk das heißt die gewünschte Aussage. Für die Erfülltheit der zusätzlichen Voraussetzung in Satz 9.3.6. ist hinreichend, dass P global Lipschitz-stetig ist, oder in vielen Fällen auch, dass die Menge D beschränkt ist. Beispiel 9.3.7. : • gegeben n reelle Zahlen x1 , . . . , x2 Arithmetik mit Mantissenlänge t. P • gesucht s = P (x) = ni=1 xi für xi ∈ n (Voraussetzung: kein Über- oder Unterlauf ) R • konzeptioneller Algorithmus s := 0, s := s + xi , i = {1, . . . , n} • realer Algorithmus s0 := 0, si := f lt (si−1 + rdt (xi )), i = {1, . . . , n} das heißt PA (x) = sn Behauptung : R P ist korrekt gestellt und der Algorithmus ist numerisch stabil auf D = n mit k·k1 und n L = 1 und FG := 1−(n−1) ≈ n falls (n − 1) · τ < 1 vorausgesetzt wird. Er ist sogar numerisch n gutartig auf D = mit k·k1 und R FG = n + (τ ) ≈ FS 40 Beweis : Es gilt ¯ ¯ ¯ ¯ n n n n ¯X ¯ X ¯ ¯X X ¯ ¯ ¯ ¯ |P (x) − P (x̃)| = ¯ xi − |xi − x̃i | = kx − x̃k1 x̃i ¯ = ¯ (xi − x̃i )¯ = ¯ ¯ ¯ ¯ i=1 i=1 i=1 i=1 das heißt L ≡ 1, woraus folgt, dass P korrekt gestellt ist. Nach 9.3.3. folgt für beliebige i ∈ {1, . . . , n} si = si−1 + rdt (xi )(1 + εi ) |εi | ≤ τ = si−1 (1 + εi ) + rdt (xi )(1 + εi ) = ⇔ sn = i X i Y rdt (xj ) (1 + εk ) j=1 n X k=j n Y rdt (xj ) j=1 (1 + εk ) ~ k=j hiermit (und mit s0 = 0, ε1 = 0) leitet man her ! à n X n n · |xj | = · kxk1 · τ = FS · kxk1 ·τ |s − sn | ≤ 1 − (n − 1) · τ j=1 1 − (n − 1) · τ (Das heißt PA ist numerisch stabil.) PA (x) = sn besitzt die Darstellung ~ PA (x) = n X (n) rdt (xi )(1 + εi ) ¯i=1 ¯ n n ¯Y ¯ X ¯ ¯ (n) |εk | + (τ 2 ) ≤ (n − i) · τ + (τ 2 ) |εi | = ¯ (1 + εk ) − 1¯ ≤ ¯ ¯ k=i k=i Wählt man die Störung δx von x als (n) (n) (n) δx,i := rdt (xi )(1 + εi ) − xi = (xi )(1 + ε̂i )(1 + εi ) − xi = (xi )(ε̂i + εi (n) + ε̂i · εi ) − xi mit |ε̂i | ≤ τ, i = 1, . . . , n so gilt P (x + δx ) = PA (x)und n X (n) kδx k1 ≤ (|ε̂i | + |εi | + (τ 2 )) ≤ kxk1 (nτ + (τ 2 )) ≤ kxk1 (n + (τ ) · τ ) = FG · τ i=1 41