Karl Schwalen 6.06 Version 10.12 Weitere Aufsätze des Verfassers unter http://www.primath.homepage.t-online.de Das Fermat-Verfahren u. das Lehman-Verfahren zur Faktorisierung Die Basis-Algorithmen sowie Varianten zu deren Optimierung Inhaltsübersicht Seite 1. Das Fermat Verfahren 1.1 Grundlagen und Basis-Algorithmen 1.2 Kenngrößen des Verfahren .... .... .... .... .... .... .... .... .... .... .... 2 4 2. 2.1 2.2 2.3 Restklassen-Restriktionen Unterscheidung nach Restklassen mod 8 .... Einschränkung der Lösungsmenge .... .... Bestimmung optimaler Moduln / Quadratfilter .... .... .... .... .... .... .... .... .... .... 6 8 10 3. 3.1 3.2 3.3 Verwendung von Vorfaktoren Beschreibung der Wirkungsweise fester Vorfaktor .... .... .... variable Vorfaktoren .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... 14 16 18 .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... 22 22 23 24 Anlage 1 Zur Lösungsanzahl von x2 – n ≡ y2 mod m .... .... .... nach Seite 26 4. Das Lehman-Verfahren 4.1 4.2 4.3 4.4 Der Basis-Algorithmus .... Optimierungsmöglichkeiten Der „Spitzendetektor“ .... Aussieben geeigneter Faktoren .... .... .... .... Anhang 1 Zum Lösungsansatz 2k–2 ⋅ x 2 + a⋅x – n+r 2 k = 2k–2 ⋅ y 2 + b⋅y Anhang 2 Programm für den seriellen Einsatz von Vorfaktoren Anhang 3 Vergleich Lehman Verfahren versus Spitzendetektor 1 Vorbemerkung: Die hier angesprochenen Methoden (im wesentlichen das Fermat- und das daraus entwickelte Lehman-Verfahren), die die Zerlegung einer ganzen Zahl durch deren Darstellung als Differenz zweier Quadratzahlen bewerkstelligen, werden heute meist nur noch aus Gründen der historischen Vollständigkeit am Rande behandelt. Die im Zusammenhang mit der Kryptografie auf diesem Gebiet betriebene Forschung hat inzwischen zu ungleich leistungsfähigeren Faktorisierungs-Verfahren geführt. Da aber auch die meisten der neueren Methoden indirekt darauf fußen, erscheint es nicht gänzlich uninteressant, die mannigfaltigen Optimierungsmöglichkeiten dieses elementaren Verfahrens ausführlicher darzustellen. Es wird dabei aufgezeigt, wie sowohl das Fermat- als auch das Lehman-Verfahren sich gegenüber den Standard-Algorithmen wesentlich leistungsfähiger gestalten lassen. 1. Fermat-Verfahren 1.1 Grundlagen Ausgangspunkt ist das Binom x2 – y2 = (x – y)⋅(x + y) [= t1⋅t2 = n] (1.∗) Die Darstellung einer ganzen Zahl als Differenz zweier Quadratzahlen liefert also zugleich das Teilerpaar (x + y, x – y) der betr. Zahl. Welche Zahlen besitzen eine solche Darstellung? In der Identität [n =] t1⋅t2 = ( t1 + t 2 2 ) 2 −( t1 − t 2 2 ) 2 müssen – wie der Vergleich mit (1.∗) zeigt – die beiden Klammerterme ganzzahlig sein. Das ist der Fall, wenn die ganzen Zahlen t1 und t2 beide gerade oder beide ungerade sind, da ihre Summe bzw. Differenz nur dann durch 2 teilbar ist. Sind beide Teiler ungerade, ist auch n ungerade; sind dagegen beide gerade, ist ihr Produkt n durch 4 teilbar. Ungerade Zahlen besitzen daher für jedes Teilerpaar eine Darstellung als Differenz zweier Quadrate; gerade Zahlen dagegen nur für die Teilerpaare, bei denen Teiler und Komplementärteiler beide gerade sind. Zahlen der Form n ≡ 2 mod 4 lassen sich aus diesem Grund nicht als Quadrate-Differenz schreiben. Für die triviale Zerlegung (einer ungeraden Zahl) n = 1⋅n ist wegen x – y = 1 und x + y = n stets x = (n+1)/2 und y = (n – 1)/2. Ist dagegen n eine Quadratzahl, erhält man die unteren Grenzen von x und y aus n = x2 – 02 zu x = n und y = 0. Während der kleinere Teiler t1 nur im Intervall [1, n ] zu suchen ist, können x und y also beinahe im gesamten Bereich von 0 bis n/2 auftreten! Um auf der Basis von (1.∗) dennoch zumindest für Zahlen mit einem Teiler t1 , der nur (relativ) wenig kleiner als n ist, zu einem brauchbaren Verfahren zu kommen, ging bereits Fermat so vor, dass er – ausgehend von u = n – in der Gleichung m = u2 – n den Wert von u sukzessive erhöhte und dann jeweils prüfte, ob m ein Quadrat war. Ist m ein solches, hat man mit u – m einen Teiler von n gefunden. Somit erhält man als 2 Basis-Algorithmus Fermatverfahren Eingabe: n (n mod 4 ≠ 2) u = Int(Sqr(n)): m = u^2 – n: w = 0 (*) Do While w ^2 <> m u = u + 1: m = u^2 – n: w = Int(Sqr(m)) Loop Ausgabe: Teilerpaar t1 = u – w, t2 = u + w If u – w > 2 Then w = – n: Goto (*) Mittels der (eigentlich nicht zur Basis-Variante gehörenden) letzten Zeile liefert der Algorithmus alle Teilerpaare einer ungeraden Zahl; für durch 4 teilbare Zahlen jedoch nur die Teilerpaare, bei denen Teiler und Komplementärteiler gerade sind. Gibt man anstelle der Zahl n die Eingabe 4⋅n vor, so erhält man auch im Falle eines geraden n (einschließlich n mod 4 = 2) alle Teilerpaare, wobei die beiden Ausgabewerte (u – w) bzw. (u + w) jeweils durch 2 zu teilen sind. Da im obigen Alg. u ab u = n die Folge der Quadratzahlen durchläuft, und die Differenz zweier benachbarter Quadratzahlen (u + 1) 2 – u 2 = 2u + 1 ist, lässt sich die fortlaufende Berechnung von u 2 – n vermeiden: Eingabe: n (n mod 4 ≠ 2) u = Int(Sqr(n)): m = u^2 – n: w = 0 Do While w ^2 <> m m = m + 2*u + 1: w = Int(Sqr(m)): u = u + 1 Loop Ausgabe: Teilerpaar t1 = u – w, t2 = u + w Eine dritte Variante des Basis-Algorithmus kommt innerhalb der While – Loop-Schleife gänzlich ohne Multiplikationen und Wurzelberechnungen aus: Eingabe: n (n mod 4 ≠ 2) u = Int(Sqr(n)): r = n – u^2: v = 2*u + 1: w = 1 Do While r > 0 Do While r < v r = r + w: w = w + 2 Loop r = r – v: v = v + 2 Loop Ausgabe: Teilerpaar t1 = (v – w) / 2 , t2 = (v + w – 2) / 2 Die Haupt-Schleife wird in den drei Varianten gleich oft durchlaufen. Bei der letztgenannten wird die innere Schleife je Durchlauf der Haupt-Schleife während der ersten Schritte des Verfahrens allerdings mehrfach durchlaufen. Experimentell findet man, dass die dritte Variante etwa erst ab einem Teilerverhältnis t 2 / t1 > 4 zeitliche Vorteile bringt. (Eine das berücksichtigende Anwendung nebst Erläuterung siehe Ziffer 2.) Zunächst werden nun einige Kenngrößen des Verfahrens abgeleitet. 3 1.2 Kenngrößen des Verfahren • Abhängigkeit der ’Schrittzahl’ i (Anzahl der zu prüfenden Differenzen u2 – n bis ein Quadrat gefunden wird) vom Teilerverhältnis. Es sei wiederum n = t1⋅t2 mit t1 < t2 . Dann ist t1 = x – y = x – t2 = x + x 2 − n . Damit erhält man eine Gleichung für das Teilerverhältnis v = t2 / t1. Die Auflösung dieser Gleichung nach x führt auf x = x= v +1 2⋅ v ⋅ n . Da die Suche bei n +1 beginnt, besteht zur Schrittzahl die Beziehung i = x – n . Daraus 1 n . Au i = ( v + − 2)⋅ +1 2 v folgt Wegen • x 2 − n und v= t2 t1 und n= (1.∗∗) t 1⋅t 2 ist das gleichwertig mit i = t1 + t 2 − 2 n . Länge (si) des i-ten Schrittes Unter der ’Länge des i-ten Schrittes’ wird hier die Größe des Intervalls bezeichnet, in dem der Teiler t 2 liegen kann, wenn er im i-ten Schritt des Basis-Alg. gefunden wird. Wie aus (1.∗∗) ersichtlich, kann v infolge der Rundungsvorschrift in einem gewissen Umfang variieren ohne dass i sich ändert. Auflösen des Rundungsterms nach v ergibt für io = i – 1 = const.: t2 = n + io ± v = n + io ± 2 io n + io 2 2 i o n + i o ) / n bzw. 2 . Im 1. Schritt (io = 1) wird genau dann ein Teiler von n gefunden, wenn n +1 ≤ t 2 < n + 1 + 2 n + 1 .(Wegen t 2 > t 1 ist t2 min = n +1 d.h. in diesem Fall ist nur das positive Vorzeichen vor dem Wurzelterm gültig.) Damit ist im Sinne der obigen Definition s 1 = 2 n + 1 ≈ 2 ⋅4 n . Wurde also im 1. Schritt kein Teiler gefunden, besitzt n im Bereich zwischen 1 + n und 1 + n + 2 ⋅4 n keinen Teiler. Für den i. Schritt folgt (solange die Voraussetzung ’i sehr viel kleiner n ’ erfüllt ist), durch Bildung der Differenzen analog si ≈ ( 2⋅i − 2⋅(i −1) ) ⋅ 4 n [= r⋅ 4 n ]. Nachstehend sind einige Werte des Faktors r von i = 1: 2: 3: 4: 100: r = 1,41... 0,58... 0,45... 0,37... 0,07... 4 n angeben: (100%) ( 41%) ( 32%) ( 26%) ( 5%) Die Tabelle verdeutlicht, wie schnell das Verfahren mit zunehmender Schrittzahl uneffektiv wird. Andererseits ist die Länge von Schritt 1 durchaus bemerkenswert: 4 Beispiel: n = 10 100 ==> s1 = 1,41⋅ 10 25 D.h. mit einer einzigen Schleife des BasisAlgorithmus lassen sich mehr als 10 24 potentielle (ungerade) Teiler ausschließen, bzw. lässt sich ein in diesem Bereich vorhandener Teiler feststellen. Im Intervall [10 50, 1050 + 1,41⋅ 1025 ] gibt es immerhin etwa s1 / ( ln(1050) + 1) ≈ 1,2⋅ 1023 Primzahlen. Mit den obigen Formeln lässt sich auch der „praktische“ Anwendungsbereich des Verfahrens angeben: Nimmt man an, aus Gründen der zeitlichen Beschränkung sei die maximale Schrittzahl auf i = 10 9 begrenzt, so ergeben sich abhängig vom Teilerverhältnis v folgende Werte: v≤2 nmax = 2,7⋅ 10 20 (Suche nach großen Teilern) 1/3 14 v≤n 10 v≤n 2,0⋅ 10 9 Die Suche nach einem Teilerpaar (t1, t2) mit t2 ≤ 2t1 kann also bis oberhalb 10 20 vollständig durchgeführt werden, während ein ’Primzahltest’ (v = n) nur bis 2⋅10 9 bereits 10 9 Schritte beanspruchen würde. Bevor im weiteren einige Möglichkeiten beschrieben werden, die geeignet sind, die Effektivität des Verfahrens zu steigern, noch drei Anmerkungen: a) Die Form x2 – y2 ist ein Sonderfall des allgemeinen Binoms xm – ym. Für dieses gilt: x m − y m = ( x − y) ⋅ m −1 ∑x h ⋅ y m−1−h . Zur Gewinnung von Faktoren ganzer Zahlen ist nur der h =0 (vorliegend behandelte) Fall m = 2 interessant, da – wie oben erwähnt – jede ungerade Zahl eine solche Darstellung besitzt, während für m > 2 die Dichte dieser Zahlen immer weiter zurückgeht und kein Kriterium bekannt ist, ob eine vorgegebene Zahl tatsächlich eine solche Zerlegung besitzt. [Aus der obigen Formel ist sofort ersichtlich, dass Zahlen, die als xm – ym (m > 1) darstellbar sind, nur dann Primzahlen sein können, wenn x – y = 1 und es somit keine Primzahl der Form n = xm – 1 geben kann, außer wenn x = 2 (Mersenne-Zahlen)]. b) Das hier behandelte Verfahren wurde zuerst von Pierre de Fermat (1601 – 1665) beschrieben. Der Minoriten-Pater Marin Mersenne, über den vielfach der Kontakt Fermat’s zu anderen Gelehrten Frankreichs lief, forderte Fermat in einem Brief auf, als Probe seines Könnens die Faktoren der Zahl 100.895.598.169 anzugeben. Nach kurzer Zeit antwortete Fermat: 112.303 und 898.423. Es ist allerdings kaum anzunehmen, dass er diese bemerkenswerte Leistung mittels des nach ihm benannten o.a. Basis-Algorithmus geschafft hat, denn damit findet man die Lösung erst nach rd. 190.000 Versuchen (, wenn die Suche ab n sukzessive durchgeführt wird). Er hätte dann vermutlich keine Zeit mehr gefunden, seinen berühmten ’letzten Satz’ aufzustellen. Erstaunlich ist, dass Fermat trotz seiner Fähigkeiten im Faktorisieren die sog. 5. Fermat-Zahl F5 = 232 + 1 für eine Primzahl hielt, obwohl 641 ein – zudem recht kleiner, zuerst von L. Euler gefundener – Teiler von F5 ist. c) Algorithmen werden hier größtenteils in leicht ‚lesbarem’ BASIC angegeben, wobei auf Typdeklarationen, Speicherplatzzuweisungen u. dergl. ganz verzichtet wird und Ein-/ Ausgabe-Routinen nur schematisiert angedeutet werden. 5 2. Restklassen-Restriktionen 2.1 Unterscheidung nach den ungeraden Restklassen mod 4 und mod 8 Bei ungeradem n können in n = x2 – y2 die Variablen x und y nicht beide gerade oder beide ungerade sein. Es sei zunächst x = 2v und y = 2w + 1; also n = 4v2 – (4w2 + 4w + 1) und damit (n + 1)/4 = v2 – (w2 + w). Da die rechte Seite der Gleichung eine ganze Zahl ist, muss es auch die linke sein, was gleichbedeutend ist mit n ≡ 3 mod 4. Analog ergibt x = 2v + 1 und y = 2w : (n – 1)/4 = v2 + v – w2. Anstelle eine Lösung von x2 – n = y2 zu suchen, tritt für – (n + 1)/4 = w2 + w und • n ≡ 3 mod 4: v2 • n ≡ 1 mod 4: v2 + v – (n – 1)/4 = w2 Wie eingangs beschrieben, ist die erforderliche Schrittzahl beim Fermat-Verfahren proportional zur Wurzel n. Da hier n (annähernd) durch n / 4 ersetzt wird, kommt man mit der halben Schrittzahl zum Ziel. Mit diesem Ansatz und einer weiteren, unten erläuterten Überlegung, lässt sich das FermatVerfahren weiterentwickeln: Eingabe: n (ungerade Zahl) ‘===================================== ‘Teil 1 IF n MOD 4 = 3 THEN b = (n+1)/4 ELSE b = (3*n+1)/4 u = INT (SQR(b)): m = u^2 – b IF m = 0 THEN t1 = 2 * u – 1: t2 = t1 + 2: GOTO 11 w = 0: k = 1000 FOR i = 1 TO k m = m + 2 * u + 1: u = u + 1 w = INT (SQR (m)): r = m – w *(w + 1) IF r = 0 THEN t1 = 2 *(u – w) – 1: t2 = 2 *(u + w) + 1: GOTO 11 END IF NEXT i '==================================== ‘Synchronisation w = w + 1: b = b + w^2 + w: h = 2 *(w + 1) '==================================== ‘Teil 2 q = INT (SQR(b)): g = 2 * q + 1: r = b – q^2 DO WHILE r > 0 DO WHILE r < g r = r + h: h = h + 2 LOOP r = r – g: g = g + 2 LOOP t1 = g – h: t2 = g + h – 2 '==================================== 11 IF n MOD 4 = 1 THEN IF t1 MOD 3 = 0 THEN t1 = t1/3 ELSE t2 = t2/3 END IF Ausgabe: Teiler: t1;t2 Das bedarf einiger Erklärungen: – In Teil 1 sind die eingangs dieses Abschnitts gewonnenen Erkenntnisse verarbeitet. Um den Programmcode nicht für die beiden Restklassen 1 und 3 (mod 4) trennen zu müssen, werden Zahlen n ≡ 1 mod 4 mit 3 multipliziert; am Schluss wird die 3 dann wieder aus dem Teilerpaar herausdividiert. 6 In der 3. Zeile wird der Sonderfall, dass b ein Quadrat ist, erledigt. Wie man sieht, bereitet die Prüfung, ob die Zahl m von der Form w2 + w ist, keinerlei zusätzliche Probleme; die üblicherweise benutzte (in dieser Basic-Version nicht bereitgestellte) schnelle Funktion isqrt(x) kann auch in diesem Fall eingesetzt werden. – Im oberen Teil wird – sofern nicht vorher eine Lösung gefunden wurde – eine vorgegebene Anzahl (0 ≤ k < n) von Zyklen durchlaufen und die Ausführung dann an Teil 2 (dritte Variante des Basis-Algorithmus gemäß Ziffer 1.) übergeben. Funktionsweise: Eine Lösung ist gefunden, wenn in r = (n + 1)/4 + w2 + w – v2 der Wert von r Null ist . Das ist gleichwertig zu f (w) – f ( w ) = r wobei (n + 1)/4 + w2 + w mit f (w) abgekürzt wurde. Die Differenz r der beiden Terme liegt stets im Intervall [0, g] mit g = 2⋅ f ( w ) – 1; d.h. an den Sprungstellen infolge der Rundung nimmt g jeweils um 2 zu. Bei rekursiver Darstellung dieser Zusammenhänge folgt insgesamt daraus der o.a. Algorithmus. 2 Der eingangs dieser Ziffer 2.1 gemachte Ansatz lässt sich fortsetzen und führt zu folgendem Ergebnis: Bei den folgenden Restklassen mod 2 k existieren für alle Teilerpaare eines ungeraden n natürliche Zahlen x und y, so dass im Fall .... Restklasse n ≡ 1(2) → n = Teilerpaare (x + y)⋅(x – y) n ≡ 1(4) → n = (2x + 2y + 1)⋅(2x – 2y + 1) n ≡ 3(4) → n = (2x + 2y + 1)⋅(2x – 2y – 1) n ≡ 3(8) → n = (4x + 2y + 3)⋅(4x – 2y + 1) n ≡ 7(8) → n = (4x + 2y + 1)⋅(4x – 2y – 1) Berechnungsansatz → Startwert für x x2 – n = y2 n −1 = y2 x2 + x – 4 n +1 x2 – = y2 + y 4 n−3 4x 2 + 4x – = y2 + y 4 n +1 4x 2 – = y2 + y 4 x= n x= ( n − 1) x= n + 1 x= n + 1 x= 1 2 1 2 1 4 1 4 ( n + 1 − 2) Darüber hinaus scheint es keine derartigen Zerlegungen zu geben, die für eine gesamte Restklasse mod 2 k Gültigkeit besitzen; vielmehr beschränkt sich deren Gültigkeit auf bestimmte Teiler-Restklassen mod 2 k , was die Eignung zur Teilersuche naturgemäß beeinträchtigt. Als Beispiel seien die beiden übrigen Restklassen mod 8 aufgeführt: n ≡ 1(8) – Restklassen der Teilerpaare mod 8 : (1, 1) und (5, 5) n −1 n = (4x + 4y + 1)⋅(4x – 4y + 1) 2x 2 + x – = 2y 2 8 – Restklassen der Teilerpaare mod 8 : (3, 3) und (7, 7) n−9 n = (4x + 4y + 3)⋅(4x – 4y + 3) 2x 2 + 3x – = 2y 2 8 7 n ≡ 5(8) – Restklassen der Teilerpaare mod 8 : (3, 7) 4x 2 + 2x – n = (4x + 2y + 3)⋅(4x – 2y – 1) – Restklassen der Teilerpaare mod 8 : (1, 5) 4x 2 + 6x – n = (4x + 2y + 5)⋅(4x – 2y +1) n+3 = y 2 + 2y 4 n −5 = y 2 + 2y 4 Genauere Aussagen darüber, wie man im Fall des Modul 2 k zu den einzelnen Gleichungen gelangt und wie man die Werte x und y bestimmt, sind im Anhang 1 aufgeführt. In der folgenden Ziffer soll nun untersucht werden, wie im Falle eines allgemeinen Modul die Lösungsmenge für x verringert werden kann. Es zeigt sich, dass dies in sehr effektiver Weise möglich ist. 2.2 Verringerung der potentiellen Lösungsmenge Für die (diophantische) Gleichung n = x2 – y2 werden ausschließlich ganzzahlige Lösungen gesucht. Sie kann daher ohne weiteres als Restklassengleichung zu einem beliebigen Modul m geschrieben werden: [n] = [x]2 – [y]2 (Wählt man m = n, ergibt das [0]n = [ x ]2n − [ y]2n , was gleichbedeutend mit der sog. Legendre-Kongruenz x2 ≡ y2 mod n ist. Diese ist die Basis nahezu aller heutigen leistungsfähigen Faktorisierungs-Verfahren.) Im weiteren werden alle Restklassen durch ihre kleinsten nicht-negativen Vertreter angegeben. Anstelle n als Quadrate-Differenz darzustellen, lautet die Aufgabe jetzt, zunächst alle ’Quadrat-Reste’ r (man könnte auch sagen ’quadratische Reste’, für die aber wird ggT(r,m) = 1 gefordert) ausfindig zu machen, deren Differenz eine prime Restklasse zum (frei gewählten) Modul m ergibt. Besonders geeignet sind dabei natürlich Moduln, für die sich diese Aufgabe mit möglichst wenigen Restklassen erfüllen lässt, denn nur die Werte von x, die in die betr. Restklassen fallen, kommen für eine Lösung infrage. Beispiel : m = 6 Restklassen: [0], [1], [2], [3], [4], [5] Prime Restklassen: [1], [5] Ermittlung der Quadrat-Reste: a: 0, 1, 2, 3, 4, 5 a2: 0, 1, 4, 9, 16, 25 r = a2 mod 6: 0, 1, 4, 3, 4, 1 Die möglichen Quadrat-Reste sind also 0, 1, 3, 4. Mit diesen lassen sich für die beiden primen Restklassen nur die folgenden Gleichungen [n] = [x]2 – [y]2 aufstellen: [1] = [1] – [0] [5] = [0] – [1] [1] = [4] – [3] [5] = [3] – [4] Ersetzt man die Quadrat-Reste durch die zugrundeliegenden x- bzw. y-Werte/Restklassen, erhält man alle in diesem Fall möglichen Restklassengleichungen: [1] = [1]2 – [0]2 [5] = [3]2 – [2]2 2 2 [1] = [5] – [0] [5] = [3]2 – [4]2 [1] = [2]2 – [3]2 [1] = [4]2 – [3]2 [5] = [0]2 – [1]2 [5] = [0]2 – [5]2 8 Dass für Zahlen n ≡ 1 mod 6 das gesuchte x insgesamt 4 der 6 Restklassen belegen kann ([1], [2], [4], [5]), lässt diese Vorgehensweise als nicht sehr effektiv erscheinen; bei n ≡ 5 mod 6 sieht es mit nur zwei ’zulässigen’ Restklassen schon besser aus. Eine Halbierung erzielt man durch Verwendung der eingangs gezeigten Tatsache, dass x bei Zahlen n ≡ 3 mod 4 stets gerade sein muss und im Fall n ≡ 1 mod 4 ungerade. Bei Verwendung eines geraden Modul gilt das auch allgemein für die Restklassen von x. Das abschließende Ergebnis für den Modul 6 lautet somit in Tabellenform: n mod 6 1 5 x mod 6 n ≡ 1 mod 4 n ≡ 3 mod 4 1, 5 3 2, 4 0 Bei der praktischen Anwendung wird natürlich nicht jedes x darauf überprüft, ob es in einer Restklasse liegt, die für eine Lösung infrage kommt, sondern zu jeder primen Restklasse von n wird als Startwert für den Zyklus die kleinste Restklasse gespeichert und ausgehend von dieser die Schrittfolge (Zyklus) festgelegt, bei deren Addition man immer auf einer zulässigen Restklasse „landet“. Das sieht dann so aus: n mod 6 1 5 x mod 6 n ≡ 1 mod 4 n ≡ 3 mod 4 Startwert Schrittfolge Startwert Schrittfolge 1 3 4, 2 6 2 0 2, 4 6 Für m = 2⋅3⋅5 = 30 erhält man folgende Tabelle: n mod 30 1 7 11 13 17 19 23 29 n ≡ 1 mod 4 x mod 30 1, 5, 11, 19, 25, 29 1, 11, 19, 29 9, 15, 21 7, 13, 17, 23 9, 21 5, 7, 13, 17, 23, 25 3, 7 3, 15, 27 n ≡ 3 mod 4 4, 10, 14, 16, 20, 26 4, 14, 16, 26 0, 6, 24 2, 8, 22, 28 6, 24 2, 8, 10, 20, 22, 28 12, 18 0, 12, 18 9 2.3 Bestimmung optimaler Moduln (m und n sind teilerfremd) Aus den beiden Beispielen (m = 6 und m = 30) ist ersichtlich, dass die Anzahl der xRestklassen (im Weiteren mit Ax bezeichnet) von der primen Restklasse n mod m abhängt. In Anlage 1 ist dargelegt, dass - Ax für Moduln m = p k (p > 2) nur zwei Werte annimmt (ϕ (m) / 2 – Ck (p) bzw. ϕ (m) /2), je nach dem n mod p ein quadratischer Rest (QR) oder QNR ist. - Ax für Moduln 2 e im wesentlichen davon abhängt, in welcher Restklasse zum Modul 8 n liegt. - Ax sich für zusammengesetztes m sich durch Multiplikation aus den Ax-Werten der Faktoren (Primzahlpotenzen) ergibt. Mittels der Berechnung von Ax (ohne die x-Restklassen im Einzeln bestimmen zu müssen), bietet sich eine einfache Möglichkeit, die Beschleunigung des Fermat-Verfahrens zu beurteilen: Beim Basis-Alg. ist der mittlere Abstand der x-Werte gleich 1, da ab Wurzel n jeder x-Wert überprüft wird, während der mittlere Abstand nun – durch Ausnutzen der Tatsache, dass nicht jedes x die Kongruenz x 2 – n ≡ y 2 mod m zu lösen vermag – gleich m / Ax ist. Gemäß Anlage 1 ist für m = p k (p > 2) Ax ≤ 1 + ϕ (m) / 2, so dass der mittlere Abstand mit jeden zusätzlichen Primteiler etwa um den Faktor 2 zunimmt; d.h. im Prinzip kann der mittlere Abstand beliebig groß gemacht werden. Allerdings nimmt Ax mit jedem Primteiler ungefähr um den Faktor p / 2 zu, was den Aufwand zur Berechnung der x-Restklassen stark anwachsen lässt und dadurch der Vorteil der Abstands-Erhöhung überkompensiert werden kann. Jedenfalls ist klar, dass m möglichst kleine Primfaktoren enthalten sollte. Zur Festlegung der Exponenten der einzelnen Primfaktoren ist einerseits entscheidend, dass wie erwähnt der Exponent k keinen Einfluss auf m / Ax hat, wenn n ein QNR zum Modul p (p > 2) ist und –falls n ein QR ist – der Quotient m / (ϕ (m) / 2 – Ck) zügig gegen einen Grenzwert Sg (p) konvergiert. (Z.B.: p = 2 → Sg = 24; p = 3 → Sg = 12; p = 5 → Sg = 4,3..; p = 7 → Sg = 3.29..; usw.) Die beiden folgenden Tabellen fassen die vorstehenden Aussagen zusammen: m = 2e e-opt. S∅ n ≡ 1(8) 11 22,6 n ≡ 5(8) 5 8 m = pk QR p: k-opt. S∅ k-opt. S∅ 3 5 5 2 11,04 3,57 1 1 3 2,5 QNR n ≡ 3(4) 3 4 ← mittlerer Abstand = m / Ax 7 2 3,06 1 2,3 11 2 2,63 1 2,2 13 17 1 1 1,85 1,88 1 1 2,16 2,11 19 1 1,91 1 2,1 = 2p / (p – 1) Beispiel: Aus Gründen des zur Verfügung stehenden Arbeitsspeichers sei m < 10 8. - n sei QR nach 2, 3 und 5. Die Dimensionierung gemäß Tabelle ergibt: m = 2 11⋅3 5 ⋅5 2 ⋅7 = 87.091.200 → S∅ = 2.041 → Ax= 42.670. Ersetzt man 3 5 durch 3 4 → m = 29.030.400 → S∅ = 1.878 → Ax= 15.458. Die Verringerung von Ax ist beträchtlich, während die Verringerung des mittleren Abstands evtl. weniger ins Gewicht fällt. - n sei kongruent 3 mod 4 und QNR nach 3 bis 19: m = 2 3 ⋅3⋅5⋅7⋅11⋅13⋅17⋅19 = 38.798.760 → S∅ = 4⋅3⋅2,5 ⋅....⋅ 2,1 = 1.452 → Ax= 26.721. 10 Es stellt sich nun die Frage, wie die bisherigen Überlegungen in einen möglichst effizienten Algorithmus umgesetzt werden können. Entscheidend ist dabei, dass die jeweils infrage kommenden x-Restklassen mit wenig Aufwand gefunden werden. Die folgende Lösung (,die nur für Zahlen kleiner 10 18 anwendbar ist,) macht von dem heute im PC allgemein eher reichlich bemessenen Arbeitsspeicher umfänglich Gebrauch: n=73445017 * 270985441 Teil 1: Optimaler Modul m FOR i=1 TO 20: a(i)=q(i): NEXT i q (i) = pi ( vorberechnete Primzahl-Folge) IF n MOD 4=3 THEN a(1)=2^3 Festlegung des optimalen m (Ist n < 10 18 IF n MOD 8=5 THEN a(1)=2^5 sollten die Exponenten der Primfaktoren um 1 IF n MOD 8=1 THEN a(1)=2^10 reduziert werden (im Vergleich zu den ‘optimalen’)). IF n MOD 3=1 THEN a(2)=3^4 g=n MOD 5: IF g=1 OR g=4 THEN a(3)=5^2 n ist QR mod p g=n MOD 7: IF g=1 OR g=4 OR g=2 THEN a(4)=7^1 g=n MOD 11: IF g=1 OR g=4 OR g=9 OR g=3 OR g=5 THEN a(5)=11^1 m=1: FOR i=1 TO 12: m=m*a(i): IF m*a(i+1)>5*10^8 THEN i0=i: EXIT FOR NEXT i: FOR i=1 TO i0:PRINT a(i): NEXT: PRINT , “ m = “;m ‘-------------------------------------------------------------- Teil 2: FOR i=0 TO m-1: r =(i^2)MOD m: u(r)=1:NEXT i Speichern aller QR (= y 2) als Adresse in u ( ) s=n MOD m: k=0 FOR x=0 TO m-1 Speichern aller möglichen Lösungen x von r=(x^2)MOD m-s: IF r<0 THEN r=r+m x 2 – n ≡ y 2 mod m als Adresse in p ( ) IF u(r)=1 THEN k=k+1: p(x)=1 NEXT x: ax=k ax = Ax FOR i=0 TO m-1: IF p(i)=1 THEN EXIT FOR d (- 1): Startwert der NEXT i: d(-1)=i: a=i: k=-1 Differenzen-Folge (Fixpunkt) FOR i=a+1 TO m-1:IF p(i)=1 THEN k=k+1:d(k)=i-a: a=i Berechnen der Differenzenfolge aus NEXT i: d(k+1)=2*d(-1) den x-Werten und Speichern in d ( ) '-------------------------------------------------------------Teil 3: u0=INT(SQR(n)): ru=u0 MOD m: i=0: uw=d(-1) Da die Lösungssuche im Fermat-Verfahren FOR i=0 TO ax: uw=uw+d(i) bei Wurzel n beginnt, ist zunächst der IF uw+d(i+1)=>ru THEN EXIT FOR passende Startwert modulo m in der Diff.NEXT i: u=u0-ru+uw: w=0: v=1: k=0 Folge zu suchen (u = u0 – u0 mod m + uw). ‚-------------------------------------------------------------DO WHILE v<>w^2 Hauptteil k=k+1: i=i+1: IF i=ax THEN i=0 ‘Zyklenschalter’ für die Differenzenfolge u=u+d(i): v=u^2-n: w=INT(SQR(v)) Anstelle u = u + 1 nun u = u + d (i) LOOP PRINT n, u+w; u-w, (u+w)*(u-w) Ergebnis (Teilerpaar von n) PRINT ax, m/ax, k Ax, mittl. Abstand, Anzahl Schritte bis zur Lösung Für die angenommene Beispiel-Zahl erhält man: m = 107.627.520, Ax = 55.296, S∅ = 1.946 Die Do while..Loop-Schleife wird 828.272-mal durchlaufen; im Basis-Alg. wären rd. 1,6 ⋅10 9 Durchläufe erforderlich. Fazit: Durch Vergrößerung des Moduls m (Erhöhung der Anzahl der Primfaktoren) lässt sich der mittlere Abstand prinzipiell beliebig vergrößern. Da die potentielle Lösungsmenge für Primfaktoren p > 20 in etwa proportional zu p ist, während sich der Abstand nur etwa verdoppelt, erhöht sich der Aufwand zur Berechnung der Ax x-Restklassen letztlich so stark, dass der Zeitaufwand der Vorausberechnungen die Ersparnis bei der finalen Quadratsuche übersteigt. Eine Implementierung gemäß dem obigen Basic-Code (schnell, aber mindestens 4 GB Arbeitsspeicher erforderlich; Begrenzung des Modul auf 5⋅10 8 ) liefert mittl. Abstände von 11 bis zu 3000 (bei Ax-Werten < 10 5) , was insgesamt eine Erweiterung des Einsatzbereiches des Fermat-Verfahrens um den Faktor 10 7 (bei gleichem Zeitaufwand) ermöglicht ! Anmerkungen: • Ein Grund dafür, dass man in den einschlägigen Darstellungen kaum Hinweise auf oben beschriebene Optimierungs-Möglichkeit findet, dürfte sein, dass weitere Verbesserungen sehr naheliegend sind; aber das firmiert dann nicht mehr unter „Fermat-Verfahren“. • Der obige Algorithmus bezieht sich auf die Zerlegung n = x2 – y2. Das Verfahren lässt sich (mit einem leicht modifizierten Algorithmus) aber auch auf die für Zahlen n ≡ 3 mod 4 mögliche und um den Faktor zwei schnellere Zerlegung v2 – (n + 1)/4 = w2 + w anwenden. Unterscheidet man dann danach, ob (n + 1)/4 gerade oder ungerade ist, entstehen genau die gleichen Schrittfolgen-Zyklen, wie bei der Zerlegung n = x2 – y2 und Auftrennung in die beiden ungeraden Restklassen mod 4; allerdings ist die Zuordnung zu den jeweiligen primen Restklassen eine andere. (Für Zahlen n ≡ 1 mod 4 funktioniert die letztere Aufteilung nicht.) • Der Algorithmus kann unverändert auf gerade Zahlen (n ≡ 0 mod 4) angewandt werden (wobei der Modul dann natürlich ungerade sein muss). • Zu Vervollständigung noch ein weitere, manchmal beschriebene Variante: Ist n ungerade, sind es auch Teiler und Komplementärteiler jeden Teilerpaares: n = t1⋅t2 = (2ks + 1)(2ls + 1). Daraus: n + 1 = 4kls2 + t1 + t2 und schließlich t1 + t 2 n+ 1 2 2 ≡ 2 mod ( 2s ) . Andererseits ist immer noch t +t n = t1⋅t2 = ( 1 2 2 ) 2 − ( t1 −2 t 2 ) 2 = x2 – y2 . Folglich kommen für x nur die Werte infrage, die in der gleichen Restklasse ( mod 2s2) liegen, wie (n+1)/2. Liegen (wie das meistens der Fall ist) keine Informationen über die Struktur der Teiler vor, bleibt nur s = 1; d.h. x liegt in der Folge der geraden bzw. ungeraden Zahlen. Aber bei den Mersenne-Zahlen ist x ≡ 22p–1 mod (2p2) und p bei den Fermat-Zahlen ist x ≡ ( 2 2 −1 + 1) mod (22p+1) . • In jedem Zyklus des Fermat-Verfahrens ist zu prüfen, ob eine Zahl m = u2 – n eine Quadratzahl ist, was einen Großteil der gesamten Rechenzeit beansprucht. Auch die Anzahl dieser Prüfungen lässt sich aufgrund von Restklassen-Restriktionen wesentlich einschränken: Sei q ein Quadrat und r die Restklasse von q zu einem Modul h. Dann ist [s] = [r]2 die Restklasse von q. s ist also Quadrat-Rest und die Quadrat-Reste stellen für h > 2 immer nur eine Teilmenge der Restklassen {0,1,.......,h–1} dar. Kleinstes Beispiel: h = 3 [r] [r]2 0 0 1 1 Folglich ist eine Zahl n ≡ 2 mod 3 kein Quadrat. 2 1 Bei einem im Sinne der hier gestellten Aufgabe zweckmäßigen Modul sollte der Quotient h / k groß sein, wobei k die Anzahl der Quadrat-Reste bezeichnet. Je größer nämlich dieser Quotient ist, mit desto größerer Wahrscheinlichkeit werden Nicht12 Quadrate „herausgefiltert“. Beim Modul 10.080 ist h / k = 30; d.h. knapp 97% aller Nicht-Quadrate werden als solche erkannt! Diese Quote lässt sich mit wesentlich größeren Moduln natürlich noch übertreffen, aber die Rechenzeit beeinflusst das kaum noch. Die Umsetzung dieses „Quadrat-Filters“ in einen Algorithmus kann folgendermaßen aussehen: Mat a() = Zer: h = 10080 For i = 0 to h –1: q = i^2 mod h: a(q) = 1: Next i ((Abspeichern der QuadratEingabe: n Reste im Vektor a(). )) u0 = isqrt(n): m = u0^2 – n For u = u0 + 1 to n m=m+u+u+1 s = m mod h: If a(s) <>1 then Iterate (***) w = isqrt (m): If w^2 = m then Exit For Next u Ausgabe: Teilerpaar (u – w); (u + w) Durch Einfügen der mit (***) gekennzeichneten Programm-Zeile wird eine Verkürzung der Rechenzeit um etwa 30% erzielt (, wobei die Verkürzung mit der Größe von n leicht zunimmt). 13 3. Beaufschlagung der zu zerlegenden Zahl mit Faktoren 3.1 Beschreibung der Wirkungsweise Wie in Abschnitt 1. gezeigt, arbeitet das Fermat-Verfahren am besten, wenn Teiler und Komplementärteiler einer Zahl nahe bei n liegen, also das Teilerverhältnis v (= t2/t1 mit t2 > t1) nicht viel größer als 1 ist. Im weiteren werden nun Möglichkeiten untersucht, die vorgelegte Zahl n mittels Faktoren f derart zu „manipulieren“, dass das Teilerverhältnis v´ eines Teilerpaares von f⋅n kleiner als v ist. Findet man ein Teilerpaar von f⋅n, so können die (gesuchten) Teiler von n leicht per ggT-Berechnung bestimmt werden. Zunächst soll die Auswirkung eines Vorfaktors anhand der folgenden Grafik veranschaulicht werden. 20000 i (Schrittzahl) 16000 n = pi⋅pj ≈ 108 (pi, pj prim) v = pi / pj (pi > pj) 12000 19,46 f=1 8000 5,0 5,94 f = 16 4000 2,0 7,7 f = 15 15 4,0 0 11 1,66 6 11 16 21 v Bild 1: Auswirkung auf die zum Auffinden eines Teilers von n erforderliche Schrittzahl i in Abhängigkeit vom Teilerverhältnis v am Beispiel der Vorfaktoren 15 und 16 im Vergleich zum Basisalgorithmus (f = 1). (Es wurden nur Zahlen pi ⋅pj zerlegt, deren Produkt möglichst nahe bei 108 liegt, um die Auswirkung von n auf die Schrittzahl (s. 1. ∗∗) zu neutralisieren.) Dem Bild entnimmt man, dass der Vorfaktor 15 ab v = 5,94 eine erhebliche und nachhaltigere Verringerung der Schrittzahl, die zum Auffinden eines Teilers von n benötigt wird, bewirkt, während dies bei f = 16 nur (und in wesentlich kleinerem Ausmaß) im Bereich 2,51 < v < 19,46 der Fall ist. 14 Da das Teilerverhältnis bei einer vorgelegten Zahl nicht bekannt ist, sondern gerade die gesuchte Größe ist, sind Vorfaktoren nur sinnvoll anzuwenden (sie können ja auch eine Vergrößerung der Schrittzahl zur Folge haben), wenn klar ist, wie die im Bild beispielhaft dargestellten Kurven zustande kommen. Sei f eine Zahl mit r Teilerpaaren f = hk⋅tk , für die t k ≡ h k mod 2 gilt. Mit der Festlegung h h k ≥ t k und 1 < h k < h k + 1 ≤ f ist dann 1 ≤ ..< ht kk < t kk ++11 < ...≤ f. (Den Wert 1 kann der Quotient nur annehmen, wenn f eine Quadratzahl ist; den Wert f – wegen t k ≡ h k mod 2 – nur, wenn f ungerade ist.) Im weiteren werden die Quotienten hk / tk mit vk bezeichnet. Beispiele: f = 15 → v1 = 5 / 3; v2 = 15 / 1 f = 16 → v1 = 4 / 4; v2 = 8 / 2 f = 3⋅5⋅7 → v1 = 15 / 7; v2 = 21 / 5; v3 = 35 / 3; v4 = 105 / 1 Gemäß Ziffer 1. (Seite 2) besteht beim Basisalgorithmus zwischen der Schrittzahl i und dem ( v − 1) Teilerverhältnis v der formelmäßige Zusammenhang i = bzw. ( bei 2 ⋅ v ⋅ n +1 Vernachlässigung der 1 sowie der Rundung) i = ( v 1 + 1 v 2 − 2)⋅ n 2 . Diese Formel gilt natürlich auch, wenn n durch f⋅n ersetzt wird. Bezogen auf die Teiler von n ist das gleichbedeutend mit i = ( v vk + vk v − 2)⋅ f⋅ n 2 (3.∗) wobei vk der Reihe nach die Werte von v1 bis vr durchläuft. Dabei erfolgt der Übergang von vk auf vk + 1 genau dann, wenn für einen eindeutig bestimmten Wert von v (= vs) gilt: i (vs, vk) = i (vs, vk + 1). Mit (3.∗) kann der Verlauf von i(v) leicht beschrieben werden: Für v = vk ist der Klammerausdruck gleich Null, d.h. i(v) besitzt r Minima mit i(v = vk) = 0. Der Schnittpunkt der beiden Kurven i(v, vk) und i(v, vk + 1) liegt bei v = vs, k = v k ⋅ v k +1 . Dieser Punkt ist jeweils ein rel. Maximum im Verlauf i(v). Beispiele: f = 15: vs, 1 = (5 / 3) ⋅ (15 / 1) = 5 Siehe Bild 1 f = 16: vs, 1 = ( 4 / 4) ⋅ (8 / 2) = 2 f = 105: vs, 1 = (15 / 7) ⋅ ( 21 / 5) = 3, vs, 2 = 7, vs, 3 = 35 Etwas schwieriger und auch rechenintensiver ist die Bestimmung der Schnittpunkte von Verläufen zweier unterschiedlicher Vorfaktoren (f1 und f2). Die Gleichsetzung der beiden für f1 bzw. f2 gültigen Terme (3.∗) führt auf eine quadratische Gleichung mit den beiden Lösungen va,b = ( − e ± e 2 − 4⋅u⋅w 2 ) . (3.∗∗) Darin sind 2⋅u e = 2 v k ⋅ v m ( f1 − f 2 ) u= v k ⋅ f 2 − v m ⋅ f1 w=– v k ⋅ v m ( v k ⋅ f1 − v m ⋅ f 2 ) Der Quotient des m-ten Teilerpaares von f2 ist zur Unterscheidung mit vm bezeichnet, während vk (wie oben eingeführt) der Quotient des k-ten Teilerpaare von f1 ist. 15 Die so ermittelten Lösungen geben nur dann die gesuchten Ordinaten der Schnittpunkte wieder, wenn zwischen v = vm und v = vk keine weiteren „Nullstellen“ der betrachteten Vorfaktoren liegen. Im Beispiel f = 15 und f = 16 aus Bild 1 gibt es für die ’v-Paare’ (15/1, 8/2), (5/3, 8/2) sowie (5/3, 4/4) jeweils nur einen Schnittpunkt (v = 7,7..; 2,59..und 1,285..), der zwangsläufig zwischen den betreffenden zwei Nullstellen liegt. (In den drei Fällen ist die zweite Lösung von (3.∗∗) kleiner Eins und somit nicht von Interesse.) Zu beachten ist noch der Sonderfall v k = o 1 / e und v m = o 2 / e – wenn also die beiden Nenner gleich sind (z.B. f1 = 4 →vk = 2 / 2 und f2 = 16 → vm = 8 / 2 ). Dann existiert nur ein Schnittpunkt, und der besitzt die Ordinate vs = ( o 2 − o1 2 ⋅( f 2 − f 1 ) ). 2 Nach soviel „Kurvendiskussion“ soll nun die Nutzung von Vorfaktoren in konkreten Algorithmen geprüft werden. 3.2 Beaufschlagung von n mit einem festen Vorfaktor Nimmt man an, dass bei einem vorgegebenen n = t1⋅t2 das Teilerverhältnis v = t1/t2 für alle möglichen Werte von v unterhalb einer bestimmten Grenze vo gleich wahrscheinlich ist (d.h. v ist statistisch gleichverteilt), kann man den Vorteil (Nachteil), der sich im Mittel bei Anwendung eines bestimmten Vorfaktors einstellt, leicht berechnen indem die Fläche unterhalb der Kurve i = f(v)|v = v1 zu der entsprechenden Fläche für i = f(v)|v = v2 ins Verhältnis gesetzt wird. Weil es nicht auf die absoluten Flächengrößen ankommt, sondern nur auf deren Verhältnis, kann man immer auf i / n normieren, d.h. die Ergebnisse sind von n unabhängig. 1 −1 Besonders einfach ist die Berechnung im Fall f = 1: Wegen in = 12 ( v 2 + v 2 − 2 ) gilt v0 Ff = 1 = 1 2 − ∫ ( v + v − 2 ) dv = 13 ⋅ ( v o − 1) + ( v o − 1) − ( v o − 1) . 1 1 2 3 2 1 2 2 1 Besitzt f mehrere (k) Teilerpaare mit den nach aufsteigender Größe geordneten Teilerverhältnissen vi , sind als erstes daraus – wie oben gezeigt – alle Schnittpunkte vs,i < vo zu berechnen. Die zwischen den Schnittpunkten vs, i – 1 und vs, i liegenden Kurvenzüge können jeweils analog zum Fall f = 1 integriert werden. Die gesuchte Gesamtfläche Ff ist dann die Summe der m Einzelflächen: m Ff = ∑ Ff , i = ∑ i =1 vs , i m i =1 f 2 ∫ ( v s , i −1 v vi + vi v − 2) dv Es ist vs, 0 = 1 und vs, m = vo zu nehmen. Die i-te 3 3 1 1 Einzelfläche ergibt sich zu Ff, i = f ⋅ 3⋅ 1v ( v s,2i − v s ,2i −1 ) + v i ( v s ,2i − v s,2i −1 ) − ( v s , i − v s , i −1 ) i In der nachstehenden (auch experimentell verifizierten) Tabelle sind für einige vo und Vorfaktoren f die Quotienten der im Mittel erforderlichen Schrittzahlen if = 1/if =fo angegeben. (Der Eintrag 3,44 bedeutet also, dass die erforderliche Schrittzahl bei Verwendung des Vorfaktor f sich im Vergleich zum Basisalgorithmus (f = 1) um den Faktor 3,44 verringert.) Die markierten Werte stellen die Optima einer Vielzahl getesteter Vorfaktoren dar. f \ vo: 5 10 100 1000 1.440 2.880 10.080 181.440 Tabelle 3.1 3,44 (5) 2,10 (5) 2,00 (8) 0,81 (13) 4,41 6,25 3,95 2,39 14,41 18,12 23,74 10,60 16 6,13 (In Klammern 14,22 gesetzte Zahlen: 14,27 Siehe Text unten) 32,69 Die Aussagen der Tabelle sind insofern zu relativieren, als die Annahme, die v-Werte seien unterhalb der Grenze vo gleichverteilt, bekanntlich nicht zutrifft. Z.B. besitzen rd. ein Drittel aller ungeraden 7-stelligen Zahlen (ohne Primzahlen und Quadratzahlen) mindestens ein Teilerpaar (t1, t2) mit t2 / t1 < 5, d.h. die restlichen zwei Drittel verteilen sich auf den Bereich 5 bis 107 / 3. Bei rd. 11 % der genannten Zahlen ist sogar t2 / t1 < 1,5 (jeweils t2 > t1). Daraus ist zu folgern, dass nur die drei erstgenannten Vorfaktoren in Frage kommen; diese aber „im Mittel“ einen erheblichen Vorteil bringen. Die wesentliche Aussage der Tabelle ist aber, dass – wie auch immer vo gewählt wird – es für den Vorfaktor einen optimalen Wert gibt, und eine weitere Vergrößerung die erforderliche Schrittzahl erhöht, auch wenn der betr. Faktor u.U. sehr viele „Nullstellen“ im Bereich 1 bis vo aufzuweisen hat (siehe Zahlen in Klammern unter vo = 5). Ein weiterer Aspekt, unter dem ein Vorfaktor bewertet werden kann (und der auch weiter unten Anwendung findet), ist seine „effektive Schrittlänge“ (des ersten Schritts). Dazu ist (3.∗) nach v aufzulösen: v= ( v k 1+ i f ⋅n ± (1 + i f ⋅n ) ) 2 −1 . (3.∗∗∗) n + i ⋅( 1 ± 1 + 2⋅ f ⋅ n ) umformen. Für (rel.) kleine Werte i f von i ist die 1 unter dem Wurzelzeichen vernachlässigbar, was zu der leichter interpretierbaren Darstellung v 2⋅ v v = 1n v k n + i⋅ fk ± i⋅ 4 f k ⋅ 4 n führt. Bei Verwendung eines Vorfaktors werden die Umgebungen aller „Nullstellen“ v = v k im ersten Schritt simultan darauf getestet, ob sich eine Quadratdarstellung und somit ein Teiler von n findet. Die beiden Grenzwerte für das Teilerverhältnis der k-ten „Nullstelle, bei der ein Teiler im 1. Schritt gefunden wird, sind diejenigen Werte, für die der in den Das lässt sich zu v= vk n Rundungsklammern stehenden Term der Beziehung i = ( gleich 1 ist. In der obigen Auflösung nach v⋅ n= t2 t1 v vk + vk v − 2) ⋅ f⋅ n 2 + 1 gerade v ist also i = 1 einzusetzen und wegen ⋅ t 1 ⋅t 2 = t2 erhält man schließlich das Intervall, in dem der Teiler t2 im ersten Schritt gefunden wird: ∆ t2 = 2⋅ 2 ⋅ v k 4f ⋅ 4 n (= d ⋅ 4 n ). Somit hat man in dem vor der 4-ten Wurzel n stehenden Faktor d einen Bewertungsmaßstab für verschiedene Vorfaktoren, wobei für einen vorgegebenen Vorfaktor f und ein vorgegebenes vo die Summe über die vk zu bilden ist, die kleiner als vo sind. Ist vk =1, was nur bei Vorfaktoren vorkommt, die Quadratzahlen sind, ist die Besonderheit zu beachten, dass in dem Ausdruck für d anstelle der 2 eine 1 zu setzen ist, da v hier immer größer 1 definiert ist (t2 > t1; z.B. f =1: d = 1⋅ 2 ). In der nachstehenden Tabelle sind die effektiven Längen des ersten Schritts (Vielfache von 4 n ) für einige Vorfaktoren aufgelistet. 17 f \ vo: 5 1 3 4 16 1440 2880 10080 20160 60480 1,41 3,72 1,0 3,53 3,63 3,72 3,37 3,58 3,32 Summe di für v < vo 10 100 6,15 5,91 5,54 5,45 5,77 17,35 17,05 17,83 18,48 18,15 1000 alle 26,06 32,59 36,00 36,90 44,29 50,18 62,17 84,95 Tabelle 3.2: Effektive Länge des ersten Schrittes bezogen auf 4 n für ausgewählte Vorfaktoren. Die insgesamt gefundenen Maximalwerte sind markiert. Ein Vergleich mit Tabelle 3.1 zeigt, dass die Lage der Optima recht gut übereinstimmt. 3.3 Der serielle Einsatz von Vorfaktoren Naheliegend ist der Gedanke, der Reihe nach Vorfaktoren mit den „Nullstellen“ 1, 2, 3, 4, 5,.... anzuwenden, indem jeweils die Schnittpunkte (vf, if) für aufeinander folgende Vorfaktoren berechnet werden und sodann der Basisalgorithmus mit if Schritten für die Zahl f⋅n ausgeführt wird. Für große n ergeben sich mit diesem Verfahren allerdings leicht zu große Werte von if . Um hier mehr Flexibilität zu erhalten, kann man wie folgt vorgehen: Vorab wird die max. Schrittzahl imax , mit der ein Vorfaktor höchstens eingesetzt wird, sowie das max. Teilerverhältnis vmax , für das ein Teilerpaar von n gesucht wird (z.B. vmax = 3), festgelegt. (Die Begrenzung auf vmax ist kein Nachteil, da die sukzessiv eingesetzten Vorfaktoren auch (in der Regel zahlreiche) „Nullstellen“ besitzen, die größer als vmax sind und die Umgebung dieser Nullstellen jeweils simultan auf Teiler getestet wird. Wird dennoch ein Teilerpaar mit v > vmax nicht gefunden, kann das Verfahren anschließend für die Zahl n⋅vmax wiederholt werden.) Als erstes werden die ‚Ränder’ des v–Bereichs mit f = 1 bzw. f = vmax bearbeitet. Durch Einsetzen von imax in (3.∗∗∗) und quadrieren erhält man u. a. die beiden Werte v1,o und vmax,u; diese werden abgespeichert. Der zwischen diesen beiden Eckpunkten liegende Bereich wird nun mittels weiterer Vorfaktoren fx solange mit Intervallen [vx,u – vx,o] aufgefüllt, bis der gesamte Bereich belegt ist. Dabei wird die Folge der Vorfaktoren f = c⋅s (v = c / s) wie folgt gebildet: Der Nenner s durchläuft – beginnend mit s = 2 – die Folge der (ersten) natürlichen Zahlen. Zu jedem Wert von s durchläuft der Zähler c (mit Schrittweite 2) alle Werte von c = s + 2 bis c = vmax⋅s – 2. 18 Die ersten f-Werte z.B. für vmax = 3 sind demnach: s 2 3 4 5 6 7 f = c⋅s 4⋅2 5⋅3 7⋅3 8⋅4 6⋅4 7⋅5 9⋅5 8⋅6 10⋅6 ...... ...... 10⋅4 11⋅5 12⋅6 13⋅5 14⋅6 16⋅6 Treten dabei die Fälle ggT(c, s) > 2 (in der Tabelle rot) oder c ≡ 2 mod 4 und zugleich s ≡ 2 mod 4 (in der Tabelle blau) auf, wird der betr. Vorfaktor f = c⋅s übergangen (, da die gekürzten Brüche zuvor bereits zur Anwendung kamen). Insgesamt stellt dieses Vorgehen sicher, dass betragsmäßig kleine Vorfaktoren bevorzugt zur Anwendung kommen. Für jeden ‚brauchbaren’ Vorfaktor fx werden mit i = imax die beiden Grenzen vx, o und vx, u berechnet. Dabei sind – um Überschneidungen und damit Doppelarbeit zu vermeiden – folgende Fälle zu beachten: 1. Die „Nullstelle“ c / s des aktuellen Vorfaktors fx fällt in einen Bereich, der bereits von einem der vorhergehenden Vorfaktoren ‚belegt’ ist → fx wird übergangen. 2. a) vx,o liegt in einem bereits durch irgendeinen Vorfaktor fy belegten Bereich (d.h. vx,o > vy,u; siehe Bild 2). Dann ist durch Einsetzen von vy,u in (3.∗∗) die (abzuspeichernde) Schrittzahl ix,o < imax und mit dieser wiederum das verkleinerte vx,u zu berechnen. (Damit schließt der von fx belegte Bereich exakt an den Bereich von fy an.) i belegt Lücke belegt imax fx x RestLücke fz vz, o fy ix, o vx, u vx, o = vy, u v Bild 2 b) vx,u liegt in einem bereits durch irgendeinen Vorfaktor fz belegten Bereich (d.h. vx,u < vz,o). → Analog zu a). c) vx,o und vx,u liegen beide in (von zwei verschiedenen Vorfaktoren) bereits belegten Bereichen (siehe Bild 3). Mit Hilfe von vz,o und vy,u werden ix,u und ix,o berechnet; der größere der beiden i-Werte (im Bild ix,u) ist abzuspeichern. Damit ist der v19 Bereich zwischen fz und fy belegt, (wobei eine geringfügige Überlappung (im Bild ist vx,o > vy,u) in Kauf genommen wird). i belegt Lücke belegt imax x ix,u fz fx fy ix,o vx,u = vz,o vy,u v Bild 3 Auf diesem Wege lassen sich die zur vollständigen Belegung des vorgegebenen v-Bereiches erforderlichen Vorfaktoren (unter Berücksichtigung der je Vorfaktor maximalen Schrittzahl) bestimmen. Zur schnellen und einfachen Umsetzung für die praktische Nutzung sind allerdings noch zwei Punkte zu berücksichtigen: – Die strikte Vorgabe von imax kann dazu führen, dass zwischen zwei belegten Bereichen eine sehr kleine Lücke bestehen bleibt und es schwierig ist, für diese einen geeigneten Vorfaktor zu finden. Das kann man vermeiden, indem jeweils geprüft wird, ob die verbleibende Lücke durch eine geringe Überschreitung von imax ( z.B. < 5% ) vollständig geschlossen werden kann. Falls ja, wird für den betr. Vorfaktor imax soweit wie erforderlich erhöht (Überführung von Fall 2.a) in 2.c)). – Wie gesagt, ist für jeden Vorfaktor fx zu überprüfen, inwieweit der Bereich [vx,u – vx,o] noch frei ist. Um langwierige Suchvorgänge zu vermeiden, ist es zweckmäßig die von den betreffenden Vorfaktoren belegten Bereiche ‚geordnet’ abzuspeichern. Eine leicht umzusetzende Möglichkeit besteht darin, die Werte vx,u und vx,o mit Faktor B (nat. Zahl) zu multiplizieren und B⋅vx,u sowie B⋅vx,o (nach Abrundung) in einem Vektor der Länge B⋅vmax abzulegen. Der gesamte Bereich zwischen Bvx,u und Bvx,o wird als ‚belegt’ markiert. Zur Überprüfung der quantitativen Wirksamkeit des beschriebenen Konzeptes wurde das im Anhang 2 beigefügte Programm benutzt. Es ergaben sich z.B. folgende Verminderungen der erforderlichen Schrittzahl im Vergleich zum Basis-Alg.(vmax = 3 und unter der Annahme, dass das Teilerverhältnis der Faktoren von n in der Nähe von vmax liegt): n ≈ 10 16 , imax = 200 → Schrittzahlverringerung um den Faktor 110 n ≈ 10 29 , imax = 10 7 → Schrittzahlverringerung um den Faktor 380 Da der Zeitaufwand zur Durchführung des Programms praktisch vernachlässigbar ist, ist die Laufzeitverringerung in der Größenordnung der Schrittzahlverringerung. Allerdings lohnt der Einsatz sich – wegen des kleinen vmax – sich erst für n > 1020. 20 Fazit: Kombiniert man den seriellen Einsatz von Vorfaktoren mit dem Verfahren zur Schrittlängenvergrößerung gemäß Ziffer 2. lassen sich große Teiler (vmax < 5) von Zahlen bis etwa 1030 bestimmen; eine Größenordnung, die üblicherweise nicht mit dem FermatVerfahren in Zusammenhang gebracht wird. 21 4. Das Lehman-Verfahren 4.1 Der Basis-Algorithmus Die konsequente Weiterführung der in Ziffer 3. diskutierten Verwendung von Vorfaktoren führt auf das nachstehende, von Lehman entwickelte Verfahren, dessen Zeitbedarf proportional zur dritten Wurzel von n ist. Eine vorgelegte Zahl n` wird zunächst per Probedivision darauf überprüft, ob ein (oder mehrere) Teiler t <= n`1/3 vorhanden sind; diese werden ggf. herausdividiert. Die verbleibende Zahl n ist somit entweder prim oder – da n keine drei Faktoren enthalten kann, die alle größer n1/3 sind – von der Form n = pi⋅pj (pi, pj prim; pi < pj) mit pi > n1/3 und pj < pi2. Unter Beachtung dieser Voraussetzungen sieht der (Standard-)Algorithmus des LehmanVerfahrens wie folgt aus: Eingabe: n (Der kleinste Primteiler von n muss größer n1/3 sein; s.o.) For f = 1 To n^(1/3) fn = 4*f*n: ug = Int(Sqr(fn)) + 1: og = ug + Int(n^(1/6)/(4*Sqr(f))) For u = ug To og m = u^2 – fn: w = Int(Sqr(m)) If m = w^2 then Exit, Exit Next u Next f Ausgabe: Teiler: t1 = ggT(u + w, n), t2 = n / t1 f durchläuft ggf. alle Zahlen von 1 bis 3 n . U.A. um auch die Werte von f verwenden zu können, für die f ≡ 2 mod 4 ist, wird n generell vorab mit 4 multipliziert. Zu den Einzelheiten, insbesondere zum Beweis, dass unter den genannten Voraussetzungen immer ein Teiler gefunden wird, sei auf diesbezügliche Darstellungen im Netz verwiesen . Nachteilig zu werten ist, dass die „Ordnung“ insofern verloren geht, als Teiler, die z.B. ganz in der Nähe von 2 n liegen, dennoch u. U. erst nach relativ vielen Schritten gefunden werden. Daher eignet es sich nicht zur gezielten Suche nach großen Teilern von Zahlen. 4.2 Optimierungen des Lehman-Verfahren Als erstes liegt eine Aufteilung des Algorithmus nahe, denn die ’u-Schleife’ wird nur solange benötigt, wie n1/6 / (4⋅ f ) > 1. Also ist die Berechnung der oberen Grenze der u-Schleife nur bis f = n1/3 /16 erforderlich. Des Weiteren: Wendet man den „Multiplikator“ 4 nur auf die geraden Werte von f an, resultiert daraus im Mittel eine Verkürzung der Rechenzeit um etwa 15 %; bei ungeradem f ist die Multiplikation mit 4 überflüssig und nachteilig. (Die Bezeichnung „Multiplikator“ wird benutzt zwecks Unterscheidung vom „Vorfaktor“ 4⋅f .) Es stellt sich außerdem die Frage, ob die 4 als Multiplikator optimal ist. Wie sich zeigt , ist die 16 deutlich effektiver. Im Mittel ergibt sich nahezu eine Halbierung der Rechenzeit, was man mit Hilfe des im Anhang 3 beigefügten Programms verifizieren kann. Das liegt zum einen daran, dass der Multiplikator 16 zusätzlich zu vk = 4 / 4 = 1 noch über die „Nullstelle“ vk = 8 / 2 = 4 verfügt (siehe Bild 3.1) und die Anzahl Durchläufe der inneren Schleife sich um rd. ¾ reduziert. 22 4.3 Der „Spitzendetektor“ Es scheint allerdings so zu sein, dass die Multiplikatoren 4 und 16 die einzigen sind, die für alle dem Lehman-Verfahren zugänglichen Zahlen die Forderung erfüllen, dass ein Teiler von n spätestens nach n1/3 Durchläufen der Hauptschleife gefunden wird. Bei allen weiteren untersuchten Multiplikatoren mit vielen Nullstellen liegt die erforderliche Rechenzeit im Mittel zwar deutlich unterhalb derjenigen des Standard-Alg., aber für einzelne Zahlen übersteigt die Anzahl der Hauptschleifen-Durchläufe den Wert von n1/3, so dass man wohl nicht mehr von einer Variante des Lehman-Verfahren sprechen kann. Der im Sinne einer Minimierung der Rechenzeit optimale Multiplikator scheint 10.080 zu sein. Infolge der erhöhten Wirksamkeit dieses Faktors kann die innere (zweite) Schleife beim Lehman-Verfahren ganz entfallen, so dass sich ein sehr einfacher Algorithmus ergibt: Algorithmus ’Spitzendetektor’ Eingabe: n (n ungerade, kein Quadrat, keine Primzahl) fn = 10080 * n: v = 0: m = 1: w = 0 (∗) Do While w^2 <> m v = v + fn: u = Int (Sqr(v)) + 1 m = u^2 – v: w = Int (Sqr(m)) Loop Ausgabe: Teiler sind t1 = ggT(u – w, n) und t2 = n / t1 (Für den o.a. Mersenne-Prüfling werden nur 35 Iterationen benötigt!) Im Ergebnis wird die Rechenzeit gegenüber der Standard-Variante im Mittel auf weniger als ein Drittel verkürzt. Zur Verifizierung dieser Aussage ist im Anhang 3 ein unter der im Netz frei verfügbaren Langzahlarithmetik „ari.bas“ lauffähiges Programm wiedergegeben, in dem jeweils ein Satz zufällig ausgewählter Zahlen mittels der drei hier behandelten Varianten („LEH“, „LEH16“ und „Spitzendetektor“) faktorisiert wird und die benötigten Zyklen und Rechenzeiten (jeweils Mittelwerte) verglichen werden. Anmerkungen: • Die Bezeichnung „Spitzendetektor“ wurde wegen einer naheliegenden ‚graphischen’ Interpretation des Verfahrens gewählt. Diese ist im Beitrag „Über quadratische Reste und quadratische Kongruenzen“ des Verfassers beschrieben. • Beschränkt man n nicht auf Zahlen, deren kleinster Teiler größer n1/3 ist, kann ggT( u – w, n) = 1 eintreten. In diesem Fall setzt man m = v und fährt mit (*) fort. Bei der Ermittlung kleiner Teiler ist der Algorithmus – ähnlich wie das Fermat-Verfahren – allerdings häufig uneffektiv. • Wegen des rel. großen Multiplikators ergeben sich ab etwa n > 1012 im Laufe der Berechnung leicht Zahlen, die die Größenordnung von 1018 überschreiten, so dass man eine Langzahl-Arithmetik (etwa ‚ari.bas’) verwenden muß. 23 4.4 Das Aussieben geeigneter Faktoren Die gezielte Suche nach großen Teilern ( n > t1 > n / 2 ) großer Zahlen ist mit den bisher beschriebenen drei Varianten nicht möglich, da bei diesen das Teilerverhältnis und die erf. Schrittzahl kaum miteinander korrelieren. Da gemäß obiger Definition das Teilerverhältnis v für ‚große Teiler’ zwischen 1 und 2 liegt, müsste die untersuchte Zahl – anstelle mit den Gliedern der Folge 1, 2, 3, 4,... – ausschließlich mit Zahlen multipliziert werden, die je über mindestens ein Teilerpaar (o, u) verfügen, mit 1 < o / u < 2. Folglich ist eine entsprechende Auswahl aus den zwischen 1 und 2 liegenden rationalen Zahlen zu treffen. Der unten stehende Algorithmus liefert alle verschiedenen rationalen Zahlen zwischen h –1 und h mit h = {2, 3, 4,...} in reduzierter Form, bei denen das Produkt von Zähler und Nenner unterhalb einer Grenze mmax bleibt. Diese Zahlen werden hier aus naheliegenden Gründen „geeignete Faktoren“ genannt. Algorithmus GeFak mmax = 1000 'Vorgabe h=2 'Vorgabe IF h MOD 2 = 0 THEN nr = h –1: b = h ELSE nr = h: b = h –1 nb = nr: na = 1: d = 1 FOR i = 1 TO mmax na = na + 1: nb = nb + b n1 = na: n2 = nb: f = n1 * n2 IF f > mmax THEN EXIT IF na MOD 2 = 0 THEN c = 1: r = nr: e = 4 ELSE c = 2: r = 2 * nr: e = 1 d = d + 1: e(d) = e * f FOR j = 1 TO mmax n1 = n1 + c: n2 = n2 + r: f = n1 * n2 IF f > mmax THEN EXIT ed = n2 – n1: ec = n1 DO UNTIL ed = 0: er = ec MOD ed: ec = ed: ed = er: LOOP gg = ec: IF gg < 2 THEN d = d + 1: e(d) = e * f NEXT j NEXT i e(1) = h –1: ko = d + 1: e(ko) = h IF e(1) MOD 2 = 0 THEN e(1) = 4 * e(1) IF e(ko)MOD 2 = 0 THEN e(ko) = 4 * e(ko) ARRAY SORT e() FOR ko, ASCEND Es wäre wohl nicht zielführend, dieses Programm im einzelnen zu erläutern. Am leichtesten dürfte der Zugang sein, wenn man die generierten Zahlen (die Produkte von Zähler und Nenner) über den dazugehörenden, nach ihrer Größe sortierten rationalen Zahlen (Quotienten von Zähler und Nenner) grafisch darstellt. Die ’Produkte’ liegen dann auf Parabeln, die ihrerseits wiederum ihren Ursprung in den ganzzahligen Werten einer Parabel haben. All diese Parabeln können als die Produkte je zweier Geraden aufgefasst werden; auf der einen liegen die Zähler auf der anderen die Nenner. Das bildet der obige Algorithmus nach: Die äußere (i) Schleife berechnet die jeweiligen Startpunkte für die Zähler- und Nenner-Geraden (j–Schleife). Haben Zähler und Nenner einen ggT größer als 1, wird die betr. Zahl nicht weiter verwendet. Fallen Zähler und Nenner nicht in die gleiche Restklasse (mod 2), wird das ’Produkt’ aus den bekannten Gründen mit 4 multipliziert. Sodann werden sie als „geeignete Faktoren“ in einem Vektor e() abgespeichert und abschließend dem Betrag nach aufsteigend sortiert. 24 Als erstes interessiert natürlich der Zusammenhang zwischen der oberen Grenze mmax und der Anzahl der unter den genannten Bedingungen möglichen rationalen Zahlen. Die Frage – etwas allgemeiner formuliert – lautet also: Wie viele unechte (wegen o / u > 1), voll gekürzte Brüche (o / u) gibt es im Intervall [1, k) mit o⋅u ≤ m max? Klarerweise entspricht die gesuchte Anzahl der Anzahl Ak echter, voll gekürzter Brüche im Intervall ( 1k , 1] mit o⋅u ≤ m (k ≤ m). Die Anzahl Qk aller (also einschließlich derer mit ggT(o, u) > 1) Brüche im Intervall mit o⋅u ≤ m ergibt sich (experimentell) zu Qk ≈ m⋅ln(k) / 2. Bekanntlich ist die Wahrscheinlichkeit, dass zwei zufällig gewählte nat. Zahlen teilerfremd sind, gleich ζ (12 ) = π62 = 0,6079271... Das trifft auch zu, wenn die beiden Zahlen aus einem vorgegebenen Intervall stammen. ln ( k ) 3 ⋅ ln ( k ) = m⋅ Für k = 2 folgt: a 2 = A 2 / m ≈ 0,2106914... Damit: A k ≈ m ⋅ 2 ⋅ ζ( 2) π2 Wie die nachstehende Tabelle verdeutlicht, liefert die Formel Werte, die sehr nahe an der tatsächlichen Anzahl geeigneter Faktoren „A 2-Ist“ liegen. m A 2-Ist 10 10 2 10 3 10 4 10 5 10 6 10 7 10 8 2 22 211 2112 21070 210695 2106905 21069138 m⋅ln(2)⋅3 / π 2 2 22 211 2108 21069 210692 2106915 21069148 Anm.: (ohne direkten Zusammenhang mit dem Thema) Es ist: m m 1 1 ∑ ϕ(i) / ∑ i ≈ 1 / ζ(2). Die Summe im Nenner ist gleich m (m + 1) / 2; die Summe im Zähler sei mit Sϕ (m) abgekürzt. Folglich hat man: Sϕ (m) ≈ 3⋅m⋅(m+1) / π 2 (= P). Ist m prim, gilt Sϕ (m) > P; ist ϕ (m) ≤ m / 4, ist Sϕ (m) < P. Der Wert von Sϕ (m) oszilliert also (mit immer kleiner werdender rel. Amplitude) um den Wert P. Erstaunlicherweise lässt sich die Summe der „unberechenbaren“ Eulerschen ϕ -Funktion so einfach und genau abschätzen. ------------------Fazit: Zur Zerlegung einer Zahl n = p i ⋅p j mit p i / p j < 2 mittels des Lehman-Verfahren gibt es rd. 0,21 ⋅n1/3 geeignete Faktoren f, die für Bildung des Vorfaktors 4⋅f infrage kommen. Diese können mit dem o.a. Alg. schnell (im Vergleich zur Gesamt-Rechenzeit) bestimmt werden. Die nähere Untersuchung zeigt, dass von den so gebildeten Vorfaktoren in der Praxis nur rd. die Hälfte benötigt wird. Diese wiederum aus den geeigneten Vorfaktoren auszusieben erübrigt sich, da die nicht benötigten im Wesentlichen zugleich auch die betragsmäßig größten sind (und die geeigneten Faktoren ja nach aufsteigendem Betrag sortiert wurden). Am Beispiel: n ≤ 106 => mmax = n1/3 = 100 => aq = 22. Tatsächlich benötigt werden nur 13 Faktoren: 1, 8, 15, 24, 35, 45, 48, 63, 77, 80, 91, 99 und 120; mit diesen können alle Zahlen n kleiner als 106, mit n = p i ⋅p j und p i / p j < 2, mittels Lehman-Verfahren (ohne Vorfaktor 4, denn der ist in den o.a. Zahlen schon berücksichtigt) zerlegt werden. 25 Die angegebene Zahlenfolge entspricht genau den ersten Zahlen der Folge der geeigneten Faktoren, mit der Ausnahme, dass zwischen der 99 und 120 die 112 fehlt, also nicht benötigt wird. Fazit: Zur Zerlegung aller hier in Rede stehenden Zahlen reichen rd. n1/3 / 9 Faktoren aus. Um eine belastbare Aussage zu erhalten, welchen effektiven Vorteil der Einsatz der „geeigneten“ Vorfaktoren bringt, wurden alle Zahlen n unterhalb von 1010 mit n = p i ⋅p j und p i / p j < 2 mittels des Standard-Alg., des Spitzendetektors und mit Hilfe der geeigneten Faktoren zerlegt und die Rechenzeiten verglichen (wobei der Zeitbedarf für die Berechnung der geeigneten Faktoren mit berücksichtigt wurde). Es ergibt sich folgendes Bild: Verfahren: Lehman Zeitbedarf: 100 % 172 % Spitzendetektor Leh + geeignete Faktoren 58 % 100 % 21,5 % 37 % Der Vorteil ist also durchaus nennenswert, wobei der prozentuale Zeitgewinn mit größer werdenden Zahlen noch deutlich zunimmt. (Der Vorteil des Spitzendetektor im Vergleich zu Lehman-Verfahren ist hier deutlich geringer als der oben (mit rd. drei) angegebene, was der Beschränkung auf Zahlen mit einem Teilerverhältnis kleiner 2 geschuldet ist.) 26 Anlage 1 Anzahl der Restklassen x mod m, welche als Lösung der Kongruenz x 2 – n ≡ y 2 mod m bei vorgegebenem n infrage*) kommen. (Die nachstehenden Angaben und Formeln beruhen auf der Verallgemeinerung experimenteller Befunde. Beweis?) Im folgenden wird n als ungerade natürliche Zahl mit ggT(n, m) = 1 vorausgesetzt, d.h. r = n mod m ist eine prime Restklasse. Es bedeuten: AQR : Anzahl der quadratischen Reste (Teilmenge der primen Restklassen) ApR : Anzahl primer Restklassen, bei denen die Menge der Restklassen x die gleiche Elementanzahl (Ax) besitzt. Ax : Anzahl der (möglichen) Lösungsrestklassen x mod m Untersucht werden – je in Abhängigkeit vom Modul m – die Fragen, wie viele unterschiedliche Ax-Werte es gibt, welche Werte die Ax explizit annehmen und wie viele prime Restklassen zu den einzelnen Ax-Werten ‚gehören’. Bei der Beantwortung dieser Fragen spielt die Anzahl AQR der quadratischen Reste modulo m eine wesentliche Rolle. α Die Anzahl AQR(m) der QR ist für m = 2 e ⋅ p1α 1 ⋅ . . . ⋅ p h h (pi > 2) gegeben durch h für e < 2 ϕ( m ) h + 1 für e = 2 AQR(m) = mit f = h + 2 für e > 2 2f 1.) m ist Primzahlpotenz; m = p k a) p > 2 Man findet: ApR Ax ϕ (m) / 2 ϕ (m) / 2 – Ck (m) ϕ (m) / 2 ϕ (m) / 2 Es gibt also jeweils 2 verschiedene Ax-Werte, und diese treffen je für genau die Hälfte der primen Restklassen zu. Wichtig ist, dass es sich bei den primen Restklassen der ersten Zeile der Tabelle (ϕ (m) / 2 = AQR ) ausschließlich um quadratische Reste handelt. Für Ck gilt: Ck (p k) k 1 2 3 4 5 6 –1 p–2 p2 – p – 1 p3 – p2 + p – 2 p4– p3 + p2 – p – 1 ...... Das ergibt die Formeln für k >1: Ck (p k) = k ungerade: Ck = = = = = ϕ (p) – 1 ϕ (p 2) – 1 ϕ (p 3) + ϕ (p ) – 1 ϕ (p 4) + ϕ (p 2) – 1 k −1 ∑ ( − 1) k −1+ i ⋅p i − 2 ( k −1) mod 2 oder auch i= 1 k / 2 k/2 i= 1 i= 1 ∑ ϕ ( p 2⋅i ) −1 bzw. k gerade: Ck = ∑ ϕ ( p 2⋅i −1 ) −1 -----------------------*) Die im konkreten Fall tatsächlich vorhandene Lösungsmenge hängt von der hier als nicht bekannt angenommenen Teilerstruktur von n ab. 1 Zwei Beispiele: m = 11 → ϕ (m) = 10, AQR = 5, Ck (11) = – 1 ApR 5 5 Ax 6 5 Die 5 primen Restklassen, die auf Ax = 6 führen, sind die 1, 3, 4, 5, 9 Das sind die qua. Reste mod 11. Im einzeln gilt folgende Zuordnung: pri. Restkl. x-Restklassen 1 → 1, 2, 4, 7, 9, 10 3 → 1, 2, 5, 6, 9, 10 4 → 2, 3, 4, 7, 8, 9 5 → 3, 4, 5, 6, 7, 8 9 → 1, 3, 5, 6, 8, 10 m = 3 6 → ϕ (m) = 3 6 – 3 5 = 486, AQR = 243, Ck (3 6) = 2 + 18 + 162 – 1 = 181 ApR 243 243 Ax 243 – 181 = 62 243 b) p = 2 → m = 2e → ϕ (m) = 2e – 1, AQR = 2e – 3 für e > 2; AQR = 1 sonst Da die Aufteilung der Ax nicht in das einfache Schema für p > 2 passt, andererseits eine Zuordnung der primen Restklassen mod 4 bzw. mod 8 (geschrieben als ‚r(s)’) zu den x-Restklassen mod 2 bzw. mod 4 möglich ist, erfolgt die Angabe tabellarisch: e 1 2 3 4 5 ApR 1 1 1(4) 1 3(4) 2 1 3(8) 1 7(8) 4 2 3(8) 2 7(8) 4 1(8) 4 5(8) 4 3(8) 4 7(8) Ax 1 2 1(2) 2 0(2) 4 2 2(4) 2 0(4) 4 4 2(4) 4 0(4) 8 4 8 2(4) 8 0(4) e 6 ≥7 e 7 8 9 ApR 8 1(8) 8 5(8) 8 3(8) 8 7(8) 2e – 3 1(8) 2e – 3 5(8) 2e – 3 3(8) 2e – 3 7(8) Ax 8 8 16 2(4) 16 0(4) Be 2e – 3 2e – 2 2(4) 2e – 2 0(4) Be 12 16 28 e 10 11 12 Be 48 92 ….. Für die Be gilt die Rekurrenz Be = 2(Be – 1 – 2 1 + e mod 2) mit B6 = 8 und somit Be = (a + 2e – 3) / 3 mit a = 16 für e ungerade und a = 20 für e gerade. Bekanntlich sind alle Restklassen r mod 2e für e > 2 quadratische Reste für r ≡ 1 mod 8. Ab e = 7 weist das zugehörige Ax sich durch den von den übrigen verschiedenen Wert Be aus. Bemerkenswert ist, dass sich erst ab 27 ein festes Schema bezüglich der Ax einstellt. 2 α 2.) m ist das Produkt von Potenzen ungerader Primzahlen; m = p1α 1 ⋅ . . . ⋅ p h h Die Lösungen von (quadratischen) Kongruenzen zu einem zusammengesetzten Modul erhält man bekanntlich (siehe z.B. „Über quadratische Reste und quadratische Kongruenzen“ auf der Netz-Seite des Verfassers) indem zunächst die Lösungen zu den einzelnen Primfaktoren bestimmt werden und diese dann mittels des Chinesischen Restsatzes kombiniert werden. Die gesamte Lösungsanzahl ist das Produkt aus der Anzahl der Lösungen zu den einzelnen Primzahlpotenzen. Analog dazu werden vorliegend entsprechend der Beziehung ϕ (m) = AQR⋅2h die ϕ (m) primen Restklassen in 2h Teilmengen mit der Elementanzahl AQR zerlegt. Die zu diesen Teilmengen gehörenden Ax erhält man durch Bilden aller möglichen Produkte aus den zu jedem Faktor p iαi existierenden zwei Ax-Werten, was gerade 2h Werte ergibt. Am Beispiel: m = 3 3 ⋅5 ⋅11 2 → ϕ (m) = 7920 = 990 ⋅2 3 Die Ax-Werte der Faktoren sind gemäß Ziffer 1): 3 3 5 11 2 4 3 46 ← Ax der qua. Reste 9 2 55 Das ergibt (der Größe nach geordnet) folgende Ax-Werte: Ax ( zu je 990 primen Restklassen mod m) 4⋅2⋅46 = 368 9⋅2⋅46 = 828 4⋅2⋅55 = 440 9⋅2⋅55 = 990 4⋅3⋅46 = 552 9⋅3⋅46 = 1242 4⋅3⋅55 = 660 9⋅3⋅55 = 1485 Auf diese Weise lassen sich die Ax-Werte zu jedem ungeraden Modul bestimmen. Die quadratischen Reste führen auch in diesem Fall alle zum gleichen Ax-Wert. Im Beispiel ist das das Produkt 4⋅3⋅46 = 552. Nicht bei jedem ungeraden Modul kommen 2h unterschiedliche Ax-Werte vor – sondern in manchen Fällen gehört das gleiche Ax zu einem Vielfachen von AQR. Dies ist aber nur scheinbar eine Ausnahme von der Regel, die genau dann auftritt, wenn das betreffende Ax auf mehrere Arten aus den Faktoren dargestellt werden kann. Z.B.: m = 105 = 3⋅5⋅7 → ϕ (m) = 6⋅8 → AQR = 6 Ax der Faktoren: 3 5 7 1 2 3 Es ist 1⋅3⋅4 = 2⋅2⋅3 = 12; also zwei Darstellungen → 2 3 4 Für Ax = 12 ist ApR = 2⋅AQR = 2⋅6 = 12 -------------------------Anmerkung zu den x-Restklassen Wie unter 1.a) gezeigt, weisen die ϕ (p k) (nicht unbedingt verschiedenen) Lösungsmengen Lx(r) für p > 2 nur zwei unterschiedliche Mächtigkeiten auf, und zwar besitzen die Lx(r) für alle r mod p k, die QR mod p sind, die gleiche Elementanzahl (Ax(QR)) und desgleichen führen die QNR mod p auf Ax(QNR). Hinsichtlich der Elemente der Lx(r) fallen folgende Eigenschaften ins Auge: Insgesamt kommen in den Lx(r) alle Restklassen mod p k mindestens einmal vor (gilt auch für p = 2). Weiter gilt: x ∈ Lx(r) → m – x ∈ Lx(r) (symmetrische Anordnung, da mit x immer auch – x eine Lösung der quadratischen Kongruenz ist). Daraus folgt, dass Ax genau dann ungerade ist, wenn Lx(r) die Restklasse ’0’ enthält, da in diesem Fall x und m – x mod m identisch sind. Die Lx(r) mit ungerader Elementanzahl enthalten außerdem alle x mit x ≡ 0 mod p (das sind p k – 1). In den Lx(r) mit gerader Elementanzahl sind ausschließlich zu p teilerfremde x-Restklassen enthalten. 3 α 3.) Allgemeiner Modul m = 2 e ⋅ p1α 1 ⋅ . . . ⋅ p h h Zweckmäßigerweise werden zunächst die 2h Ax-Werte des ungeraden Anteils u von m gemäß Ziffer 2.) berechnet. Die Auswirkungen der Multiplikation mit 2e werden aus Gründen der Übersichtlichkeit in Tabellenform (die im Wesentlichen eine Kurzform der Tabelle aus Ziffer 1.b) ist) angegeben. Es sei AQR(2e ⋅u) = fQR ⋅AQR(u); ApR(2e ⋅u) = fpR ⋅ApR(u); Ax (2e ⋅u) = fx ⋅Ax (u) e 1 2 3 fQR 1 1 1 4 5 2 4 5(8) 6 8 1,5(8) ≥7 2e – 3 1(8) 5(8) 3,7(8) ApR 16⋅6 = 96 16⋅12 = 192 16⋅6 = 96 16⋅6 = 96 16⋅12 = 192 16⋅6 = 96 32⋅6 = 192 32⋅12 = 384 32⋅6 = 192 1,5(8) fpR 1 2 2 2 8 4 12 16 16 2e – 3 2e – 3 2e – 2 fx 2 2 4 2 4 4 8 8 16 Be 2e – 3 2e – 2 Beispiel: m = 27 ⋅32 ⋅5 → AQR(u) = 6 ApR(u) 6 12 6 Ax (u) 4 6 9 Es ist 2e – 3 = 16 und B7 = 12 Damit können die Werte für ApR(m) und Ax (m) berechnet werden (siehe nachstehende Tabelle). Ax 12⋅4 = 48 12⋅6 = 72 12⋅9 = 108 16⋅4 = 64 16⋅6 = 96 16⋅9 = 144 32⋅4 = 128 32⋅6 = 192 32⋅9 = 288 4.) Zuordnung vorgegebene prime Restklasse → Ax Die obigen Ergebnisse ermöglichen die Bestimmung der unterschiedlichen Mächtigkeiten Ax der potentiellen Lösungsmengen (Restklassen x mod m) und machen Aussagen, wie viele prime Restklassen den verschiedenen Ax zuzuordnen sind. Darüber hinaus ist aber auch leicht zu bestimmen, auf welches Ax eine vorgegebene prime Restklasse r = n mod m führt. Z.B. sei bei dem Modul m = 27 ⋅32 ⋅5 des vorstehenden Beispiels r = 437. Wie groß ist Ax(r) ? Da die ungeraden Primzahlpotenzen bezüglich der Ax nur danach unterscheiden, ob r quadratischer Rest bzw. Nichtrest ist, ist je ungeradem Primfaktor das Legendre-Symbol zu berechnen, und für den geraden Anteil 2e ist festzustellen, in welcher Restklasse modulo 8 der Rest r liegt. Vorliegend ist r mod 8 = 5, r mod 3 = 2 (also kein QR) und r mod 5 = 2 (ebenfalls kein QR). Damit liefert 27 den Faktor 16 (siehe obige Tab.), 32 den Faktor 3 (= ϕ (9) / 2) und 5 den Faktor 2 (= ϕ (5) / 2). D.h. beim Rest r = n mod m = 437 sind (von den insgesamt 5760) genau Ax = 16⋅3⋅2 = 96 Restklassen x mod 5760 in Betracht zu ziehen, welche als Lösung der Kongruenz x2 – n ≡ y2 mod m infrage kommen. 4 Anhang 1 Jede Lösung der diophantischen Gleichung n = x2 – y2 (*) kann man trivialer Weise einem der folgenden vier Fälle zuordnen: (g,g): x ist gerade und y ist gerade (g,u): x ist gerade und y ist ungerade Analog: (u,g) und (u,u) Beschränkt man sich auf ungerade n kommen nur die beiden Fälle (g,u) und (u,g) in Frage. Fall (g,u): Einsetzen von x = 2x’ und y = 2y’ +1 in (*) führt auf n 4+ 1 = x '² − ( y'² + y' ) bzw. (wenn die beiden Variablen wieder mit x und y bezeichnet werden) auf x²− n+1 = y² + y . 4 (**) Diese Gleichung ist lösbar, wenn (n + 1)/4 eine ganze Zahl ist, wenn also n ≡ 3(4) . Die Suche nach einer Lösung startet man zweckmäßigerweise mit x o = 12 n + 1 . Die zum Auffinden einer Lösung erforderliche Schrittzahl ist dann nur halb so groß (im Grenzwert) wie bei Anwendung von (*); das Teilerpaar (t1,t2) errechnet sich aus t1 = 2(x + y) + 1 und t2 = 2(x – y) – 1. Fall (u,g): Das analoge Vorgehen führt auf x ² + x − n −1 = y² . 4 (***) Diese Form bezieht sich auf Zahlen n ≡ 1(4). Es gilt x o = 12 ( n − 1) , t1 = 2(x + y) + 1 und t2 = 2(x – y) + 1. Wird die gleiche Prozedur auf die Gleichungen (**) und (***) angewandt, erhält man insgesamt 8 Gleichungen. Zum Modul 8 gibt es 4 ungerade Restklassen. Auf jede dieser Restklassen entfallen genau 2 der 8 Gleichungen. Diese – und ebenso alle weiteren auf diese Art erzeugten Gleichungen – sind von folgender Form: 2 ( k − 2) ⋅ x ² + a ⋅ x − n+r 2k = 2 ( k − 2) ⋅ y ² + b ⋅ y (****) In (**) und (***) ist k = 2; in der darauffolgenden Stufe ist k = 3, u.s.w. Die drei Größen a, b und r lassen sich unter Verwendung der Abkürzung h = 2(k – 2) für die jeweils nächste Stufe rekursiv leicht bestimmen: (g,g): (g,u): (u,g): (u,u): a <== a; a <== a; a <== 2h + a; a <== 2h + a; b <== b; b <== 2h + b; b <== b; b <== 2h + b; r <== r r <== r + 2k ⋅ (h + b) r <== r – 2k ⋅ (h + a) r <== r + 2k ⋅ (b – a) Abschließend: k <== k + 1 h = 2h. Die Restklasse mod 2k, für die die betr. Gleichung „zuständig“ ist, folgt natürlich sofort aus der Größe r. Beispiel: Aus (**) soll die im Fall (u,u) gültige Gleichung entwickelt werden. k = 2: a = 0; b = 1; r = 1; h = 1. Es folgt k = 3: a = 2⋅1 + 0; b = 2⋅1 + 1; r = 1 + 22⋅(1 – 0) = 5. n + 5 ist genau dann durch 23 teilbar, wenn n ≡ 3(23). Für diese lautet also eine der beiden Gleichungen: 2x² + 2x – n+ 5 8 = 2y² + 3y (Wie sich zeigt, lassen sich mit dieser Gleichung sogar alle Teilerpaare der Zahlen n ≡ 3(8) bestimmen.) 1 Praktisch anwendbar zur Der Startwert für x ist x o = ( k1−1) ( n + r + a 2 − a ) 2 Teilersuche sind die Gleichungen natürlich nur, wenn es ein einfaches Kriterium gibt, das entscheidet, ob ein vorgelegtes x die betr. Gleichung erfüllt. Dieses Kriterium ist vorhanden: x ist genau dann eine Lösung, wenn der Term d = 2k ⋅m + b2 ein Quadrat – also d = w2 – ist, wobei der Wert der linken Seite von (****) mit ‚m’ abgekürzt wurde. Hat man ein d = w2 gefunden, errechnet sich das zugehörige Teilerpaar t1⋅t2 = n zu t1 = 2(k – 1)⋅x + a + w und t2 = 2(k – 1)⋅x + a – w. [Also n = (2(k – 1)⋅x + a) 2 – w 2 ] Nun stellt sich natürlich die Frage, inwieweit das Verfahren geeignet ist, die Anzahl der Iterationen („Schrittzahl“) des Basis-Algorithmus zu reduzieren. Für k = 2 wurde oben bereits gesagt, dass die Schrittzahl halbiert wird und man beim Übergang zu k = 3 für jede der 4 ungeraden Restklassen von 23 zwei Gleichungen erhält. Das ist bei jeder weiteren Erhöhung von k so; die Anzahl der je Restklasse zu lösenden Gleichungen beträgt somit 2(k – 2). Da die Schrittzahl je Gleichung sich gegenüber Basis-Algorithmus gleichzeitig ungefähr auf den 2(k – 1) ten Teil reduziert, ergibt sich gegenüber k = 2 keine Verbesserung mehr (was auch nicht überrascht). Die weitere Prüfung zeigt allerdings, dass die gemäß dem o.a. Verfahren gebildeten Gleichungen nicht alle benötigt werden, denn alle Gleichungen, in denen der Wert von a derselbe ist, liefern die gleichen Teilerpaare der vorgelegten Zahl n. Es ist daher einfach, die überflüssigen Gleichungen auszusortieren. Die nachstehende Tabelle zeigt in Abhängigkeit von k, wie viele Gleichungen tatsächlich benötigt werden. Dabei gibt es bemerkenswerte Unterschiede je nach dem zu welcher Restklasse mod 8 die zu zerlegende Zahl gehört. k: 2 3 4 5 6 7 8 9 10 n ≡ 1(8): 5(8): 3,7(8): 1 1 1 2 2 1 2 2 2 4 2 4 4 4 8 6 8 16 8 16 32 14 32 64 24 64 128 Für Zahlen n ≡ 3(4) ist also ab k = 3 keine Verbesserung mehr möglich; für n ≡ 5(8) liegt die Schwelle bei k = 5. Dagegen scheint die Zunahme an Gleichungen für n ≡ 1 (8) auch für große k immer unterhalb einer Verdoppelung zu bleiben; allerdings ist der Gewinn ab k = 10 nicht mehr nennenswert. Im folgenden sind – als Auswahl der zahlreichen Varianten (gleiche a-Werte) – für k = 4 die maßgeblichen Größen r, a und b (siehe (****)) der 2 je prime Restklasse mod 16 erforderlichen Gleichungen angegeben. Die letzte Spalte zeigt, zu welcher Restklasse mod 16 die beiden Teiler (eines Paares) gehören, die von der betreffenden Gleichung gefunden werden. Ihr Produkt muss natürlich die in der ersten Spalte angegebene Restklasse ergeben. 2 n(16) r a b {t1,t2} mod 16 1 –1 – 49 1 7 0 0 1/1, 9/9, 5/13, 3/11, 7/7, 15/15 3 –3 13 2 6 1 7 1/3, 9/11 5/7, 13/15 5 –5 11 3 5 2 6 1/5, 9/13 3/7, 11/15 7 –7 9 4 0 3 3 1/7, 9/15 3/13, 5/11 9 –9 7 5 3 4 4 1/9, 5/5, 13/13 3/3, 7/15, 11/11 11 –11 5 6 2 5 3 1/11, 3/9 5/15, 7/13 13 –13 3 7 1 6 2 1/13, 5/9 3/15, 7/11 15 –15 49 4 0 1 7 3/5, 11/13 1/15, 7/9 Insgesamt ist es erstaunlich, dass die mehrfache Anwendung der nun wirklich trivialen Information „Die Lösung ist entweder gerade oder ungerade“ eine wesentliche Verminderung des Aufwandes zur Teilerbestimmung bewerkstelligen kann. Der Algorithmus (zum Experimentieren; hier am Beispiel n ≡ 1 mod 16; erste Zeile): Vorgabe: n (≡ 1 mod 16) k = 4: a = 1: b = 0: r = – 1 k0 = 2^k: k1 = k0 div 2: k2 = k1 div 2 x = int ((sqr (n + r + a^2) – a) / k1): nr = (n + r) div k0 m = k2 * x^2 + a * x – nr: d = 0: w = 1 do while d <> w^2 m = m + k2 * (2 * x + 1) + a d = k0 * m + b^2: w = isqrt(d) x=x+1 loop c = k1 * x + a Ausgabe: t1 = c + w: t2 = c – w (falls die beiden Teiler in den o.a. Restklassen liegen.) 3 Eine effektive Nutzung für die Faktorisierung ist dann nur möglich, wenn alle Gleichungen, die die betr. Zahl erfüllen können, simultan abgearbeitet werden. Das ist ohne weiteres möglich, wie das nachstehende Beispiel zeigt, wobei auf die o.a. Darstellung n = (2(k – 1)⋅x + a) 2 – w 2 zurück gegriffen wird: Eingabe: n (≡ 5 mod 16 oder ≡ 9 mod 16) k = 4: a = 3: a2 = 5 k1 = 2^(k–1): f2 = 2 * k1 * (a2 – a): e2= a2^2 – a^2 x0 = INT ((SQR (n + 1 – a^2) – 1) / k1) FOR x = x0 + 1 TO n s = k1 * x + a m = s^2 – n: y = INT (SQR (m)) IF y^2 = m THEN PRINT “Teiler: ”;s + y; s – y: EXIT m2 = m + f 2 * x + e2: y2 = INT (SQR (m2)) IF y2^2 = m2 THEN PRINT “Teiler: “;s – a + a2 + y2; s – a + a2 – y2: EXIT NEXT x Der Algorithmus benötigt also nur die beiden für die Restklasse 5(16) und 9(16) zuständigen a-Werte (siehe obige Tabelle); der Wert von m2 wird zur Vereinfachung aus m berechnet. Fazit: Jede zusammengesetzte ungerade Zahl besitzt für alle k mit 2 k < n Darstellungen als n = (2 k – 1 ⋅x + a) 2 – y 2 (0 ≤ a < 2 k–1 ) wobei a nur von den Restklassen modulo 2 k der beiden Faktoren 2 k –1⋅x + a + y und 2 k –1⋅x + a – y abhängt. 4 Anhang 2 Serieller Einsatz von Vorfaktoren DEFEXT V-Z DEFQUD A-U DIM a(1 TO 83000,1 TO 3) AS LONG DIM v(1 TO 63000000,0 TO 5) AS LONG '========================================= '0. Vorgaben: n,i0,f0,dd,vmax (ganzzahlig) 'z.B.:i0=5*10^2:f0=1*10^6:dd=40:vmax=3 ---------------------------------------wn=SQR(n) im=INT(wn*(SQR(vmax)+1/SQR(vmax)-2)/2)+1:PRINT im 'Schrittzahl Basis-Alg. '1. Belegung der Ränder des Intervalls [1,v-max] f=1:ru=f0:z=1+i0/wn i..:Schrittzahl vo=(z+SQR(z^2-1))^2:ro=INT(vo*f0) ii :Schrittz.-Summe v(ru,0)=1:v(ru,3)=i0:v(ru,4)=1:v(ru,5)=1:ii=i0 si :Belegungs-Summe FOR j=ru TO ro:v(j,1)=ro:v(j,2)=ru:NEXT j:si=ro-ru w..:Quadrat-Wurzel f=vmax:ro=f*f0:z=1+i0/(wn*SQR(f)) wvu=SQR(f)*(z-SQR(z^2-1)):vu=wvu^2:ru=INT(vu*f0) v(ru,0)=f: v(ru,3)=i0: v(ru,4)=f: v(ru,5)=1: ii=ii+i0 FOR j=ru TO ro:v(j,1)=ro:v(j,2)=ru:NEXT j:si=si+ro-ru+1 'For..Next: von f IF si=>(vmax-1)*f0 THEN END 'belegten Bereich in v(,) markieren '2. Erzeugung der Vorfaktoren f = c*s (v= c/s) FOR s=2 TO 10^12 FOR c=s+2 TO vmax*s-2 STEP 2 IF c MOD 4=2 AND s MOD 4=2 THEN ITERATE 'ITERATE: Vorfaktor wird verworfen ed=s:ec=c:DO UNTIL ed=0:er=ec MOD ed:ec=ed:ed=er:LOOP ggt=ec: IF ggt>2 THEN ITERATE 'ggT-Berechnung f= c*s '3. Berechnung des von f belegten v-Intervalls sowie der Schrittzahl wvk=SQR(c/s): rv=INT(wvk^2*f0) IF v(rv,1)>0 THEN ITERATE IF v(rv-dd,1)>0 AND v(rv+2*dd,1)=0 THEN ITERATE IF v(rv+dd,1)>0 AND v(rv-2*dd,1)=0 THEN ITERATE wf=wn*SQR(f): z=1+i0/wf wvo=wvk*(z+SQR(z^2-1)): vo=wvo^2:ro=INT(vo*f0)-1 wvu=wvk*(z-SQR(z^2-1)): vu=wvu^2:ru=INT(vu*f0)+1 '3a. Fallunterscheidung (aa = 1, 2, 3, 4) FOR e=1 TO 1 IF v(ro,1)=0 AND v(ru,1)=0 THEN aa=1 'Bereich komplett frei IF v(ro+dd,1)>0 AND v(ru-dd,1)>0 THEN aa=2:ro=ro+dd:ru=ru-dd:EXIT IF v(ro+dd,1)>0 AND v(ru-dd,1)=0 THEN aa=3:ro=ro+dd:EXIT IF v(ro+dd,1)=0 AND v(ru-dd,1)>0 THEN aa=4:ru=ru-dd:EXIT IF v(ro,1)>0 AND v(ru,1)>0 THEN aa=2 'Belegung überlappt beidseitig IF v(ro,1)>0 AND v(ru,1)=0 THEN aa=3 IF v(ro,1)>0 AND v(ru-dd,1)>0 THEN aa=2:ru=ru-dd:EXIT IF v(ro,1)=0 AND v(ru,1)>0 THEN aa=4 IF v(ro+dd,1)>0 AND v(ru,1)>0 THEN aa=2:ro=ro+dd NEXT e SELECT CASE aa CASE 1 v(ru,0)=f: v(ru,3)=i0:v(ru,4)=c: v(ru,5)=s:ii=ii+i0 FOR j=ru TO ro:v(j,1)=ro:v(j,2)=ru:NEXT j:si=si+ro-ru+1 CASE 2 ru1=v(ru,1)+1:DO WHILE v(ru1,1)>0:ru1=v(ru,1)+1:ru=v(ru1,2):LOOP ro1=v(ro,2)-1:DO WHILE v(ro1,1)>0:ro1=v(ro,2)-1:ro=v(ro1,1):LOOP wvo=SQR((ro1+2)/f0):y=wvo/wvk+wvk/wvo-2:iho=INT(y*wf/2)+1 wvu=SQR((ru1-2)/f0):y=wvu/wvk+wvk/wvu-2:ihu=INT(y*wf/2)+1 ih=MAX(iho,ihu) v(ru1,0)=f: v(ru1,3)=ih: v(ru1,4)=c: v(ru1,5)=s: ii= ii+ih FOR j=ru1 TO ro1:v(j,1)=ro1:v(j,2)=ru1:NEXT j:si=si+ro1-ru1+1 1 CASE 3 ro1=v(ro,2)-1:DO WHILE v(ro1,1)>0:ro1=v(ro,2)-1:ro=v(ro1,1):LOOP wvo=SQR((ro1+2)/f0):y=wvo/wvk+wvk/wvo-2:ih=INT(y*wf/2)+1:z=1+ih/wf wvu=wvk*(z-SQR(z^2-1)):vu=wvu^2:ru=INT(vu*f0) v(ru,0)=f: v(ru,3)=ih: v(ru,4)=c: v(ru,5)=s: ii= ii+ih FOR j=ru TO ro1:v(j,1)=ro1:v(j,2)=ru:NEXT j:si=si+ro1-ru+1 CASE 4 ru1=v(ru,1)+1:DO WHILE v(ru1,1)>0:ru1=v(ru,1)+1:ru=v(ru1,2):LOOP wvu=SQR((ru1-2)/f0):y=wvu/wvk+wvk/wvu-2:ih=INT(y*wf/2)+1:z=1+ih/wf wvo=wvk*(z+SQR(z^2-1)):vo=wvo^2:ro=INT(vo*f0) v(ru1,0)=f: v(ru1,3)=ih: v(ru1,4)=c: v(ru1,5)=s: ii= ii+ih FOR j=ru1 TO ro:v(j,1)=ro:v(j,2)=ru1:NEXT j:si=si+ro-ru1+1 END SELECT IF si=>(vmax-1)*f0 THEN EXIT,EXIT NEXT c NEXT s '4. Fertig; Darstellung der Ergebnisse, Belegung a=0 FOR o=f0 TO vmax*f0 IF v(o,0)<>0 THEN a=a+1:a(a,1)=v(o,0):a(a,2)=v(o,3)+1:a(a,3)=v(o,5) 'Speichert f, Schrittzahl, s in der Matrix a(,) NEXT o PRINT "n= ";n, "Schritte Basis-Alg./red. Schrittzahl: ";INT(im/ii) PRINT "Anzahl Vorfak.:"; a,"Max. Vorfak.:";c"*";s;"=";f 'Kontrolle, ob alle v-Werte (überlappend) belegt sind FOR h=1 TO a:'PRINT ,,,a(h,1),a(h,2),a(h,3) z=1+a(h,2)/(wn*SQR(a(h,1))):wz=SQR(z^2-1):wv=SQR(a(h,1))/a(h,3) wvo=wv*(z+wz):vo=wvo^2:wvu=wv*(z-wz):vu=wvu^2 IF vd-vu<0 AND h>1 THEN PRINT vo,vu,vd-vu;"Fehler!" vd=vo NEXT h END 2 Anhang 3 Vergleich von Varianten des Lehman-Verfahren (Kurzbeschreibung ist unten angefügt) function le(mi: integer); var n0,n,n1,n2,n3,n6,n16,nw,nu,nr,nz,v,v1,v2,i,j,g,b,k: integer; u,ug,og,m,x,d,c,fn: integer; t: real; e: array[5011] begin #--------------------Teil 1--------------------------------------n0: = 10**mi; b: = 1000; nw: = isqrt(n0); nu: = floor(n0**(1/3)); random_seed(666); nr: = nw – nu; i: = 0; while i < b + 10 do v1: = random(nr); v1: = v1 + nu; n1: = next_prime(v1,0); v2: = n0 div n1; n2: = next_prime(v2,0); n: = n1 * n2; if n1 <> n2 then i: = i+1; e[i]: = n; end; end; #-------------------LEH -------------------------------------t:= timer(); c:=0; # c zählt die Anzahl der erf. Rechenzyklen for k:=1 to b do n:=e[k]; n3:=floor(n**(1/3)); n6:=isqrt(n3)+1; g:=4*n; fn:=0; j:=0; i:=1; while j=0 do fn:=fn+g; ug:=isqrt(fn)+1; d:=4*isqrt(i); og:=ug+floor(n6/d); i:=i+1; for u:=ug to og do m:=u**2-fn; x:=isqrt(m); c:=c+1; if m=x**2 then v1:=gcd(u-x,n); v2:=n div v1; j:=1; break; end; end; end; end; writeln("LEH: ",floor(c/b)," Zyklen (Mittelw.)"); writeln("Zeit: ",floor((timer()-t)/1000)," Sek."); #-------------------LEH16---------------------------------------t: = timer(); c: = 0; for k: = 1 to b do n: = e[k]; n3: = floor(n**(1/3)); nz: = floor(n3/64); n6: = isqrt(n3); j: = 0; n16: = 16 * n; for i: = 1 to nz do fn: = n16 * i; ug: = isqrt(fn) + 1; d: = 8 * isqrt(i); og: = ug + floor(n6 / d); for u: = ug to og do m: = u**2 – fn; x: = isqrt(m); c: = c + 1; if m = x**2 then v1: = gcd(u + x, n); v2: = n div v1; j: = 1; nz: = n3; break; end; end; if j=1 then break; end; end; 1 for i:=nz+1 to n3 do fn:=n16*i; u:=isqrt(fn)+1; m:=u**2-fn; x:=isqrt(m); c:=c+1; if m=x**2 then v1:=gcd(u+x,n); v2:=n div v1; break; end; end; end; writeln("LEH16 ",floor(c/b)," Zyklen (Mittelw.)"); writeln("Zeit: ",floor((timer()-t)/1000)," Sek."); #-------------------Spitzendetektor-------------------------------t: = timer(); c: = 0; for k: = 1 to b do n: = e[k]; fn: = n * 10080; v: = 0; m: = 0; x: = 1; while m <> x**2 do v: = v + fn; u: = isqrt (v) + 1; m: = u**2 – v; x: = isqrt(m); c: = c + 1 ; end; v1: = gcd (u – x, n); v2: = n div v1; end; writeln("Spitz.: ",floor(c/b)," Zyklen (Mittelw.)"); writeln("Zeit: ",floor((timer()-t)/1000)," Sek."); #----------------------------------------------------------------end. Erläuterung: Lautet die Start-Eingabe z.B. „ le(12).“, wird in Teil 1 ein Satz von 1000 Zahlen der Größenordnung 1012 generiert, die das Produkt von 2 Primfaktoren sind. Der kleinere der beiden Primfaktoren wird dabei ‚zufällig’ aus dem Intervall [1012/3, 1012/2] ausgewählt. Speicherung der Zahlen im Vektor e[ ]. (Wählt man den Exponenten > 21 – etwa „ le(22).“ – sollte man etwas Zeit zur Verfügung haben.) Anschließend werden die 1000 Zahlen mit den 3 o.a. Varianten faktorisiert, wobei die erste (LEH) das Standard-Verfahren beinhaltet. Der Vorteil von „Spitz.“ gegenüber LEH wächst (im Mittel) mit dem Teilerverhältnis. Wählt man z.B. das Teilerverhältnis ‚zufällig’ aus dem Intervall [1, n1/3] und bestimmt daraus die beiden Teiler so, dass ihr Produkt möglichst nahe an 10x liegt, steigt der Zeitvorteil auf über das fünffache an. 2