1 / 32 Einstieg in die Informatik mit Java Effizienz Gerd Bohlender Institut für Angewandte und Numerische Mathematik
Gliederung 2 / 32 1 Überblick: was ist Effizienz? 2 Landau-Symbole 3 Eier im Korb 4 Zyklische Ziffern
Gliederung 3 / 32 1 Überblick: was ist Effizienz? 2 Landau-Symbole 3 Eier im Korb 4 Zyklische Ziffern
4 / 32 Überblick: was ist Effizienz? In diesem Kapitel betrachten wir verschiedene Aspekte der Effizienz eines Programms Benötigte Rechenzeit Ausnutzung der Performance des Computers Beispiel Parallelrechner mit p Prozessoren: Effizienz(p) = Zeit(1) pzeit(p) Benötigter Speicher Aufwand des Programmierers... 2 Beispiele
Gliederung 5 / 32 1 Überblick: was ist Effizienz? 2 Landau-Symbole 3 Eier im Korb 4 Zyklische Ziffern
Asymptotischer Aufwand eines Algorithmus Landau-Symbole 6 / 32 Landau-Symbole: Schreibweise f (n) O(g(n)) für f wächst nicht wesentlich schneller als g (Edmund Landau, Berlin / Göttingen / Jerusalem, 1877-1938) Die Funktion f (n) ist O(g(n)), für n, genau wenn es Konstanten n 0 und M gibt mit f (n) < M g(n) für alle n > n 0 Alternative Definition: f (n) O(g(n)) genau wenn 0 lim sup n f (n) g(n) < Weitere Varianten siehe http://de.wikipedia.org/wiki/landau-symbole
Landau-Symbole Beispiele 7 / 32 g(n) ist meist eine einfache Funktion, z.b. O(n), O(n 2 ), O(log n),... Notation Bedeutung wenn das Argument verdoppelt wird, f f wächst dann ändert sich f etwa so: O(1) garnicht f bleibt beschränkt O(n) linear f verdoppelt sich O(n log n) superlinear f wächst auf etwas mehr als das Doppelte O(n 2 ) quadratisch f vervierfacht sich O(n 3 ) kubisch f verachtfacht sich O(2 n ) exponentiell wenn das Argument um 1 erhöht wird, dann verdoppelt sich f
8 / 32 Landau-Symbole Anwendung Angaben zum Rechenaufwand eines Algorithmus (asymptotische Komplexität) Angaben zum Speicherbedarf eines Algorithmus Beispiel n n-matrix (Zahlenschema mit n Zeilen und n Spalten) Speicherbedarf O(n 2 ) Rechenaufwand für Addition O(n 2 ) Rechenaufwand für Multiplikation O(n 3 ) n O(n 2 ) O(n 3 ) 10 100 1000 100 10000 1000000 1000 1000000 1000000000
9 / 32 Landau-Symbole Rechenregeln Rechenregeln für den asymptotischen Aufwand: Konstante Faktoren spielen keine Rolle: O(c g(n)) = O(g(n)) für eine reelle Konstante c 0, folglich gilt auch O(log 2 n) = O(ln n) = O(log 10 n) Langsamer anwachsende Terme können vernachlässigt werden, z.b. gilt mit reellen Konstanten a > b und c: O(n a + c n b ) = O(n a ) O(n a + c log n) = O(n a ) O(2 n + c n b ) = O(2 n ) Beispiel: O(2n 3 + 3n 2 + 24n + 799) = O(n 3 )
Landau-Symbole Einsatz zum Vergleich von Algorithmen 10 / 32 Beispiel: sortiere n Zahlen x 0, x 1,..., x n 1 Algorithmus 1 (Bubblesort) Algorithmus 2 (Quicksort) n O(n 2 ) O(n log n) 2 4 2 4 16 8 8 64 24... 1000 10 6 10000 10 6 10 12 20 10 6 Algorithmus ist für n = 10 6 etwa 100000 mal schneller. 100000 1 Tag / 1 Sekunde
11 / 32 Landau-Symbole Vorsicht Aber Vorsicht! Alle Aussagen gelten nur asymptotisch für n, also ab einem (unbekannten) n 0 und mit einem (unbekannten) Faktor M. Für ein kleines n könnte Algorithmus 1 durchaus schneller sein als Algorithmus 2.
Gliederung 12 / 32 1 Überblick: was ist Effizienz? 2 Landau-Symbole 3 Eier im Korb 4 Zyklische Ziffern
Eier im Korb - Aus einem alten Rechenbuch 13 / 32 Ein Mann stößt den Korb voller Eier einer Marktfrau um. Die Eier gehen zu Bruch. Der Mann will den Schaden ersetzen und fragt wieviele Eier im Korb waren. Die Marktfrau antwortet: Die genaue Zahl weiß ich nicht. Aber wenn ich immer 2 Eier aus dem Korb genommen habe, dann blieb eines übrig. Genauso, wenn ich immer 3, immer 4, immer 5 oder immer 6 Eier heraus genommen habe. Aber wenn ich immer 7 Eier heraus genommen habe, dann blieb keines übrig. Wieviele Eier waren (mindestens) im Korb?
14 / 32 Eier im Korb - Erster Algorithmus Teste alle Zahlen n = 1, 2, 3,... Beginne mit n = 1 Prüfe, ob die Zahl n bei Division durch 2, 3, 4, 5, 6 den Rest 1 ergibt und ob n durch 7 ohne Rest teilbar ist. Ist dies der Fall, dann brich ab und gib das Ergebnis aus. Andernfalls erhöhe n um 1 und prüfe nochmal.
Eier im Korb - Erstes Java-Programm 15 / 32 public class Eier { } public s t a t i c void main ( S t r i n g [ ] args ){ i n t i =0; do i ++; while ( i %2!=1 i %3!=1 i %4!=1 i %5!=1 i %6!=1 i %7!=0); System. out. p r i n t l n ( Es waren + i + Eier im Korb. ) ; }
16 / 32 Eier im Korb - Zweiter Algorithmus Es kommen nur Zahlen in Frage, die bei Division durch 2, 3, 4, 5, 6 den Rest 1 ergeben. Mit etwas Mathematik stellt man fest: Es kommen nur Zahlen in Frage, die bei Division durch kgv(2, 3, 4, 5, 6) = 60 den Rest 1 ergeben. Also: Teste alle Zahlen n = 1, 61, 121... Beginne mit n = 1 Prüfe, ob n durch 7 ohne Rest teilbar ist. Ist dies der Fall, dann brich ab und gib das Ergebnis aus. Andernfalls erhöhe n um 60 und prüfe nochmal.
Eier im Korb - Zweites Java-Programm 17 / 32 public class Eier2 { } public s t a t i c void main ( S t r i n g [ ] args ){ i n t i =1; do i += 60; while ( i%7!= 0 ) ; System. out. p r i n t l n ( Es waren + i + Eier im Korb. ) ; }
18 / 32 Vergleich der Effizienz Programm 2 braucht nur 1/60 der Rechenzeit von Programm 1 Beide Programm brauchen nur Bruchteile einer Sekunde Rechenzeit spielt hier keine Rolle Fazit: Die Arbeitszeit des Programmierers für die mathematischen Überlegungen ist verschwendet Übrigens... es waren 301 Eier im Korb!
Gliederung 19 / 32 1 Überblick: was ist Effizienz? 2 Landau-Symbole 3 Eier im Korb 4 Zyklische Ziffern
20 / 32 Zyklische Ziffern - Das Problem Finde eine Zahl mit Endziffer 5 Multipliziere sie mit 5 Ist das Produkt gleich der ursprünglichen Zahl, wenn man die 5 am Ende streicht und dafür vorne anfügt? Beispiel: 5 * abcd5 = 5abcd (mit 4 Ziffern a, b, c, d) Verallgemeinerung: ersetze 5 durch Faktor 2 bis 9 Quelle: Jacques Arsac, Computerdenkspiele selbst programmiert, Problem 3
21 / 32 Zyklische Ziffern - Erster Algorithmus Teste alle Zahlen n = 1, 2, 3,... Beginne mit n = 1 Prüfe, ob die Zahl n die Bedingung Zyklische Ziffern erfüllt Ist dies der Fall, dann brich ab und gib das Ergebnis aus. Andernfalls erhöhe n um 1 und prüfe nochmal.
Zyklische Ziffern - Erstes Java-Programm 22 / 32 public class Z y k Z i f f 1 { } public s t a t i c void main ( S t r i n g [ ] args ){ i n t i =0; do i ++; while ( i 5!= i /10+50000); / / bei 4 Z i f f e r n abcd System. out. p r i n t l n ( Zyklische Z i f f e r n : + i ) ; }
23 / 32 Zyklische Ziffern - Probleme mit diesem Programm Unbekannt, ob 4 Stellen abcd nötig sind oder mehr oder weniger Ggf. müssen alle Stellenzahlen durchprobiert werden Reicht der Zahlbereich von int (9 Stellen) aus? Reicht long (19 Stellen)? Rechenzeit???
24 / 32 Zyklische Ziffern - Mathematische Idee Führe Ziffernvergleich bei 5 abcd5 = 5abcd durch, beginnend bei der niederwertigsten Ziffer. 5 abcd5 = 5abcd führt wegen 5 5 = 25 zu d = 5 Es entsteht ein Übertrag von 2, der im nächsten Schritt zu berücksichtigen ist 5 abc55 = 5abc5 führt wegen 5 5 + 2 = 27 zu c = 7 Es entsteht ein Übertrag von 2 5 ab755 = 5ab75 führt wegen 5 7 + 2 = 37 zu b = 7 Es entsteht ein Übertrag von 3 usw. (egal wie viele Stellen abcd vorliegen) Der Algorithmus ist zu Ende, wenn die berechnete Ziffer = 5 ist, und der Übertrag = 0 ist
25 / 32 Zyklische Ziffern - Zweiter Algorithmus Verallgemeinerung: ersetze 5 durch beliebigen Faktor 2 bis 9 Starte mit Ziffer = Faktor und Übertrag = 0 Berechne das 2-stellige Produkt = Ziffer * Faktor + Übertrag Zerlege Produkt in die niederwertige Ziffer und den höherwertigen Übertrag Wiederhole solange die berechnete Ziffer nicht gleich dem Faktor ist, oder der Übertrag nicht 0 ist
Zyklische Ziffern - Zweites Programm 26 / 32 import java. u t i l. ; public class Z y k z i f f 5 { public s t a t i c void main ( String [ ] args ) { Locale. s e t D e f a u l t ( Locale.US ) ; Scanner sc = new Scanner ( System. in ) ; i n t Faktor, Ziffer, Uebertrag =0, Produkt, Stellen =0; System. out. p r i n t ( Mit welchem Faktor s o l l m u l t i p l i z i e r t werden? ) ; Faktor = sc. nextint ( ) ; / / Faktor einlesen Z i f f e r = Faktor ; / / n i e d e r w e r t i g s t e Z i f f e r = Faktor System. out. p r i n t l n ( Das Ergebnis l a u t e t ( rueckwaerts gelesen! ) : ) ; do { System. out. p r i n t ( Z i f f e r ) ; / / a k t u e l l e Z i f f e r ausdrucken S t e l l e n ++; / / S t e l l e n z a h l bei j e d e r Ausgabe erhoehen Produkt = Z i f f e r Faktor + Uebertrag ; / / neues Produkt, z w e i s t e l l i g Z i f f e r = Produkt % 10; / / neue Z i f f e r = n i e d e r s t e S t e l l e des Produkts Uebertrag = Produkt / 10; / / neuer Uebertrag = hoechste S t e l l e des Produk } / / wiederholen, wenn eine der beiden... while ( Z i f f e r!= Faktor Uebertrag!= 0 ) ; / /... Abbruch Bedingungen v e r l e t z t i s t System. out. p r i n t l n ( ) ; System. out. p r i n t l n ( Es hat + S t e l l e n + S t e l l e n ) ; } }
Zyklische Ziffern - Ergebnisse 27 / 32 c:\b\java>java Zykziff5 Mit welchem Faktor soll multipliziert werden? 5 Das Ergebnis lautet (rueckwaerts gelesen!): 557783964376381959798442216035623618040201 Es hat 42 Stellen
Zyklische Ziffern - Ergebnisse 28 / 32 Mit welchem Faktor soll multipliziert werden? 2 248637498751362501 Es hat 18 Stellen Mit welchem Faktor soll multipliziert werden? 3 3973142715569860268572844301 Es hat 28 Stellen Mit welchem Faktor soll multipliziert werden? 4 465201 Es hat 6 Stellen Mit welchem Faktor soll multipliziert werden? 6 6697760446811726754748050389833022395531882732452519496101 Es hat 58 Stellen Mit welchem Faktor soll multipliziert werden? 7 7975048813263572944101 Es hat 22 Stellen Mit welchem Faktor soll multipliziert werden? 8 8487228562101 Es hat 13 Stellen Mit welchem Faktor soll multipliziert werden? 9 91742202834944046788980825779716505595321101 Es hat 44 Stellen
29 / 32 Zyklische Ziffern - Laufzeit des zweiten Algorithmus 42 Schleifendurchläufe etwa 10 Operationen pro Schleife theoretisch etwa 10 7 Sekunden auf einem handelsüblichen PC mit Java-Overhead (Interpretation, Startup) deutlich unter 1 Sekunde
30 / 32 Zyklische Ziffern - Laufzeit des ersten Algorithmus Er benötigt 10 42 Schleifendurchläufe = etwa 10 43 Operationen Schnellster Rechner zzt. (2009, Quelle: www.top500.org): etwa 10 15 Flops (Floating point Operationen pro Sekunde) Dieser braucht etwa 10 28 Sekunden zur Lösung 10 28 Sekunden = etwa 10 20 Jahre (1 Jahr = 365 86400 Sekunden = etwa 3 10 7 Sekunden)... aber das Universum existiert erst etwa 10 10 Jahre seit dem Urknall!
31 / 32 Zyklische Ziffern - Laufzeitvergleich der beiden Algorithmen Der erste Algorithmus braucht 10 20 Jahre auf dem schnellsten Rechner der Erde Der zweite Algorithmus braucht einen Bruchteil einer Sekunde auf einem handelsüblichen PC Fazit: Nachdenken über mathematische Hintergründe hat sich gelohnt
Zyklische Ziffern - Wann sind Computer schnell genug für den ersten Algorithmus? Der erste Algorithmus braucht 10 20 Jahre auf dem heute schnellsten Rechner der Erde Supercomputer wurden im letzten Jahrzehnt fast um den Faktor 1000 schneller (Quelle: www.top500.org) In 70 Jahren wäre das (theoretisch!!!) ein Faktor 10 21 Im Jahre 2080 bräuchte der schnellste Computer der Erde noch 1 Monat (sehr theoretisch!!!) 32 / 32