Einleitung EUKLID Primzahltest Einleitung EUKLID Primzahltest Gliederung Algorithmen und Datenstrukturen – Einführung Algorithmen D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg 1 Einleitung 2 EUKLID 3 Primzahltest Winter 2008/2009, 20. Oktober 2008 D. Rösner AuD 2008/2009 . . . D. Rösner Einleitung EUKLID Primzahltest AuD 2008/2009 . . . Einleitung EUKLID Primzahltest Algorithmus Frage: Was ist die wichtigste Fähigkeit, die in einem Studium der Informatik oder Wirtschaftsinformatik oder Computervisualistik oder Computer Systems Engineering/Ingenieurinformatik oder vergleichbarer Studiengänge erworben und ausgebaut werden sollte? mögliche Antwort: Fähigkeit, für (viele) Probleme Lösungen finden zu können Problemlösungen dabei in Form von Algorithmen, die dann in ausführbare Programme umgesetzt D. Rösner AuD 2008/2009 . . . Algorithmus ist einer der zentralen Begriffe der Informatik Algorithmen: gibt es auch unabhängig von Computern gibt es schon seit tausenden von Jahren Bezeichnung ’Algorithmus’ ist vom Namen des persischen Gelehrten Muhammed Al Chwarizimi (etwa 783 bis 850) abgeleitet (s.a. [PD08]) D. Rösner AuD 2008/2009 . . . Einleitung EUKLID Primzahltest Einleitung EUKLID Primzahltest Algorithmus Algorithmus Algorithmen (zumindest in einem intuitiven Sinne) begegnen uns auch im Alltag: Kochrezepte Bau- und Montageanleitungen Betriebsanleitungen s.a. [SS02] D. Rösner AuD 2008/2009 . . . Einleitung EUKLID Primzahltest Ein Algorithmus ist eine präzise (d.h. in einer festgelegten Sprache abgefasste) endliche Beschreibung eines allgemeinen Verfahrens unter Verwendung ausführbarer elementarer (Verarbeitungs-)Schritte. D. Rösner AuD 2008/2009 . . . Einleitung EUKLID Primzahltest EUKLIDs Algorithmus EUKLIDs Algorithmus Auf EUKLID (≈ 300 v. Chr.) geht ein Algorithmus zur Bestimmung des grössten gemeinsamen Teiler (ggT) zweier nicht negativer ganzer Zahlen zurück. Der ggT von x und y ist definiert als diejenige Zahl z, für die gilt: Eine Möglichkeit zum Bestimmen des ggT (x, y): Bestimme die Primfaktorzerlegung von x und von y und bilde das Produkt derjenigen Primfaktoren, die sowohl in der Faktorzerlegung von x wie in der von y vorkommen. EUKLIDs Algorithmus ist ‘einfacher’ und eleganter. Er nutzt die folgenden Beziehungen: z ist Teiler von x, z ist Teiler von y und für jedes z’ mit z’ Teiler von x und z’ Teiler von y gilt: z’ ≤ z D. Rösner eine intuitive Begriffsbestimmung für Algorithmus (vgl. [SS02]) AuD 2008/2009 . . . ggT(x, y) = ggT(y, Rest von x/y) falls y > 0 ggT(x, y) = x falls y = 0 D. Rösner AuD 2008/2009 . . . Einleitung EUKLID Primzahltest Einleitung EUKLID Primzahltest EUKLIDs Algorithmus EUKLIDs Algorithmus eine mögliche Realisierung in Haskell: ggT :: Int -> Int -> Int Fragen: Terminiert der Algorithmus immer? Warum? Wird immer der richtige Wert berechnet? m.a.W.: Ist der Algorithmus korrekt? Hilft Testen beim Beantworten dieser Frage? D. Rösner AuD 2008/2009 . . . Einleitung EUKLID Primzahltest Main> ggT 69 81 3 Main> ggT 43 101 1 Main> ggT 69 23 23 D. Rösner AuD 2008/2009 . . . Algorithmus Primzahltest alternative Realisierung mit Wächtern (guards): ggT’ :: Int -> Int -> Int x y y > 0 = ggT’ y (rem x y) y == 0 = x otherwise = error "ggT’: Argument y darf nicht negativ sein" Bedingungen der Wächter werden nacheinander (von oben nach unten) überprüft sobald eine erfüllt ist, wird ihre rechte Seite (nach =) ausgewertet und ergibt den Wert otherwise als letzter Wächter trifft immer zu (sog. catch all-Bedingung) D. Rösner einige Beispiele für Verwendung: Einleitung EUKLID Primzahltest EUKLIDs Algorithmus ggT’ | | | ggT x y = if y > 0 then ggT y (rem x y) else if y == 0 then x else error "ggT: Argument y darf nicht negativ sein" AuD 2008/2009 . . . Primzahlen . . . z.B. wichtig für bestimmte Verschlüsselungsverfahren im folgenden werden Varianten eines Primzahltest entwickelt (s.a. [SS02], p. 65) zur Erinnerung: Definition: Eine natürliche Zahl n (n > 1) ist genau dann Primzahl, wenn sie nur durch sich selbst und durch 1 teilbar ist. Beispiele: prim oder nicht prim? 2 ist . . . 3 ist . . . alle geraden Zahlen grösser 2 sind . . . 31 ist . . . 51 ist . . . ... D. Rösner AuD 2008/2009 . . . Einleitung EUKLID Primzahltest Einleitung EUKLID Primzahltest Algorithmus Primzahltest Algorithmus Primzahltest erste Version des Algorithmus: erster Schritt: Test auf Teilbarkeit: istTeilerVon :: Int -> Int -> Bool istTeilerVon cand zahl = mod zahl cand == 0 realisiert mit einer Hilfsfunktion: istPrim :: Int -> Bool Beispiele für Verwendung: Main> 5 ‘istTeilerVon‘ 20 True Main> istTeilerVon 7 15 False Main> istTeilerVon 7 63 True D. Rösner Um zu entscheiden, ob n > 1 Primzahl, teste, ob n durch irgendeine Zahl m mit 2 <= m < n teilbar. Wenn dies zutrifft, dann ist n nicht prim, andernfalls ist n prim. istPrim n = if n <= 1 then False else primtest 2 n primtest m n = if m >= n then True else if istTeilerVon m n then False else primtest (m + 1) n AuD 2008/2009 . . . D. Rösner Einleitung EUKLID Primzahltest Einleitung EUKLID Primzahltest Algorithmus Primzahltest Algorithmus Primzahltest Variante 1 funktioniert (d.h. ist effektiv), ist aber nicht effizient genug verbesserte Variante: Ziel: unnötigen Aufwand vermeiden es brauchen nur m = 2 und dann nur noch ungerade m getestet werden es braucht auch nicht bis m = n getestet zu werden, sondern es reicht zu testen, solange m*m <= n AuD 2008/2009 . . . Variante 2: istPrim’ :: Int -> Bool istPrim’ n = if n <= 1 || (n > 2 && istTeilerVon 2 n) then False else primtest 3 where primtest m = if m * m > n then True else if istTeilerVon m n then False else primtest (m + 2) Mit beiden Veränderungen lässt sich der Aufwand deutlich verringern. Hinweis: primtest ist hier lokale Definition (nach where), d.h. nur innerhalb von istPrim’ sichtbar Motto (manchmal): Make it work, then make it fast! n ist innerhalb von primtest ’sichtbar’ und braucht daher nicht als Parameter übergeben zu werden D. Rösner AuD 2008/2009 . . . D. Rösner AuD 2008/2009 . . . Einleitung EUKLID Primzahltest Einleitung EUKLID Primzahltest Algorithmus Primzahltest Literatur: weitere Variante: istPrim’’ :: Int -> Bool istPrim’’ n = if n <= 1 then False else primtest 2 where primtest m = if m * m > n then True else if istTeilerVon m n then False else primtest (if (m==2) then (m+1) else (m+2)) Hinweis: der letzte else-Zweig in primtest könnte gleichwertig auch wie folgt lauten: ... Gustav Pomberger and Heinz Dobler. Algorithmen und Datenstrukturen – Eine systematische Einführung in die Programmierung. Pearson Education Dtl. GmbH, München, 2008. Gunter Saake and Kai-Uwe Sattler. Algorithmen und Datenstrukturen – Eine Einführung mit Java. dpunkt.verlag, Heidelberg, 2002. ISBN 3-89864-122-8. else if istTeilerVon m n then False else if (m==2) then primtest (m+1) else primtest (m + 2) D. Rösner AuD 2008/2009 . . . D. Rösner AuD 2008/2009 . . .