Das Problem ist wie folgt.
Eingabe: Eine ganze Zahln
Output: Die kleinste Primzahl größer als n
.
Die Herausforderung besteht darin, den schnellstmöglichen Code dafür anzugeben. Ich werde den Code auf Werten testen, die ungefähr bei der Größe beginnen 10^8
10^200
und sich verdoppeln, bis es auf meinem Computer mehr als eine Minute und 10 Sekunden dauert .
Der Gewinncode findet die nächste Primzahl für die größte Eingabegröße.
Im Vergleich dazu , ein einfaches Sieb in Python geschrieben ist in der Lage die nächste Primzahl größer zu finden , als 10^8
in etwa 20
Sekunden.
Die Anforderung, dass ich es auf meinem 4 GB RAM Ubuntu-Computer testen kann, ist streng. Der gesamte Code muss (in beiden Richtungen) frei sein, und wenn Bibliotheken verwendet werden, müssen sie auch frei und leicht installierbar sein. Alle gemeldeten falschen Primzahlen disqualifizieren die Einsendung sofort.
Ich werde auch für die Gewinner in jeder Programmiersprache separate Auszeichnungen vergeben, wenn der Code vollständig in dieser Sprache geschrieben ist und keine externen Bibliotheken verwendet werden. Ich werde auch einen Lauftisch mit den schnellsten Zeiten halten, während der Wettbewerb weitergeht, damit die Leute sehen können, wie es ihnen geht.
Tisch so weit
- Python. Eine erstaunliche
357
Ziffer Primzahl343239883006530485749095039954069660863471765007165270469723172959277159169882802606127982033072727748864815569574042901856099399985832190628701414555752857600000000000000000000000000000000000000002872284792758930912601189043411951050852357613658978971208596097634095500808832510259693761982135208603287199546795000697807728609476163156438356035166156820611
war die letzte Zahl unter 10 Sekunden mit dem Code vonprimo
. Wird jemand diesen ersten Eintrag schlagen?
quelle
fast next prime function
.Antworten:
Python ~ 451 Stellen
Dies ist ein Teil der Bibliothek, die ich für ein Semiprime-Faktorisierungsproblem geschrieben habe , bei dem unnötige Funktionen entfernt wurden. Es wird der Baillie-PSW-Primalitätstest verwendet , der technisch gesehen ein probabilistischer Test ist. Bisher sind jedoch keine Pseudoprimes bekannt - und es gibt sogar eine Geldprämie, wenn Sie eine finden können (oder wenn Sie einen Beweis vorlegen, dass keine existieren). .
Edit : Ich hatte nicht bemerkt, dass Python modulare Potenzierung eingebaut hat. Das Ersetzen meiner eigenen durch die eingebauten führt zu einer Leistungssteigerung von ca. 33%.
my_math.py
Ein Beispiel für ein Testskript:
Ein Faktor von 317 wurde gewählt, weil er ungefähr die Quadratwurzel von
10000
ist und ungefähr 2,5 Stellen pro Iteration hinzufügt (und weil das Verdoppeln zu langsam war, um durchzuhalten). Die Ausgabe zeigt die aktuelle Anzahl der Stellen und die benötigte Zeit.Beispielergebnisse:
Der gesamte Code ist jetzt Python 3-kompatibel.
quelle
next_prime((2^520)*(10^200))
ungefähr 15 Sekunden auf meiner Maschine, also auf den ersten Blick ist das ziemlich beeindruckend. Esnext_prime((2^520)*(10^200),proof=False)
dauert jedoch ... 0,4 Sekunden, da nur auf Pseudoprimalität geprüft wird. Ihr Anspruch : „Es gibt keine bekannte Pseudoprimzahlen“ zu überzeugen , ist verschwindend als die Anzahl der Bits geht über 64. 357 Ziffern, ich bin nicht einmal entfernt durch einen Mangel an Gegenbeispielen überzeugt.C ++ mit GMP: 567 Stellen
Verwendet die Miller-Rabin-Implementierung in GMP. Es könnte ein falsch positives Ergebnis liefern, aber viel Glück beim Treffen eines mit einer Wahrscheinlichkeit von 2 ^ -200.
Findet die Primzahl
10^200 * 2^1216 + 361
(567 Stellen), bevor sie mit der Zeit auf meinem langsamen Laptop ausgeführt wird.quelle
Perl mit GMP-Modul, 1300 Stellen
Mit meinem Modul Math :: Prime :: Util und seinem GMP- Backend . Der genaue Übergangspunkt hängt von Ihrem Computer ab und davon, ob Sie über die neueste GMP-Bibliothek verfügen. Der gesamte Code ist kostenlos (die Module sind auf Github und CPAN und GMP ist frei verfügbar). Ich habe sie auf AWSs Ubuntu sowie auf einem Desktop-Ubuntu (und Fedora, AIX und NetBSD usw.) ausgeführt.
Der Kerncode ist in C und C + GMP. next_prime von MPU erkennt, dass die Nummer zu groß ist und leitet sie an das GMP-Back-End weiter (oder reinen Perl-Code, wenn das Back-End nicht installiert ist). Dadurch wird das Ergebnis in einen mpz-Wert umgewandelt und wieder in den Eingabeobjekttyp oder Math :: BigInt konvertiert. next_prime selbst macht:
Der wahrscheinliche Primetest ist:
Alles vor dem ES BPSW ist nur Optimierung, was wir natürlich für next_prime wollen. next_prime wird auch in Perl mithilfe des Math :: BigInt-Moduls implementiert (im Kern mit optionalen Pari- und GMP-Backends). Das macht AES BPSW (wie Pari), ist aber nicht so optimiert.
Ich habe über die Vorzüge einer auf einem Teilsieb basierenden Version nachgedacht und dabei eine Reihe von beispielsweise zwei Vorzügen verwendet. Ich bin mir nur nicht sicher, ob dies wirklich besser wäre, da wir die meiste Zeit unnötig gesiebt haben, da die Lücke klein war, und manchmal mussten wir sie für eine große Lücke mehrmals wiederholen.
Die Bibliothek implementiert ECPP (einschließlich Zertifikate), so dass wir einen Proof für das Ergebnis ausführen können, aber 1200 Stellen sind wirklich zu groß für den winzigen Standardsatz der enthaltenen Polynome (es gibt eine Methode zum Herunterladen größerer Sätze - Proofs würden etwas länger dauern) 15 Minuten, etwas schneller als der APR-CL von Paris, aber etwas langsamer als der mpz_aprcl von WraithX). Ein Nachteil von ECPP im Vergleich zu APR-CL ist, dass es mehr Zeitabweichungen gibt, so dass die Wahrscheinlichkeit hoch ist, dass es bei einer bestimmten Zahl 10 Sekunden überschreitet, bevor die durchschnittliche Zeit dort ankommt. Mit einem Beweis, denke ich, sind wir auf etwas im 400-stelligen Bereich beschränkt, sofern wir keine Multithread-Software zulassen.
Ich habe mich entschlossen, es mit der gleichen Sequenz zu versuchen, die auch primo verwendet. Es wurden 1191 Stellen erreicht, da wir hier eine Lücke von 18138 erreichten. Ich habe auch Primos Code mit der neuesten Datei my_math.py getestet. Es werden 630 Stellen mit der Sequenz 10 ^ e und 641 mit seiner Sequenz erreicht. Sehr beeindruckend für kompakten Python-Code ohne viele Vortests.
quelle
Math::GMP
auf eine Weise um, die mit der Erstellung / Zerstörung von mpz-Referenzen nicht ganz so verschwenderisch ist.$x = new Math::GMP(0); $x += 3 for 1..1000000
. Ich werde auf cpan posten, wenn ich fertig bin. Du wirst einer der ersten sein, die es wissen;)