Algorithme pour trouver le plus grand facteur premier d'un nombre

185

Quelle est la meilleure approche pour calculer le plus grand facteur premier d'un nombre?

Je pense que le plus efficace serait le suivant:

  1. Trouver le plus petit nombre premier qui se divise proprement
  2. Vérifiez si le résultat de la division est premier
  3. Sinon, trouvez le plus bas suivant
  4. 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.

mercutio
la source
Mon approche était: (1) diviser un grand nombre possible par 2; (2) vérifier si le grand nombre se divise uniformément en lui; (3) si oui, vérifiez si le nombre divisé par 2 est premier. Si c'est le cas, renvoyez-le. (4) Sinon, soustrayez 1 du nombre divisé par 2 et revenez à l'étape 3.
Kevin Meredith
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 facteur
user3819867
1
Nous pouvons diviser avec de petits nombres premiers, et celui qui reste finalement est le plus grand facteur premier (je suppose)

Réponses:

134

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.

Artelius
la source
3
Pollard rho et la méthode de la courbe elliptique sont bien meilleures pour se débarrasser des petits facteurs premiers de votre nombre que le tamis quadratique. QS a à peu près le même temps d'exécution, quel que soit le nombre. L'approche la plus rapide dépend de votre numéro; QS craquera plus rapidement les nombres difficiles à factoriser tandis que rho et ECM casseront plus rapidement les nombres faciles à factoriser.
tmyklebu le
Merci pour la suggestion de variation quadratique. J'avais besoin de l'implémenter pour l'un de mes clients, la version initiale que j'ai proposée ressemblait à ce que @mercutio suggérait dans sa question. La solution quadratique est ce qui alimente maintenant l'outil de mon client à math.tools/calculator/prime-factors .
dors
S'il existe un moyen efficace de résoudre ce problème, cela ne signifie-t-il pas que le cryptage Web n'est pas sécurisé?
BKSpurgeon
141

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
Triptyque
la source
11
Veuillez lire et / ou exécuter ce code avant de le rejeter. Ça fonctionne bien. Copiez et collez simplement. Comme écrit prime_factors (1000) renverra [2,2,2,5,5,5], ce qui devrait être interprété comme 2 ^ 3 * 5 ^ 3, c'est-à-dire la factorisation première.
Triptyque
11
"court dans O(sqrt(n))le pire des cas" - Non, il court dans O(n)le pire des cas (par exemple, quand nest prime.)
Sheldon L. Cooper
16
Facile à rendre O (sqrt (n)), vous arrêtez simplement la boucle lorsque d * d> n, et si n> 1 à ce stade, sa valeur doit être ajoutée à la liste des facteurs premiers.
Sumudu Fernando
5
Y a-t-il un nom pour cela?
Forethinker
11
puisque 2 est le seul nombre premier pair, donc au lieu d'ajouter 1 à chaque fois, vous pouvez itérer séparément pour d = 2 puis l'incrémenter de 1, puis à partir de d = 3, vous pouvez incrémenter de 2. donc cela diminuera le nombre des itérations ... :)
tailor_raj
18

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.

var largestPrimeFactor;
if(n mod 2 == 0)
{
    largestPrimeFactor = 2;
    n = n / 2 while(n mod 2 == 0);
}
if(n mod 3 == 0)
{
    largestPrimeFactor = 3;
    n = n / 3 while(n mod 3 == 0);
}

multOfSix = 6;
while(multOfSix - 1 <= n)
{
    if(n mod (multOfSix - 1) == 0)
    {
        largestPrimeFactor = multOfSix - 1;
        n = n / largestPrimeFactor while(n mod largestPrimeFactor == 0);
    }

    if(n mod (multOfSix + 1) == 0)
    {
        largestPrimeFactor = multOfSix + 1;
        n = n / largestPrimeFactor while(n mod largestPrimeFactor == 0);
    }
    multOfSix += 6;
}

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.

sundar - Réintégrer Monica
la source
12
Vous pouvez en fait pousser cette idée encore plus loin, par exemple au-delà de 2,3,5 tous les nombres premiers sont de la forme 30n + k (n> = 0) où k ne prend que les valeurs comprises entre 1 et 29 qui ne sont pas divisibles par 2,3 ou 5, c'est-à-dire 7,11,13,17,19,23,29. Vous pouvez même faire en sorte que cela s'adapte dynamiquement après tous les quelques nombres premiers que vous avez trouvés jusqu'à présent à 2 * 3 * 5 * 7 * ... * n + k où k ne doit pas être divisible par l'un de ces nombres premiers (notez que tous les k possibles n'ont pas besoin être premier, par exemple pour 210n + k, vous devez inclure 121, sinon vous manqueriez 331 )
Tobias Kienzler
2
Je suppose que ça devrait êtrewhile (multOfSix - 1 <= n)
Nader Ghanbari
8

Code JavaScript:

'option strict';

function largestPrimeFactor(val, divisor = 2) { 
    let square = (val) => Math.pow(val, 2);

    while ((val % divisor) != 0 && square(divisor) <= val) {
        divisor++;
    }

    return square(divisor) <= val
        ? largestPrimeFactor(val / divisor, divisor)
        : val;
}

Exemple d'utilisation:

let result = largestPrimeFactor(600851475143);

Voici un exemple de code :

Vlad Bezden
la source
7

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
Ugnius Malūkas
la source
Enfin quelque chose de lisible et instantanément (en js) exécutable en même temps. J'essayais d'utiliser la liste principale infinie et c'était déjà trop lent sur 1 million.
Ebuall
4

Tous les nombres peuvent être exprimés comme le produit de nombres premiers, par exemple:

102 = 2 x 3 x 17
712 = 2 x 2 x 2 x 89

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:

712 / 2 = 356 .. 356 / 2 = 178 .. 178 / 2 = 89 .. 89 / 89 = 1

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.

number = 712;
currNum = number;    // the value we'll actually be working with
for (currFactor in 2 .. number) {
    while (currNum % currFactor == 0) {
        // keep on dividing by this number until we can divide no more!
        currNum = currNum / currFactor     // reduce the currNum
    }
    if (currNum == 1) return currFactor;    // once it hits 1, we're done.
}
nickf
la source
Oui, mais c'est terriblement inefficace. Une fois que vous avez divisé tous les 2, vous ne devriez vraiment pas essayer de diviser par 4, ou par 6, ou ...; Il est vraiment beaucoup plus efficace à la limite de ne vérifier que les nombres premiers ou d'utiliser un algorithme complémentaire.
wnoise
6
+1 pour compenser wnoise, qui je pense est faux. Essayer de diviser par 4 ne se produira qu'une seule fois et échouera immédiatement. Je ne pense pas que ce soit pire que de supprimer 4 d'une liste de candidats, et c'est certainement plus rapide que de trouver tous les nombres premiers à l'avance.
Triptyque
2
@Beowulf. Essayez d'exécuter ce code avant de voter contre. Il renvoie des facteurs premiers; vous ne comprenez tout simplement pas l'algorithme.
Triptyque
3
le code fonctionne bien, mais est lent si le nombre entrant est un nombre premier. Je ne courrais que jusqu'au carré et augmenterais de 2. Cela pourrait être trop lent pour de très grands nombres, cependant.
blabla999
4
blabla999 a tout à fait raison. L'exemple est 1234567898766700 = 2 * 2 * 5 * 5 * 12345678987667. Lorsque nous avons atteint 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.
Will Ness
4
    //this method skips unnecessary trial divisions and makes 
    //trial division more feasible for finding large primes

    public static void main(String[] args) 
    {
        long n= 1000000000039L; //this is a large prime number 
        long i = 2L;
        int test = 0;

        while (n > 1)
        {
            while (n % i == 0)
            {
                n /= i;     
            }

            i++;

            if(i*i > n && n > 1) 
            {
                System.out.println(n); //prints n if it's prime
                test = 1;
                break;
            }
        }

        if (test == 0)  
            System.out.println(i-1); //prints n if it's the largest prime factor
    }
le_prole
la source
1
avez-vous essayé votre code avec 1 000 000 000 039? il devrait également fonctionner en un clin d'œil. Le fait-il?
Will Ness le
2
Vous pouvez le savoir à l'avance, sans essayer. 10 ^ 12 = (2 * 5) ^ 12 = 2 ^ 12 * 5 ^ 12. Ainsi, votre whileboucle passera par des ivaleurs de 2,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.
Will Ness le
1
Parce que je ne savais pas que (10 ^ 12 + 39) était un nombre premier, ce que je fais maintenant. Je comprends exactement ce que vous dites.
the_prole
1
OK, donc vous pouvez changer votre code pour qu'il n'y ait pas un si gros ralentissement pour les nombres premiers: si n = a b et a <= b, alors a a <= b a = n, c'est-à-dire a a <= n . Et si nous avons atteint a + 1, alors n est sûrement un nombre premier. (envoyez-moi un ping si vous modifiez votre réponse pour l'incorporer).
Will Ness le
1
que se passe-t-il quand long n = 2*1000000000039L? Cela fonctionne-t-il aussi vite qu'il le devrait? (aussi, pouvez-vous simplifier votre code en utilisant une return;instruction?). (si vous voulez que j'arrête de vous donner un coup de coude, dites-le simplement;))
Will Ness
4

La solution la plus simple est une paire de fonctions mutuellement récursives .

La première fonction génère tous les nombres premiers:

  1. Commencez par une liste de tous les nombres naturels supérieurs à 1.
  2. Supprimez tous les nombres qui ne sont pas premiers. Autrement dit, les nombres qui n'ont pas de facteurs premiers (autres qu'eux-mêmes). Voir ci-dessous.

La deuxième fonction renvoie les facteurs premiers d'un nombre donné ndans l'ordre croissant.

  1. Prenez une liste de tous les nombres premiers (voir ci-dessus).
  2. Supprimez tous les nombres qui ne sont pas des facteurs de n.

Le plus grand facteur premier de nest 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.

Apocalisp
la source
2
n = abs(number);
result = 1;
if (n mod 2 == 0) {
  result = 2;
  while (n mod 2 = 0) n /= 2;
}
for(i=3; i<sqrt(n); i+=2) {
  if (n mod i == 0) {
    result = i;
    while (n mod i = 0)  n /= i;
  }
}
return max(n,result)

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:

  • Créez d'abord la liste d'entiers jusqu'à sqrt (n).
  • Dans la boucle for, marquez tous les multiples de i jusqu'au nouveau sqrt (n) comme non premiers et utilisez une boucle while à la place.
  • mettre i au nombre premier suivant de la liste.

Voir aussi cette question .

Ralph M. Rickenbach
la source
2

Je suis conscient que ce n'est pas une solution rapide. Poster comme solution lente, espérons-le plus facile à comprendre.

 public static long largestPrimeFactor(long n) {

        // largest composite factor must be smaller than sqrt
        long sqrt = (long)Math.ceil(Math.sqrt((double)n));

        long largest = -1;

        for(long i = 2; i <= sqrt; i++) {
            if(n % i == 0) {
                long test = largestPrimeFactor(n/i);
                if(test > largest) {
                    largest = test;
                }
            }
        }

        if(largest != -1) {
            return largest;
        }

        // number is prime
        return n;
    } 
thejosh
la source
1

Approche itérative Python en supprimant tous les facteurs premiers du nombre

def primef(n):
    if n <= 3:
        return n
    if n % 2 == 0:
        return primef(n/2)
    elif n % 3 ==0:
        return primef(n/3)
    else:
        for i in range(5, int((n)**0.5) + 1, 6):
            #print i
            if n % i == 0:
                return primef(n/i)
            if n % (i + 2) == 0:
                return primef(n/(i+2))
    return n
Jyothir Aditya Singh
la source
1

J'utilise un algorithme qui continue de diviser le nombre par son facteur premier actuel.

Ma solution en python 3:

def PrimeFactor(n):
    m = n
    while n%2==0:
        n = n//2
    if n == 1:         # check if only 2 is largest Prime Factor 
        return 2
    i = 3
    sqrt = int(m**(0.5))  # loop till square root of number
    last = 0              # to store last prime Factor i.e. Largest Prime Factor
    while i <= sqrt :
        while n%i == 0:
            n = n//i       # reduce the number by dividing it by it's Prime Factor
            last = i
        i+=2
    if n> last:            # the remaining number(n) is also Factor of number 
        return n
    else:
        return last
print(PrimeFactor(int(input()))) 

Entrée: 10 Sortie:5

Entrée: 600851475143 Sortie:6857

Kalpesh Dusane
la source
0

Voici ma tentative en c #. La dernière impression est le plus grand facteur premier du nombre. J'ai vérifié et ça marche.

namespace Problem_Prime
{
  class Program
  {
    static void Main(string[] args)
    {
      /*
       The prime factors of 13195 are 5, 7, 13 and 29.

      What is the largest prime factor of the number 600851475143 ?
       */
      long x = 600851475143;
      long y = 2;
      while (y < x)
      {
        if (x % y == 0)
        {
          // y is a factor of x, but is it prime
          if (IsPrime(y))
          {
            Console.WriteLine(y);
          }
          x /= y;
        }

        y++;

      }
      Console.WriteLine(y);
      Console.ReadLine();
    }
    static bool IsPrime(long number)
    {
      //check for evenness
      if (number % 2 == 0)
      {
        if (number == 2)
        {
          return true;
        }
        return false;
      }
      //don't need to check past the square root
      long max = (long)Math.Sqrt(number);
      for (int i = 3; i <= max; i += 2)
      {
        if ((number % i) == 0)
        {
          return false;
        }
      }
      return true;
    }

  }
}
Seamus Barrett
la source
0
#python implementation
import math
n = 600851475143
i = 2
factors=set([])
while i<math.sqrt(n):
   while n%i==0:
       n=n/i
       factors.add(i)
   i+=1
factors.add(n)
largest=max(factors)
print factors
print largest
Rishabh Prasad
la source
1
25 est le plus grand facteur premier de 25?
Will Ness
0

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:

int getLargestPrime(int number) {
    int factor = number; // assumes that the largest prime factor is the number itself
    for (int i = 2; (i*i) <= number; i++) { // iterates to the square root of the number till it finds the first(smallest) factor
        if (number % i == 0) { // checks if the current number(i) is a factor
            factor = max(i, number / i); // stores the larger number among the factors
            break; // breaks the loop on when a factor is found
        }
    }
    if (factor == number) // base case of recursion
        return number;
    return getLargestPrime(factor); // recursively calls itself
}
4aRk Kn1gh7
la source
0

Voici mon approche pour calculer rapidement le plus grand facteur premier. Il est basé sur le fait que modifié xne contient pas de facteurs non premiers. Pour y parvenir, nous nous divisons xdè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):

f max' x i | i > x = max'
           | x `rem` i == 0 = f i (x `div` i) i  -- Divide x by its factor
           | otherwise = f max' x (i + 1)  -- Check for the next possible factor

g x = f 2 x 2
Penkovsky
la source
mais cela n'essaiera-t-il pas de diviser aussi avec tous les nombres pairs?
Janus Troelsen
0

L'algorithme C ++ suivant n'est pas le meilleur, mais il fonctionne pour les nombres inférieurs à un milliard et c'est assez rapide

#include <iostream>
using namespace std;

// ------ is_prime ------
// Determines if the integer accepted is prime or not
bool is_prime(int n){
    int i,count=0;
    if(n==1 || n==2)
      return true;
    if(n%2==0)
      return false;
    for(i=1;i<=n;i++){
    if(n%i==0)
        count++;
    }
    if(count==2)
      return true;
    else
      return false;
 }
 // ------ nextPrime -------
 // Finds and returns the next prime number
 int nextPrime(int prime){
     bool a = false;
     while (a == false){
         prime++;
         if (is_prime(prime))
            a = true;
     }
  return prime;
 }
 // ----- M A I N ------
 int main(){

      int value = 13195;
      int prime = 2;
      bool done = false;

      while (done == false){
          if (value%prime == 0){
             value = value/prime;
             if (is_prime(value)){
                 done = true;
             }
          } else {
             prime = nextPrime(prime);
          }
      }
        cout << "Largest prime factor: " << value << endl;
 }
sn
la source
0

J'ai trouvé cette solution sur le Web par "James Wang"

public static int getLargestPrime( int number) {

    if (number <= 1) return -1;

    for (int i = number - 1; i > 1; i--) {
        if (number % i == 0) {
            number = i;
        }
    }
    return number;
}
BabarBaig
la source
0

Facteur principal utilisant un tamis:

#include <bits/stdc++.h>
using namespace std;
#define N 10001  
typedef long long ll;
bool visit[N];
vector<int> prime;

void sieve()
{
            memset( visit , 0 , sizeof(visit));
            for( int i=2;i<N;i++ )
            {
                if( visit[i] == 0)
                {
                    prime.push_back(i);
                    for( int j=i*2; j<N; j=j+i )
                    {
                        visit[j] = 1;
                    }
                }
            }   
}
void sol(long long n, vector<int>&prime)
{
            ll ans = n;
            for(int i=0; i<prime.size() || prime[i]>n; i++)
            {
                while(n%prime[i]==0)
                {
                    n=n/prime[i];
                    ans = prime[i];
                }
            }
            ans = max(ans, n);
            cout<<ans<<endl;
}
int main() 
{
           ll tc, n;
           sieve();

           cin>>n;
           sol(n, prime);

           return 0;
}
éruptions cutanées
la source
-1

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:

1)  Test = 2 
2)  Current = Number to test 
3)  If Current Mod Test = 0 then  
3a)     Current = Current Div Test 
3b)     Largest = Test
3c)     Goto 3. 
4)  Inc(Test) 
5)  If Current < Test goto 4
6)  Return Largest

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é.

Loren Pechtel
la source
c'est ce que j'ai dit, mais j'ai été rejeté: (Je suppose que le problème est que si le nombre a un facteur premier très important (comme lui-même), alors cette méthode doit boucler jusqu'à ce nombre. Dans de nombreux cas cependant, cette méthode est assez efficace.
nickf
En relisant le vôtre, c'est la même chose mais la première partie de la vôtre est déroutante.
Loren Pechtel
Essayez cela sur ce numéro 143816789988504044536402352738195137863656439, faites-moi savoir à quel point c'est efficace ...
MichaelICE
-1

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.

guoger
la source
-1

Avec Java:

Pour les intvaleurs:

public static int[] primeFactors(int value) {
    int[] a = new int[31];
    int i = 0, j;
    int num = value;
    while (num % 2 == 0) {
        a[i++] = 2;
        num /= 2;
    }
    j = 3;
    while (j <= Math.sqrt(num) + 1) {
        if (num % j == 0) {
            a[i++] = j;
            num /= j;
        } else {
            j += 2;
        }
    }
    if (num > 1) {
        a[i++] = num;
    }
    int[] b = Arrays.copyOf(a, i);
    return b;
}

Pour les longvaleurs:

static long[] getFactors(long value) {
    long[] a = new long[63];
    int i = 0;
    long num = value;
    while (num % 2 == 0) {
        a[i++] = 2;
        num /= 2;
    }
    long j = 3;
    while (j <= Math.sqrt(num) + 1) {
        if (num % j == 0) {
            a[i++] = j;
            num /= j;
        } else {
            j += 2;
        }
    }
    if (num > 1) {
        a[i++] = num;
    }
    long[] b = Arrays.copyOf(a, i);
    return b;
}
Paul Vargas
la source
-2

Ce n'est probablement pas toujours plus rapide mais plus optimiste quant au fait que vous trouvez un grand diviseur premier:

  1. N est ton numéro
  2. Si c'est le meilleur alors return(N)
  3. Calculer les nombres premiers jusqu'à Sqrt(N)
  4. Parcourez les nombres premiers par ordre décroissant (le plus grand en premier)
    • Si N is divisible by PrimealorsReturn(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 ...)

palotasb
la source
1
N'avez-vous pas besoin de faire l'essai d'affacturage pour déterminer s'il s'agit d'un nombre premier (étape 2)? Envisagez également de trouver le plus grand facteur premier de 15. Les nombres premiers jusqu'à sqrt (15) sont 2 et 3; mais le plus grand facteur premier est 5, n'est-ce pas? De même avec 20.
Jonathan Leffler
-3

Pas le plus rapide mais ça marche!

    static bool IsPrime(long num)
    {
        long checkUpTo = (long)Math.Ceiling(Math.Sqrt(num));
        for (long i = 2; i <= checkUpTo; i++)
        {
            if (num % i == 0)
                return false;
        }
        return true;
    }
pseudo
la source
Ce n'est pas une réponse à la question. ;-) La question était de trouver le plus grand facteur premier, pas de vérifier la primalité.
Hans-Peter Störr
Il est beaucoup plus efficace d'initialiser votre boucle comme (long i = 3; i <checkUpTo; i + = 2)
cjk
-3

Voici la même fonction @ Triptyque fournie en générateur, qui a également été légèrement simplifiée.

def primes(n):
    d = 2
    while (n > 1):
        while (n%d==0):
            yield d
            n /= d
        d += 1

le max prime peut alors être trouvé en utilisant:

n= 373764623
max(primes(n))

et une liste de facteurs trouvés en utilisant:

list(primes(n))
Pedram
la source
-4

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 :)

Klesk
la source
-6
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include <time.h>

factor(long int n)
{
long int i,j;
while(n>=4)
 {
if(n%2==0) {  n=n/2;   i=2;   }

 else
 { i=3;
j=0;
  while(j==0)
  {
   if(n%i==0)
   {j=1;
   n=n/i;
   }
   i=i+2;
  }
 i-=2;
 }
 }
return i;
 }

 void main()
 { 
  clock_t start = clock();
  long int n,sp;
  clrscr();
  printf("enter value of n");
  scanf("%ld",&n);
  sp=factor(n);
  printf("largest prime factor is %ld",sp);

  printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC);
  getch();
 }
Chitransh
la source