Quelle est la meilleure approche pour calculer le plus grand facteur premier d'un nombre?
Je pense que le plus efficace serait le suivant:
- Trouver le plus petit nombre premier qui se divise proprement
- Vérifiez si le résultat de la division est premier
- Sinon, trouvez le plus bas suivant
- Allez au 2.
Je fonde cette hypothèse sur le fait qu'il est plus facile de calculer les petits facteurs premiers. Est-ce à peu près correct? Quelles autres approches devrais-je examiner?
Edit: J'ai maintenant réalisé que mon approche est futile s'il y a plus de 2 facteurs premiers en jeu, puisque l'étape 2 échoue lorsque le résultat est un produit de deux autres nombres premiers, donc un algorithme récursif est nécessaire.
Modifier à nouveau: Et maintenant, j'ai réalisé que cela fonctionnait toujours, car le dernier nombre premier trouvé doit être le plus élevé, donc tout test supplémentaire du résultat non premier de l'étape 2 entraînerait un nombre premier plus petit.
la source
1.
trouver n'importe quel nombre qui divise clairement (pour i = 2 à int (sqr (num)))2.
diviser par ce nombre (num = num / i) et se répéter jusqu'à ce que rien ne soit trouvé dans l'intervalle de 1.3.
num est le plus grand facteurRéponses:
En fait, il existe plusieurs façons plus efficaces de trouver des facteurs de grand nombre (pour les plus petits, la division d'essai fonctionne raisonnablement bien).
Une méthode qui est très rapide si le nombre d'entrée a deux facteurs très proches de sa racine carrée est la factorisation de Fermat . Il utilise l'identité N = (a + b) (a - b) = a ^ 2 - b ^ 2 et est facile à comprendre et à mettre en œuvre. Malheureusement, ce n'est pas très rapide en général.
La méthode la plus connue pour factoriser des nombres jusqu'à 100 chiffres est le tamis quadratique . En prime, une partie de l'algorithme se fait facilement avec un traitement parallèle.
Un autre algorithme dont j'ai entendu parler est l'algorithme Rho de Pollard . Ce n'est pas aussi efficace que le tamis quadratique en général, mais semble être plus facile à mettre en œuvre.
Une fois que vous avez décidé de diviser un nombre en deux facteurs, voici l'algorithme le plus rapide auquel je puisse penser pour trouver le plus grand facteur premier d'un nombre:
Créez une file d'attente prioritaire qui stocke initialement le numéro lui-même. À chaque itération, vous supprimez le nombre le plus élevé de la file d'attente et essayez de le diviser en deux facteurs (ne permettant pas à 1 d'être l'un de ces facteurs, bien sûr). Si cette étape échoue, le nombre est premier et vous avez votre réponse! Sinon, vous ajoutez les deux facteurs dans la file d'attente et répétez.
la source
Voici le meilleur algorithme que je connaisse (en Python)
def prime_factors(n): """Returns all the prime factors of a positive integer""" factors = [] d = 2 while n > 1: while n % d == 0: factors.append(d) n /= d d = d + 1 return factors pfs = prime_factors(1000) largest_prime_factor = max(pfs) # The largest element in the prime factor list
La méthode ci-dessus fonctionne dans
O(n)
le pire des cas (lorsque l'entrée est un nombre premier).EDIT:
Voici la
O(sqrt(n))
version, comme suggéré dans le commentaire. Voici le code, une fois de plus.def prime_factors(n): """Returns all the prime factors of a positive integer""" factors = [] d = 2 while n > 1: while n % d == 0: factors.append(d) n /= d d = d + 1 if d*d > n: if n > 1: factors.append(n) break return factors pfs = prime_factors(1000) largest_prime_factor = max(pfs) # The largest element in the prime factor list
la source
O(sqrt(n))
le pire des cas" - Non, il court dansO(n)
le pire des cas (par exemple, quandn
est prime.)Ma réponse est basée sur celle de Triptych , mais elle s'améliore beaucoup. Elle repose sur le fait qu'au-delà de 2 et 3, tous les nombres premiers sont de la forme 6n-1 ou 6n + 1.
J'ai récemment écrit un article de blog expliquant le fonctionnement de cet algorithme.
Je dirais qu'une méthode dans laquelle il n'est pas nécessaire de tester la primalité (et pas de construction de tamis) fonctionnerait plus rapidement qu'une méthode qui les utilise. Si tel est le cas, c'est probablement l'algorithme le plus rapide ici.
la source
while (multOfSix - 1 <= n)
Code JavaScript:
Exemple d'utilisation:
Voici un exemple de code :
la source
Similaire à la réponse @Triptych mais aussi différent. Dans cet exemple, la liste ou le dictionnaire n'est pas utilisé. Le code est écrit en Ruby
def largest_prime_factor(number) i = 2 while number > 1 if number % i == 0 number /= i; else i += 1 end end return i end largest_prime_factor(600851475143) # => 6857
la source
Tous les nombres peuvent être exprimés comme le produit de nombres premiers, par exemple:
Vous pouvez les trouver en commençant simplement à 2 et en continuant simplement à diviser jusqu'à ce que le résultat ne soit pas un multiple de votre nombre:
en utilisant cette méthode, vous n'avez pas à calculer réellement de nombres premiers: ils seront tous des nombres premiers, sur la base du fait que vous avez déjà factorisé le nombre autant que possible avec tous les nombres précédents.
la source
currFactor = 3513642
, nous savons que 12345678987667 est premier et devrait le renvoyer comme réponse. Au lieu de cela, ce code continuera l'énumération jusqu'à 12345678987667 lui-même. C'est 3 513 642 fois plus lent que nécessaire.la source
while
boucle passera par desi
valeurs de2,2,2,2,2,2,2,2,2,2,2,2, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5
. Toutes les 60 itérations. Mais pour (10 ^ 12 + 39) , il y aura (10 ^ 12 + 38) itérations,i=2,3,4,5,6,...,10^12+39
. Même si 10 ^ 10 opérations prennent une seconde, 10 ^ 12 prendront 100 secondes. Mais seulement 10 ^ 6 itérations sont vraiment nécessaires, et si 10 ^ 10 opérations prennent une seconde, 10 ^ 6 prendront 1/10 000e de seconde.long n = 2*1000000000039L
? Cela fonctionne-t-il aussi vite qu'il le devrait? (aussi, pouvez-vous simplifier votre code en utilisant unereturn;
instruction?). (si vous voulez que j'arrête de vous donner un coup de coude, dites-le simplement;))La solution la plus simple est une paire de fonctions mutuellement récursives .
La première fonction génère tous les nombres premiers:
La deuxième fonction renvoie les facteurs premiers d'un nombre donné
n
dans l'ordre croissant.n
.Le plus grand facteur premier de
n
est le dernier nombre donné par la deuxième fonction.Cet algorithme nécessite une liste différée ou un langage (ou une structure de données) avec une sémantique d' appel par besoin .
Pour clarifier, voici une implémentation (inefficace) de ce qui précède dans Haskell:
import Control.Monad -- All the primes primes = 2 : filter (ap (<=) (head . primeFactors)) [3,5..] -- Gives the prime factors of its argument primeFactors = factor primes where factor [] n = [] factor xs@(p:ps) n = if p*p > n then [n] else let (d,r) = divMod n p in if r == 0 then p : factor xs d else factor ps n -- Gives the largest prime factor of its argument largestFactor = last . primeFactors
Pour accélérer cela, il suffit d'être plus intelligent pour détecter les nombres premiers et / ou les facteurs de
n
, mais l'algorithme reste le même.la source
Certains tests modulo sont superflus, car n ne peut jamais être divisé par 6 si tous les facteurs 2 et 3 ont été supprimés. Vous ne pouvez autoriser que les nombres premiers pour i, ce qui est indiqué dans plusieurs autres réponses ici.
Vous pourriez en fait entrelacer le tamis d'Eratosthène ici:
Voir aussi cette question .
la source
Je suis conscient que ce n'est pas une solution rapide. Poster comme solution lente, espérons-le plus facile à comprendre.
la source
Approche itérative Python en supprimant tous les facteurs premiers du nombre
la source
J'utilise un algorithme qui continue de diviser le nombre par son facteur premier actuel.
Ma solution en python 3:
Entrée:
10
Sortie:5
Entrée:
600851475143
Sortie:6857
la source
Voici ma tentative en c #. La dernière impression est le plus grand facteur premier du nombre. J'ai vérifié et ça marche.
la source
la source
Calcule le plus grand facteur premier d'un nombre à l'aide de la récursivité en C ++. Le fonctionnement du code est expliqué ci-dessous:
la source
Voici mon approche pour calculer rapidement le plus grand facteur premier. Il est basé sur le fait que modifié
x
ne contient pas de facteurs non premiers. Pour y parvenir, nous nous divisonsx
dès qu'un facteur est trouvé. Ensuite, la seule chose qui reste est de renvoyer le plus grand facteur. Ce serait déjà prime.Le code (Haskell):
la source
L'algorithme C ++ suivant n'est pas le meilleur, mais il fonctionne pour les nombres inférieurs à un milliard et c'est assez rapide
la source
J'ai trouvé cette solution sur le Web par "James Wang"
la source
Facteur principal utilisant un tamis:
la source
Il me semble que l'étape n ° 2 de l'algorithme donné ne sera pas une approche aussi efficace. Vous ne vous attendez pas à ce que ce soit le meilleur.
En outre, la réponse précédente suggérant le tamis d'Eratosthène est totalement fausse. Je viens d'écrire deux programmes au facteur 123456789. L'un était basé sur le tamis, l'autre était basé sur ce qui suit:
Cette version était 90 fois plus rapide que le Sieve.
Le fait est que sur les processeurs modernes, le type d'opération importe beaucoup moins que le nombre d'opérations, sans compter que l'algorithme ci-dessus peut s'exécuter en cache, le Sieve ne le peut pas. Le tamis utilise de nombreuses opérations en supprimant tous les nombres composites.
Notez également que ma division des facteurs au fur et à mesure qu'ils sont identifiés réduit l'espace qui doit être testé.
la source
Calculez d'abord une liste contenant des nombres premiers, par exemple 2 3 5 7 11 13 ...
Chaque fois que vous factorisez un nombre premier, utilisez l'implémentation de Triptych mais en itérant cette liste de nombres premiers plutôt que d'entiers naturels.
la source
Avec Java:
Pour les
int
valeurs:Pour les
long
valeurs:la source
Ce n'est probablement pas toujours plus rapide mais plus optimiste quant au fait que vous trouvez un grand diviseur premier:
N
est ton numéroreturn(N)
Sqrt(N)
N is divisible by Prime
alorsReturn(Prime)
Edit: À l'étape 3, vous pouvez utiliser le tamis d'Eratosthène ou le tamis d'Atkins ou tout ce que vous voulez, mais en lui-même, le tamis ne vous trouvera pas le plus grand facteur premier. (C'est pourquoi je ne choisirais pas le post de SQLMenace comme réponse officielle ...)
la source
Pas le plus rapide mais ça marche!
la source
Voici la même fonction @ Triptyque fournie en générateur, qui a également été légèrement simplifiée.
le max prime peut alors être trouvé en utilisant:
et une liste de facteurs trouvés en utilisant:
la source
Je pense qu'il serait bon de stocker quelque part tous les nombres premiers possibles plus petits que n et de simplement les parcourir pour trouver le plus grand diviseur. Vous pouvez obtenir des nombres premiers sur prime-numbers.org .
Bien sûr, je suppose que votre nombre n'est pas trop grand :)
la source
la source