Le problème est le suivant.
Entrée: un entiern
Sortie: Le plus petit nombre premier plus grand que n
.
Le défi est de donner le code le plus rapide possible pour ce faire. Je vais tester le code sur des valeurs commençant à peu près à la taille 10^8
10^200
et doublant de taille jusqu'à ce que cela prenne plus d' une minute 10 secondes sur mon ordinateur.
Le code gagnant trouvera le premier nombre premier pour la plus grande taille d'entrée.
À titre de comparaison, un simple tamis écrit en python est capable de trouver le premier nombre supérieur plus gros qu'en quelques secondes 10^8
environ 20
.
L'obligation de pouvoir le tester sur mon ordinateur ubuntu de 4 Go de RAM est stricte. Tout le code doit être gratuit (dans les deux sens) et s'il utilise des bibliothèques, il doit également être gratuit et facilement installable. Tout faux nombre premier signalé disqualifiera immédiatement la soumission.
J'attribuerai également des mentions élogieuses aux gagnants dans chaque langage de programmation si le code est entièrement écrit dans ce langage sans utiliser de bibliothèques externes. Je garderai également un tableau des meilleurs temps au fur et à mesure de la compétition afin que les gens puissent voir comment ils vont.
Table jusqu'ici
- Python. Un
357
nombre premier étonnant343239883006530485749095039954069660863471765007165270469723172959277159169882802606127982033072727748864815569574042901856099399985832190628701414555752857600000000000000000000000000000000000000002872284792758930912601189043411951050852357613658978971208596097634095500808832510259693761982135208603287199546795000697807728609476163156438356035166156820611
était le nombre final inférieur à 10 secondes utilisant le code fourni parprimo
. Est-ce que quelqu'un battra cette première entrée?
la source
fast next prime function
.Réponses:
Python ~ 451 chiffres
Cela fait partie de la bibliothèque que j'ai écrite pour un problème de factorisation semi - primaire , avec des fonctions inutiles supprimées. Il utilise le test de primalité Baillie-PSW , qui est techniquement un test probabiliste, mais à ce jour, il n'y a pas de pseudoprimes connus - et il y a même une récompense en espèces si vous en trouvez un (ou pour fournir une preuve qu'il n'en existe pas) .
Edit : je n'avais pas réalisé que Python avait une exponentiation modulaire intégrée. Remplacer le mien pour les résultats intégrés entraîne une augmentation des performances d'environ 33%.
my_math.py
Un exemple de script de test:
Un facteur de 317 a été choisi, car il s'agit approximativement de la racine carrée de
10000
, ajoutant environ 2,5 chiffres par itération (et parce que le doublement était trop lent pour s'asseoir). La sortie affiche le nombre actuel de chiffres et le temps nécessaire.Exemples de résultats:
Tout le code est désormais compatible python 3.
la source
next_prime((2^520)*(10^200))
environ 15 secondes sur ma machine, donc à première vue, c'est assez impressionnant. Cependant ...next_prime((2^520)*(10^200),proof=False)
prend 0,4 seconde car il ne vérifie que la pseudoprimalité. Votre affirmation "il n'y a pas de pseudoprimes connus" est convaincante car le nombre de bits dépasse 64. Pour 357 chiffres, je ne suis même pas convaincu à distance par un manque de contre-exemples.C ++ avec GMP: 567 chiffres
Utilise l'implémentation Miller-Rabin dans GMP. Cela pourrait renvoyer un faux positif, mais bonne chance en frapper un avec une probabilité de 2 ^ -200.
Trouve le premier
10^200 * 2^1216 + 361
(567 chiffres) avant de courir dans le temps sur mon ordinateur portable lent.la source
Perl avec module GMP, 1300 chiffres
Utiliser mon module Math :: Prime :: Util et son back-end GMP . Le point de croisement exact dépendra de votre ordinateur et de votre dernière bibliothèque GMP. Tout le code est gratuit (les modules sont sur github et CPAN, et GMP est disponible gratuitement). Je les ai exécutés sur Ubuntu d'AWS ainsi que sur Ubuntu de bureau (et Fedora, et AIX, et NetBSD, etc.).
Le code principal est en C et C + GMP. next_prime de MPU voit que le nombre est trop grand et le transmet au backend GMP (ou du code Perl pur si le backend n'est pas installé). Cela chaîne et convertit en mpz, et convertira le résultat en arrière dans le type d'objet d'entrée ou Math :: BigInt. next_prime lui-même fait:
Le test premier probable est:
Tout ce qui précède l'ES BPSW n'est qu'une optimisation, ce que nous voulons bien sûr pour next_prime. next_prime est également implémenté en Perl en utilisant le module Math :: BigInt (en core avec des backends optionnels Pari et GMP). Cela fait AES BPSW (comme Pari) mais n'est pas aussi optimisé.
J'ai réfléchi aux avantages d'une version à tamis partiel, en utilisant par exemple une gamme de 2 avantages. Je ne suis tout simplement pas sûr que ce serait vraiment mieux, car la plupart du temps, nous effectuions un tamisage inutile car l'écart était petit, et parfois pour un grand écart, nous devions le répéter plusieurs fois.
La bibliothèque implémente ECPP (y compris les certificats) afin que nous puissions exécuter une épreuve sur le résultat, mais 1200 chiffres est vraiment trop grand pour le petit ensemble par défaut de polynômes inclus (il existe une méthode pour télécharger des ensembles plus grands - les épreuves prendraient un peu moins de 15 minutes, ce qui est un peu plus rapide que l'APR-CL de Pari mais un peu plus lent que le mpz_aprcl de WraithX). Un inconvénient d'ECPP par rapport à APR-CL est qu'il a plus de variance de temps, donc il y a de fortes chances qu'il dépasse 10 secondes sur un certain nombre avant que le temps moyen n'y arrive. Avec une preuve, je pense que nous sommes limités à quelque chose dans la plage de 400 chiffres, sauf si nous autorisons les logiciels multithreads.
J'ai décidé d'essayer avec la même séquence utilisée par primo. Il a atteint 1191 chiffres, car c'est là que nous avons atteint un écart de 18138. J'ai également testé le code de primo en utilisant le dernier my_math.py. Il atteint 630 chiffres avec la séquence 10 ^ e et 641 avec sa séquence. Très impressionnant pour du code compact tout-Python sans beaucoup de pré-tests.
la source
Math::GMP
d'une manière qui ne soit pas aussi gaspilleuse avec la création / destruction de références mpz.$x = new Math::GMP(0); $x += 3 for 1..1000000
. Je posterai sur cpan quand j'aurai fini; vous serez l'un des premiers à le savoir;)