Comment puis-je test de primalité?
Je suis en train d'écrire une petite bibliothèque avec un certain nombre de méthodes connexes. Comme je l'ai fait le travail de base (aka méthodes de travail) et maintenant je suis à la recherche pour certains d'optimisation.
Bien sûr, l'internet est un excellent endroit pour le faire. J'ai, cependant, suis tombé sur un problème d'arrondi et je me demandais comment résoudre ce problème.
Dans la boucle j'utilise pour tester un certain nombre de c'est de primalité il est plus efficace de chercher jusqu'à ce sqrt(n) au lieu de n/2 ou n - 1. Mais en raison de l'arrondissement des problèmes un certain nombre obtenir sauté et donc certains nombres premiers sont ignorés! Par exemple, le 10000th premier devrait être: 104729, mais le "optimisé" version se termine par: 103811.
Du code (il est ouvert pour plus d'optimisation, je sais, mais je peut gérer qu'une seule chose à la fois):
///<summary>
///Method for testing the primality of a number e.g.: return IsPrime(29);
///History:
///1. Initial version, most basic form of testing: m smaller then n -1
///2. Implemented m smaller then sqrt(n), optimization due to prime factoring
///</summary>
///<param name="test">Number to be tested on primality</param>
///<returns>True if the number is prime, false otherwise</returns>
public static bool IsPrime(int test)
{
//0 and 1 are not prime numbers
if (test == 0 || test == 1) return false;
//2 and 3 are prime numbers
if (test == 2) return true;
//all even numbers, save 2, are not prime
if (test % 2 == 0) return false;
double squared = Math.Sqrt(test);
int flooredAndSquared = Convert.ToInt32(Math.Floor(squared));
//start with 5, make increments of 2, even numbers do not need to be tested
for (int idx = 3; idx < flooredAndSquared; idx++)
{
if (test % idx == 0)
{
return false;
}
}
return true;
}
Je sais que le carré de la partie d'échec de moi (ou j'échoue), a essayé de Mathématiques.Plafond ainsi, avec les mêmes résultats.
Cette question semble être hors-sujet, car il est à propos de la théorie des nombres. essayez math.stackexchange.com.
squared
n'est pas le bon nom de variable pour le résultat d'une racine carrée. "Au carré" signifie élevé à la seconde puissance; racine carrée est élever à la 1/2 de la puissance. Peut-être l'appeler sqrt_test
ou quelque chose.OriginalL'auteur Oxymoron | 2009-03-09
Vous devez vous connecter pour publier un commentaire.
Malheureusement, je n'ai pas essayé les approches algorithmiques avant. Mais si vous voulez mettre en oeuvre votre approche efficace, je vous suggère de faire quelques mise en cache. Créer un tableau pour stocker tous les nombres premiers inférieurs à un seuil défini, remplir ce tableau, et de chercher à l'intérieur/à l'aide d'.
Dans l'exemple suivant, déterminer si un nombre est premier est O(1) dans le meilleur des cas (à savoir, lorsque le nombre est inférieur ou égal à
maxPrime
, qui est 821,461 pour un 64 ko de mémoire tampon), et est optimisé pour les autres cas (en cochant mod plus de 64 ko de numéros de la première de 820 000 -- 8% environ).(Note: Ne pas prendre cette réponse comme "optimal". C'est plus d'un exemple sur la manière d'optimiser votre mise en œuvre.)
OriginalL'auteur Hosam Aly
Je suppose que c'est votre problème:
Cela devrait être
si vous n'obtenez pas de chiffres dans un carré comme les nombres premiers. Aussi, vous pouvez utiliser "idx += 2" au lieu de "idx++" parce que vous n'avez qu'à tester les nombres impairs (comme vous l'avez écrit dans le commentaire directement au-dessus...).
OriginalL'auteur schnaader
Je ne sais pas si c'est tout à fait ce que vous cherchez, mais si vous êtes vraiment préoccupé par la vitesse, alors vous devriez regarder dans probabiliste des méthodes de test de primalité plutôt qu'à l'aide d'un tamis. Rabin-Miller est un test de primalité probabiliste utilisé par Mathematica.
OriginalL'auteur Mark Lavin
J'ai posté une classe qui utilise un tamis ou d'Eratosthène pour calculer les nombres premiers ici:
Est la taille d'un tableau contraint par la limite supérieure de type int (2147483647)?
Pas du tout, regardez le code. Il élargit la gamme de mesures, de sorte qu'il est seulement limitée par la capacty du type de données utilisé pour stocker les nombres premiers. Dans ce cas, un long, donc la limite est 9223372036854775807.
Pas du tout: vous pouvez créer une liste de listes de tamis approximations, et de prendre "autant que nécessaire". Vous aurez besoin d'évaluation différée bien sûr, comme dans un langage fonctionnel. J'ai écrit une mise en œuvre de cette en C# à l'aide de rendement des déclarations qui, autant que je sache, a bien fonctionné. N'ont pas de portable avec moi, si je dois revenir plus tard sur ce post la réponse exacte. (Si vous voulez.)
OriginalL'auteur Guffa
Comme dit Mark, de Miller-Rabin test est effectivement une très bonne façon d'aller. Une référence supplémentaire (pseudo-code) est le Article de Wikipedia à ce sujet.
Il convient de noter que, même si elle est probabiliste, en testant seulement un très petit nombre de cas, vous pouvez déterminer si un nombre est premier pour les nombres dans l'int (et près de long). Voir cette partie de l'article de Wikipédia, ou la Primalité de Prouver référence pour plus de détails.
Je vous recommande également la lecture de cet article sur l'exponentiation modulaire, car sinon, vous allez être face à de très grands nombres lorsque l'on essaie de Miller-Rabin test...
OriginalL'auteur Ant
Vous voudrez peut-être regarder dans Le petit théorème de Fermat.
Voici le pseudo-code de la livre Les algorithmes par S. Dasgupta, C. H. Papadimitriou, et U. V. Vazirani, où n est le nombre de test de primalité.
La mise en œuvre de Fermat devrait être plus rapide, puis le tamis de la solution. Cependant, il y a des nombres de Carmichael qui passent de Fermat test et ne sont PAS le premier. Il existe des solutions de contournement pour ce. Je vous recommande de consulter La Section 1.3 dans le ci-dessus mentionnée livre. Il est tout au sujet des tests de primalité et pourrait être utile pour vous.
Oui, absolument, mais il est assez rapide pour que vous pouvez le faire. J'ai édité la réponse à mentionner Carmichael.
Soloway-Strassen et de Miller-Rabin test de primalité sont à la fois supérieur à Petit Théorème de Fermat, dans tous les sens; les deux peuvent être trivialement étendu à déterministe (et pas seulement probabiliste), les tests, même si d'exécution n'est pas optimal. Ne vous embêtez pas à la FLT.
votre techniquement correcte, mais j'ai fait monter FLT car c'est la base de Miller-Rabin. Le livre que j'ai lié continue à expliquer la faiblesse de la FLT et puis le développer dans de Miller-Rabin. Je n'ai pas vu la Marque posté à propos de Miller-Rabin jusqu'à ce que après que j'ai posté cette réponse.
Qu'est-ce que
n
(en minuscules) et qu'est-ce queN
(en majuscules)?OriginalL'auteur James McMahon
...
Ive a utilisé ce à quelques reprises.. Pas aussi rapidement comme un tamis.. mais ça marche.
i < Math.Ceiling
(oui <= Math.Floor
) est suffisant. Vous n'avez pas besoini <= Math.Ceiling
.OriginalL'auteur Inisheer
Ici est à mi-chemin décent fonction que j'ai écrit pour résoudre l'un de la droite d'Euler:
Bonne prise @schnaader, merci
Point de pris, j'ai ajusté de retour à ma réponse originale à cette question.
désolé, le <= peut-être encore nécessaire si l'sqrt arrive à revenir un peu "moins" alors nécessaire (comme, n = 9, sqrt(n) == 2.99999999, plancher -> 2, algo pense que c'est le premier... j'ai été un peu mélangé. désolé
OriginalL'auteur Chris Ballance
J'ai un algorithme rapide pour le contrôle de nombres premiers. Vous pouvez améliorer votre algorithme si vous savez que les nombres premiers sont de la forme 6k ± 1, à l'exception de 2 et 3. Alors, tout d'abord, vous pouvez vérifier si l'entrée est divisible par 2 ou 3. Ensuite, vérifier tous les nombres de la forme 6k ± 1 ≤ √entrée.
OriginalL'auteur Vahid
Essayer le crible d'eratosthène -- qui devrait sortir l'obtention de la racine et de la virgule flottante questions.
Comme pour le
floor
, vous serez mieux servis par l'ceiling
.Pas si vous prenez vers le plafond.
OriginalL'auteur dirkgently
Je n'arrive pas à faire plus vite...
OriginalL'auteur Milan
J'ai pensé Nombres premiers et les tests de primalité de l'utilité et de l'algorithme AKS semble intéressante même si elle n'est pas particulièrement pratique par rapport à un probabily en fonction des tests.
OriginalL'auteur
Cela fonctionne très rapide pour tester les nombres premiers (vb.net)
OriginalL'auteur Charles Okwuagwu
Au cas où quelqu'un d'autre est intéressé, voici ma conversion de Mohammad de la procédure ci-dessus pour VBA. J'ai ajouté une case à exclure 1, 0 et les nombres négatifs car ils sont tous définis comme des pas premier.
Je ne l'ai testé cela dans Excel VBA:
OriginalL'auteur Greg Lovern
Votre pour la boucle devrait ressembler à ceci:
De cette façon, vous évitez le calcul en virgule flottante. Doit courir plus vite et ce sera plus précis. C'est pourquoi le
for
instruction conditionnelle est tout simplement une expression booléenne: il fait des choses comme cela possible.idx * idx
peuvent déborder, et de produire des valeurs négatives, ce qui provoque une boucle infinie. Envisagertest
= 2147483647 etidx
= 46340 et 46341.OriginalL'auteur Samir Talwar