Freitag, 4. Mai 2007O-Notation BeispieleViele meiner Suchanfragen lassen vermuten, dass einige Informatikstudenten im ersten Semester händeringend nach Beispielen suchen, wie man mit der O-Notation umgeht. Ich werde hier ein Beispiel durchrechnen, in der Hoffnung dass es jemandem hilft. Lasst doch ein Kommentar da wenn das der Fall ist ;) Also, neben der informellen Beschreibung der O-Notation gibt es natürlich auch den streng formalen Weg. Zunächst nehme ich mir mal den Bubble-Sort heraus und kopiere den Pseudocode von Wikipedia: Jetzt analysieren wir, wie man diesen Algorithmus bezüglich der O-Notation klassifizieren muss. Zunächst einigen wir uns darauf, dass wir nur Zuweisungen, Additionen und Vertauschungen (was ja auch nur Zuweisungen sind) als Rechenschritt zählen. Alles andere kostet natürlich auch Zeit, macht aber verhältnismäßig wenig aus. Also los: Zeile zwei ist eine Zuweisung, das ist ein Rechenschritt. Alles was zwischen Zeile drei und zwölf steht wird wiederholt, und zwar so lange bis das Array sortiert ist. Wann ist das im schlimmsten Fall passiert? Natürlich wenn das Array umgekehrt sortiert ist. Denn dann muss das vorderste Element nach hinten und umgekehrt. Da Bubble-Sort immer nur direkte Nachbarn vertauscht, muss jedes Element also ganz durchgeschoben werden. Also weiter, das erste Element muss also ganz nach hinten, braucht dafür n Durchläufe der "für"-Schleife. Pro einen solchen Durchlauf brauchen wir einen Vergleich, eine Vertauschung und eine Zuweisung. Wir sind also im Moment bei Da bekommen wir also Da steht also folgendes: Es gibt eine Funktion g, die schneller oder gleich schnell als unsere Funktion f wächst. Dazu multiplizieren wir noch eine Konstante c dran, die wir uns für den Beweis wählen können. Plastischer wirds erst, wenn ich das mal eben für das Beispiel durchführe. Jetzt muss ich nur noch ein c und ein Ich wähle
O-Notation Beispiele Geschrieben von Turing
in Geek-Zeug um
11:04
Kommentare (5) Trackbacks (0) Tags für diesen Artikel: algorithmus, geek-zeug, informatik, komplexität, o-notation, sonstiges mathematisches, wachstum
Donnerstag, 22. März 2007Polynomiell vs. exponentiellIch hatte ja schon über die O-Notation gesprochen und schon angedeutet, dass wir nur im wesentlichen polynomielle und exponentielle Laufzeiten auseinander halten wollen. Die Grafik im betreffenden Post war ja schon ganz anschaulich, aber ich will es doch noch ein bisschen plastischer machen um auch die praktisch veranlagten zu überzeugen. Ich habe ein paar Tests laufen lassen und habe einen kleinen, sinnlosen Algorithmus in Python geschrieben. Dieser füllt ein Array und macht nichts weiter außer ein paar überflüssigen Additionen. Für ein Array der Größe 100 braucht dieser Aber ich schweife ab. Mein Algorithmus braucht also eine Sekunde für n=100. Das bedeutet für 1003 "Schritte" braucht mein Computer eine Sekunde. Erhöhen wir mal auf n=1000, da wären wir bei runden 17 Minuten für 10003 Schritte. Das ist schon nicht mehr ganz wenig. Für n=10000 allerdings wären wir bereits bei guten 31000 Jahren. Das ist bereits utopisch für den realen Einsatz, aber wie siehts denn im Vergleich mit Für n=10 haben wir noch überschaubare 17 Sekunden, aber da hört es auch schon auf. Wir erinnern uns: beim Man zieht also die Grenze da, wo das n im Exponent steht. Das führt natürlich auch zu Ungenauigkeiten, so wäre
Polynomiell vs. exponentiell Geschrieben von Turing
in Millenium-Probleme, P vs. NP um
20:48
Kommentare (0) Trackbacks (0) Tags für diesen Artikel: algorithmus, determinismus, millenium-probleme, o-notation, p vs. np, turing-maschine
Dienstag, 6. März 2007O-NotationHier also der erste Beitrag mit Substanz, es geht um die O-Notation. Das werden wir brauchen um uns zu überlegen, was effektive Algorithmen sind und was nicht. Ein Algorithmus ist übrigens eine Abfolge von Schritten, um ein gegebenes Problem zu lösen. Es liegt natürlich nahe, einen Algorithmus in ein Computerprogramm zu verpacken, das ist aber nicht zwingend nötig für eine Laufzeitberechnung. Womit wir schon beim Thema wären, denn Algorithmen lassen sich nicht exakt vergleichen, dafür gibt es einfach zu viele unbekannte Faktoren. Zum Beispiel ist eine Implementierung in C sicher schneller als in Ruby, es sei denn der Programmierer baut großen Mist. Vielleicht benutzt der eine Programmierer noch einen Pentium 3, während der nächste auf einem Athlon64 sitzt und deshalb besser mit großen Zahlen rechnen kann. Oder vielleicht implementiert die Standard-Library von Betriebssystem A die verkettete Liste etwas langsamer als System B. Kurz gesagt, diese ganzen Unwägbarkeiten müssen raus und man muss sich Zwecks Vergleichbarkeit auf das absolute Minimum eines Algorithmus beschränken. Das wäre eben die Beschreibung der nötigen Schritte pro Element. Formal braucht man auch immer eine Eingabe und Ausgabe dazu, bei der Ausgabe kann man sich aber oft auf "wahr" oder "falsch" beschränken, wie wir später sehen werden. Ein Beispiel: Sagen wir, Schritt 1, 3 und 5 brauchen "eine Zeiteinheit", 2 und 4 brauchen jeweils drei. Pro Bier brauchen wir also neun Schritte, ganz unabhängig davon z.B. welche Biermarke wir haben. Um das Ziel des Algorithmus zu erreichen brauchen wir also ganz allgemein 9*n Schritte, wobei "n" die Anzahl Bier ist, bis man komplett dicht ist (und das variiert von Person zu Person, was hier die "Eingabe" wäre). Aber wie relevant ist die neun denn wirklich? Was, wenn wir einfach den Alkoholgehalt pro Flasche verdoppeln? Dann bräuchten wir nur noch 4,5*n Schritte. Man könnte auch weitere Laufzeitverbesserungen vornehmen indem man zwei Bier pro Lauf mitnimmt, dann wären wir bei Dazu auch ein Beispiel: Wir vergleichen Übrigens umfasst das "O" auch andere Laufzeiten, gibt damit sozusagen eine obere Schranke an. Wenn man O(n) schreibt, meint man "Der Algorithmus schafft das Problem in linearer Zeit, obwohl es vielleicht spezielle Eingabe gibt, wo er nach einem Schritt fertig ist." In jedem Fall aber braucht er nicht länger als Linearzeit. Wenn man eine genaue Aussage treffen will nimmt man Wichtige Laufzeiten sind z.B. Dabei bedeutet O(1) nicht, dass in jedem Fall nur ein Schritt nötig ist, es können auch 10000 Schritte nötig sein. In jedem Fall muss die Anzahl der Schritte konstant sein um O(1) genannt werden zu dürfen. Um ein Gefühl für das Wachstumsverhalten zu bekommen, hier zum Schluss nochmal ein Plot der Funktionen.
Fassen wir also zusammen: Um Algorithmen zu vergleichen abstrahiert man so viel wie möglich, lässt im wesentlichen alle nicht relevanten Terme weg und betrachtet nur den Teil des Algorithmus, der am schnellsten wächst. Und weil ihr bis hier durchgehalten habt, kommt hier der Clou: Eigentlich interessiert nur, ob das n im Exponent steht oder nicht.
O-Notation Geschrieben von Turing
in Millenium-Probleme, P vs. NP um
11:50
Kommentare (2) Trackbacks (0) Tags für diesen Artikel: algorithmus, laufzeit, millenium-probleme, notation, o-notation, p vs. np, wachstum
|
KategorienFeedsGetaggte Artikelööh.. informatik?
algorithmus china determinismus entscheidbarkeitstheorie fehlerwahrscheinlichkeit fernsehen filme formale sprachen games geek-zeug informatik komplexitã¤t komplexitã¤tsklasse laufzeit linux medien millenium-probleme monty hall nichtdeterminismus nicht eingã¤ngig nintendo ds np o-notation p poker p vs. np randomisierung rffc RP sco sonstiges sonstiges mathematisches spieltheorie statik technische mechanik tm turing turing-maschine universelle turingmaschinen utm videospiele wachstum wahrscheinlichkeit xkcd zpp SonstigesBlogrollSuche |
Powered by s9y - Design by Lordcoffee