Algoritmo per trovare il fattore primo più grande di un numero


183

Qual è l'approccio migliore per calcolare il fattore primo più grande di un numero?

Sto pensando che il più efficiente sarebbe il seguente:

  1. Trova il numero primo più basso che si divide in modo pulito
  2. Controlla se il risultato della divisione è primo
  3. In caso contrario, trova il successivo più basso
  4. Vai a 2.

Sto basando questo presupposto sul fatto che sia più facile calcolare i piccoli fattori primi. È giusto? Quali altri approcci dovrei esaminare?

Modifica: ora ho capito che il mio approccio è inutile se ci sono più di 2 fattori primi in gioco, poiché il passaggio 2 fallisce quando il risultato è un prodotto di altri due numeri primi, quindi è necessario un algoritmo ricorsivo.

Modifica di nuovo: e ora mi sono reso conto che funziona ancora, perché l'ultimo numero primo trovato deve essere il più alto, quindi ogni ulteriore verifica del risultato non primo dal passaggio 2 comporterebbe un numero primo più piccolo.


Il mio approccio era: (1) dividere il numero grande, possibile per 2; (2) controlla se il numero grande si divide uniformemente in esso; (3) in tal caso, verificare se il numero diviso per 2 è primo. Se lo è, restituirlo. (4) Altrimenti, sottrai 1 dal numero diviso per 2, tornando al passaggio 3.
Kevin Meredith,

1.trovare qualsiasi numero che divide chiaramente (per i = 2 a int (sqr (num))) 2.dividere per il numero (num = num / i) e ricorrono fino a che nulla si trova in 1. 's intervallo 3. num è il fattore più grande
user3819867

1
Possiamo dividere con piccoli numeri primi, e quello che è finalmente rimasto, è il più grande fattore primo (immagino)

Risposte:


134

In realtà ci sono molti modi più efficienti per trovare fattori di grandi numeri (per quelli più piccoli la divisione di prova funziona abbastanza bene).

Un metodo che è molto veloce se il numero di input ha due fattori molto vicini alla sua radice quadrata è noto come fattorizzazione Fermat . Fa uso dell'identità N = (a + b) (a - b) = a ^ 2 - b ^ 2 ed è facile da capire e implementare. Purtroppo non è molto veloce in generale.

Il metodo più noto per i numeri di factoring lunghi fino a 100 cifre è il setaccio quadratico . Come bonus, parte dell'algoritmo viene facilmente eseguita con l'elaborazione parallela.

Ancora un altro algoritmo di cui ho sentito parlare è l'algoritmo Rho di Pollard . Non è efficiente come il setaccio quadratico in generale, ma sembra essere più facile da implementare.


Dopo aver deciso come dividere un numero in due fattori, ecco l'algoritmo più veloce che mi viene in mente di trovare il fattore primo più grande di un numero:

Creare una coda prioritaria che inizialmente memorizza il numero stesso. Ad ogni iterazione, rimuovi il numero più alto dalla coda e provi a dividerlo in due fattori (non permettendo a 1 di essere uno di quei fattori, ovviamente). Se questo passaggio fallisce, il numero è primo e hai la tua risposta! Altrimenti aggiungi i due fattori nella coda e ripeti.


3
Pollard rho e il metodo della curva ellittica sono molto migliori nel liberarsi di piccoli fattori primi del numero rispetto al setaccio quadratico. QS ha circa lo stesso tempo di esecuzione, indipendentemente dal numero. Quale approccio è più veloce dipende dal tuo numero; Il QS decifrerà più rapidamente i numeri difficili da fatturare mentre rho ed ECM decifreranno più velocemente i numeri facili da fatturare.
tmyklebu,

Grazie per il suggerimento di variazione quadratica. Avevo bisogno di implementarlo per uno dei miei clienti, la versione iniziale che mi è venuta in mente era qualcosa in linea con quanto suggerito da @mercutio nella sua domanda. La soluzione quadratica è ciò che sta alimentando lo strumento del mio cliente ora su math.tools/calculator/prime-factors .
Dors

Se esiste un modo efficace per risolvere questo problema, ciò non significa che la crittografia Web non è sicura?
BKSpurgeon,

141

Ecco il miglior algoritmo che conosco (in 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

Il metodo sopra riportato viene eseguito nel O(n)caso peggiore (quando l'input è un numero primo).

EDIT: di
seguito è la O(sqrt(n))versione, come suggerito nel commento. Ecco il codice, ancora una volta.

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

11
Si prega di leggere e / o eseguire questo codice prima di votarlo. Funziona bene Basta copiare e incollare. Come scritto prime_factors (1000) restituirà [2,2,2,5,5,5], che dovrebbe essere interpretato come 2 ^ 3 * 5 ^ 3, ovvero la fattorizzazione in prime.
Trittico

11
"corre nel O(sqrt(n))peggiore dei casi" - No, si verifica nel O(n)peggiore dei casi (ad esempio, quando nè primo.)
Sheldon L. Cooper,

16
Facile renderlo O (sqrt (n)), basta interrompere il ciclo quando d * d> n, e se n> 1 a questo punto, il suo valore dovrebbe essere aggiunto all'elenco dei fattori primi.
Sumudu Fernando,

5
C'è un nome per questo?
Pensatore

11
poiché 2 è l'unico numero primo pari, quindi invece di aggiungere 1 ogni volta, è possibile iterare separatamente per d = 2 e quindi incrementarlo di 1 e quindi da d = 3 in poi è possibile aumentare di 2. in modo da ridurre il numero di iterazioni ... :)
tailor_raj

18

La mia risposta si basa su quella di Triptych , ma migliora molto su di essa. Si basa sul fatto che oltre 2 e 3, tutti i numeri primi sono nella forma 6n-1 o 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;
}

Di recente ho scritto un articolo sul blog che spiega come funziona questo algoritmo.

Mi azzarderei a pensare che un metodo in cui non è necessario un test per la primalità (e nessuna costruzione di setacci) sarebbe più veloce di quello che li utilizza. In tal caso, questo è probabilmente l'algoritmo più veloce qui.


12
Puoi effettivamente prendere questa idea ancora di più, ad esempio oltre 2,3,5 tutti i numeri primi sono della forma 30n + k (n> = 0) dove k prende solo quei valori tra 1 e 29 che non sono divisibili per 2,3 o 5, cioè 7,11,13,17,19,23,29. Puoi persino fare in modo che questo si adatti in modo dinamico dopo ogni numero primo che hai trovato finora a 2 * 3 * 5 * 7 * ... * n + k dove k non deve essere divisibile per nessuno di questi numeri primi (nota che non tutti i k possibili sii primo, ad es. per 210n + k devi includere 121, altrimenti ti mancherebbe 331 )
Tobias Kienzler,

2
Immagino che dovrebbe esserewhile (multOfSix - 1 <= n)
Nader Ghanbari,

8

Codice 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;
}

Esempio di utilizzo:

let result = largestPrimeFactor(600851475143);

Ecco un esempio del codice :


7

Simile alla risposta @Triptych ma anche diverso. In questo esempio di elenco o dizionario non viene utilizzato. Il codice è scritto in 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

Finalmente qualcosa di leggibile e immediatamente (in js) eseguibile allo stesso tempo. Stavo cercando di usare una lista primi infinita ed era già troppo lento su 1 milione.
Ebuall

4

Tutti i numeri possono essere espressi come prodotto di numeri primi, ad esempio:

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

Puoi trovarli semplicemente iniziando da 2 e semplicemente continuando a dividere fino a quando il risultato non è un multiplo del tuo numero:

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

usando questo metodo non devi realmente calcolare alcun numero primo: saranno tutti numeri primi, in base al fatto che hai già scomposto il numero il più possibile con tutti i numeri precedenti.

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

Sì, ma questo è orribilmente inefficiente. Dopo aver diviso tutti i 2, non dovresti davvero provare a dividere per 4, o per 6, o ...; È davvero molto più efficiente nel limite controllare solo i numeri primi o utilizzare alcuni algoritmi toher.
wnoise,

6
+1 per compensare la stanchezza, che penso sia sbagliata. Cercare di dividere per 4 avverrà una sola volta e fallirà immediatamente. Non penso che sia peggio che rimuovere 4 da una lista di candidati, ed è sicuramente più veloce che trovare tutti i numeri primi in anticipo.
Trittico

2
@Beowulf. Prova a eseguire questo codice prima di votare verso il basso. Restituisce fattori primi; semplicemente non capisci l'algoritmo.
Trittico

3
il codice funziona bene, ma è lento se il numero in arrivo è un numero primo. Vorrei anche correre solo al quadrato e incrementare di 2. Potrebbe essere troppo lento per numeri molto grandi, però.
blabla999,

4
blabla999 ha esattamente ragione. L'esempio è 1234567898766700 = 2 * 2 * 5 * 5 * 12345678987667. Quando abbiamo raggiunto currFactor = 3513642, sappiamo che 12345678987667 è primo e dovrebbe restituirlo come risposta. Invece, questo codice continuerà l'enumerazione fino allo stesso 12345678987667. È 3.513.642 volte più lento del necessario.
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
    }

1
hai provato il tuo codice con 1.000.000.000.039? dovrebbe anche correre in un batter d'occhio. Vero?
Will Ness,

2
Potresti saperlo in anticipo, senza provare. 10 ^ 12 = (2 * 5) ^ 12 = 2 ^ 12 * 5 ^ 12. Quindi il tuo whileciclo passerà attraverso i ivalori di 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. Tutte e 60 le iterazioni. Ma per (10 ^ 12 + 39) ci saranno (10 ^ 12 + 38) iterazioni, i=2,3,4,5,6,...,10^12+39. Anche se 10 ^ 10 operazioni richiedono un secondo, 10 ^ 12 impiegherà 100 secondi. Ma sono davvero necessarie solo 10 ^ 6 iterazioni e se 10 ^ 10 operazioni impiegano un secondo, 10 ^ 6 richiederebbe 1/1000 di secondo.
Will Ness,

1
Perché non avevo realizzato (10 ^ 12 + 39) un numero primo che faccio ora. Ho capito esattamente quello che stai dicendo.
the_prole

1
OK, quindi puoi cambiare il tuo codice in modo che non ci sia un rallentamento così grande per i numeri primi: se n = a b e a <= b, quindi a a <= b a = n, cioè a a <= n . E se abbiamo raggiunto un + 1, allora n è sicuramente un numero primo. (ping me se modifichi la tua risposta per incorporarla).
Will Ness,

1
cosa succede quando long n = 2*1000000000039L? Funziona velocemente come dovrebbe? (inoltre, puoi semplificare il tuo codice usando return;un'istruzione?). (se vuoi che smetta di darti una spinta, dillo e basta;))
Will Ness,

4

La soluzione più semplice è una coppia di funzioni reciprocamente ricorsive .

La prima funzione genera tutti i numeri primi:

  1. Inizia con un elenco di tutti i numeri naturali maggiore di 1.
  2. Rimuovi tutti i numeri che non sono primi. Cioè, numeri che non hanno fattori primi (diversi da loro stessi). Vedi sotto.

La seconda funzione restituisce i fattori primi di un dato numero nin ordine crescente.

  1. Prendi un elenco di tutti i numeri primi (vedi sopra).
  2. Rimuovi tutti i numeri che non sono fattori di n.

Il più grande fattore primo di nè l'ultimo numero dato dalla seconda funzione.

Questo algoritmo richiede un elenco pigro o una lingua (o una struttura di dati) con semantica chiamata per necessità .

Per chiarimenti, ecco una (inefficiente) implementazione di quanto sopra in 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

Renderlo più veloce è solo una questione di essere più intelligente nel rilevare quali numeri sono primi e / o fattori n, ma l'algoritmo rimane lo stesso.


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)

Ci sono alcuni test del modulo che sono superflous, poiché n non può mai essere diviso per 6 se tutti i fattori 2 e 3 sono stati rimossi. Potresti consentire solo numeri primi per i, che è mostrato in molte altre risposte qui.

Potresti effettivamente intrecciare il setaccio di Eratostene qui:

  • Innanzitutto crea l'elenco di numeri interi fino a sqrt (n).
  • Nel ciclo for, segna tutti i multipli di i fino al nuovo sqrt (n) come non primo e usa invece un ciclo while.
  • imposta i sul primo numero primo nell'elenco.

Vedi anche questa domanda .


2

Sono consapevole che questa non è una soluzione rapida. Pubblicare come una soluzione lenta, si spera più facile da capire.

 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;
    } 

1

Approccio iterativo Python rimuovendo tutti i fattori primi dal numero

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

1

Sto usando l'algoritmo che continua a dividere il numero per il suo fattore Prime attuale.

La mia soluzione in 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()))) 

Ingresso: 10 Uscita:5

Ingresso: 600851475143 Uscita:6857


0

Ecco il mio tentativo in c #. L'ultima stampa è il fattore primo più grande del numero. Ho controllato e funziona.

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;
    }

  }
}

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

1
è 25 il principale fattore primo di 25?
Will Ness,

0

Calcola il fattore primo più grande di un numero usando la ricorsione in C ++. Il funzionamento del codice è spiegato di seguito:

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
}

0

Ecco il mio approccio per calcolare rapidamente il fattore primo più grande. Si basa sul fatto che modificato xnon contiene fattori non primi. Per raggiungere questo obiettivo, ci dividiamo xnon appena viene trovato un fattore. Quindi, l'unica cosa rimasta è restituire il fattore più grande. Sarebbe già primo.

Il codice (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

ma questo non tenterà di dividere anche con tutti i numeri pari?
Janus Troelsen,

0

Il seguente algoritmo C ++ non è il migliore, ma funziona per numeri inferiori a un miliardo ed è piuttosto veloce

#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;
 }

0

Ho trovato questa soluzione sul web di "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;
}

0

Fattore primo con setaccio:

#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;
}

-1

Mi sembra che il passaggio n. 2 dell'algoritmo fornito non sarà un approccio così efficiente. Non hai ragionevoli aspettative che sia primo.

Inoltre, la risposta precedente che suggerisce il setaccio di Eratostene è assolutamente sbagliata. Ho appena scritto due programmi con fattore 123456789. Uno era basato sul setaccio, uno era basato sul seguente:

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

Questa versione era 90 volte più veloce del setaccio.

Il fatto è che sui moderni processori il tipo di operazione conta molto meno del numero di operazioni, per non parlare del fatto che l'algoritmo sopra può essere eseguito nella cache, il Sieve no. Il setaccio utilizza molte operazioni per eliminare tutti i numeri composti.

Si noti, inoltre, che la mia divisione dei fattori man mano che vengono identificati riduce lo spazio che deve essere testato.


questo è quello che ho detto, ma sono stato votato verso il basso :( Immagino che il problema sia che se il numero ha un fattore primo davvero grande (come se stesso), allora questo metodo deve arrivare fino a quel numero. In molti casi tuttavia, questo metodo è abbastanza efficace.
Nickf,

Rileggere il tuo è lo stesso ma la prima parte del tuo è confusa.
Loren Pechtel,

Provalo su questo numero 143816789988504044536402352738195137863656439, fammi sapere quanto è efficiente ...
MichaelICE,

-1

Calcola prima un elenco che memorizza i numeri primi, ad es. 2 3 5 7 11 13 ...

Ogni volta che si effettua la scomposizione in fattori primi di un numero, utilizzare l'implementazione di Triptych ma ripetendo questo elenco di numeri primi anziché numeri interi naturali.


-1

Con Java:

Per i intvalori:

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;
}

Per i longvalori:

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;
}

-2

Questo probabilmente non è sempre più veloce ma più ottimista riguardo al fatto che trovi un grande divisore principale:

  1. N è il tuo numero
  2. Se è primo allora return(N)
  3. Calcola numeri primi fino a Sqrt(N)
  4. Scorri i numeri primi in ordine decrescente (prima il più grande)
    • Se N is divisible by PrimealloraReturn(Prime)

Modifica: Al passaggio 3 puoi usare il setaccio di Eratostene o il setaccio di Atkins o qualunque cosa ti piaccia, ma da solo il setaccio non ti troverà il principale fattore principale. (Ecco perché non sceglierei il post di SQLMenace come risposta ufficiale ...)


1
Non è necessario eseguire il factoring di prova per determinare se si tratta di un numero primo (passaggio 2)? Inoltre, considera di trovare il fattore primo più grande di 15. I numeri primi fino a sqrt (15) sono 2 e 3; ma il fattore primo più grande è 5, non è vero? Allo stesso modo con 20.
Jonathan Leffler il

-3

Penso che sarebbe bene conservare da qualche parte tutti i numeri primi possibili più piccoli di n e solo scorrere attraverso di essi per trovare il divisore più grande. Puoi ottenere i numeri primi da prime-numbers.org .

Ovviamente suppongo che il tuo numero non sia troppo grande :)


-3

Non il più veloce ma funziona!

    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;
    }

Questa non è una risposta alla domanda. ;-) La domanda riguardava la ricerca del più grande fattore primo, non il controllo della primalità.
Hans-Peter Störr,

È molto più efficiente inizializzare il tuo ciclo come (long i = 3; i <checkUpTo; i + = 2)
cjk

-3

Ecco la stessa funzione @ Trittico fornita come generatore, anch'essa leggermente semplificata.

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

il massimo primo può quindi essere trovato usando:

n= 373764623
max(primes(n))

e un elenco di fattori trovati utilizzando:

list(primes(n))

-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();
 }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.