188

What is the best approach to calculating the largest prime factor of a number?

I'm thinking the most efficient would be the following:

  1. Find lowest prime number that divides cleanly
  2. Check if result of division is prime
  3. If not, find next lowest
  4. Go to 2.

I'm basing this assumption on it being easier to calculate the small prime factors. Is this about right? What other approaches should I look into?

Edit: I've now realised that my approach is futile if there are more than 2 prime factors in play, since step 2 fails when the result is a product of two other primes, therefore a recursive algorithm is needed.

Edit again: And now I've realised that this does still work, because the last found prime number has to be the highest one, therefore any further testing of the non-prime result from step 2 would result in a smaller prime.

smci
  • 26,085
  • 16
  • 96
  • 138
mercutio
  • 20,943
  • 10
  • 33
  • 37
  • My approach was: (1) divide large, possible number by 2; (2) check if the large number divides evenly into it; (3) if so, check if the divided by 2 number is prime. If it is, return it. (4) Else, substract 1 from the divided by 2 number, returning to step 3. – Kevin Meredith Jul 28 '14 at 00:59
  • `1.` find any number that divides clearly (for i = 2 to int(sqr(num)) ) `2.` divide by that number (num = num/i) and recur until nothing is found in *1.*'s interval `3.` *num* is the largest factor – user3819867 Sep 11 '15 at 21:37
  • 1
    We can Divide with small primes, and the one which is finally left, is the Largest Prime Factor (I guess) –  Jul 24 '16 at 03:05

28 Answers28

143

Here's the best algorithm I know of (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

The above method runs in O(n) in the worst case (when the input is a prime number).

EDIT:
Below is the O(sqrt(n)) version, as suggested in the comment. Here is the code, once more.

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
nhahtdh
  • 52,949
  • 15
  • 113
  • 149
Triptych
  • 188,472
  • 32
  • 145
  • 168
  • 2
    I do believe this does not work, nor does it retrieve prime-factors, but factors eventually. Where in this code are prime numbers used? d is only natural numbers upcounted, nothing prime there. – Oliver Friedrich Jan 07 '09 at 16:54
  • 11
    Please read and/or run this code before voting it down. It works fine. Just copy and paste. As written prime_factors(1000) will return [2,2,2,5,5,5], which should be interpreted as 2^3*5^3, a.k.a. the prime factorization. – Triptych Jan 07 '09 at 17:59
  • 1
    I'm sorry, did an error in converting the code to C#, put one line more into the second while loop. Undone the downvote. – Oliver Friedrich Jan 07 '09 at 18:18
  • 11
    "runs in `O(sqrt(n))` in the worst case" - No, it runs in `O(n)` in the worst case (e.g. when `n` is prime.) – Sheldon L. Cooper Sep 26 '10 at 15:23
  • @Triptych Sheldon is correct, this is `O(n)` for prime values of n. – Rob Jan 10 '12 at 18:56
  • 17
    Easy to make it O(sqrt(n)), you just stop the loop when d*d > n, and if n > 1 at this point then its value should be appended to the list of prime factors. – Sumudu Fernando Mar 19 '12 at 04:53
  • 5
    Is there a name for this? – Forethinker Jul 19 '13 at 23:44
  • 11
    since 2 is the only even prime number, so instead of adding 1 each time, you can iterate separately for d=2 and then increment it by 1 and then from d=3 onwards you can increment by 2. so it will decrease the number of iterations... :) – tailor_raj Nov 19 '13 at 09:13
  • 2
    @Forethinker I think you would call this approach "Trial Division" or "Brute Force". – Xantix Mar 14 '14 at 02:42
  • 3
    This algorithm is horribly inefficient. And the claim that it's O(sqrt(n)) is misleading: for problems such as integer factorization it's customary to measure complexity in the number of *input digits*, not the size of the input. Given than the input n has m=log(n) digits the complexity of this algorithm is O(exp(m/2)). – Michael Sep 29 '14 at 15:55
  • 4
    @avi The trick is to realize that because this loop starts at the first prime (d=2) and removes all factors, d will always be a prime if n % d == 0. Say n = 120. 120's prime factors are 2,2,2,3,5. So when d = 2, the (while n % d == 0) strips all 2's from the number, and you're left with some other prime factors. The key idea is those prime factors will be larger than 2. The other cool part is the loop terminates at sqrt(n), because there cannot be any prime factors larger than sqrt(n). – Lucas Dec 28 '14 at 16:55
  • 3
    @avi or anyone else who is still confused: another way to think of it is first: The smallest divisor will always be prime. Take 12 for example. 2 is the smallest divisor. Then note that the list of all prime numbers times each other will equal the total. So e.g. we know 2 is a prime. So we can divide 12 by 2 = 6. We know the rest of the primes multiplied by each other must equal 6. Lucas explained the rest well. – Kt Mack Jan 23 '15 at 06:59
  • What is the trick that causes `d = d + 1` to be ignored for numbers that are not a prime? – Redsandro Apr 22 '15 at 13:05
  • 1
    The 'trick' is the the line `n /= d`. It removes the prime factor d from n for all subsequent calculations in the loop. – Vince O'Sullivan Jun 30 '15 at 18:44
  • I think this method will only generate a set of prime factors only, the result set can't have any composite since we start with the first prime 2 in increasing order always, which is neat – K'' Sep 04 '15 at 02:36
  • 2
    Inefficient, but it works well enough for my purposes. But it can return a real number (199.0) instead of an integer (199). Simple fix: replace n/=d with n//=d. – Isaac Rabinovitch Aug 02 '16 at 22:21
  • @Redsandro, VinceOSullivan: there is no 'trick'. `d = d + 1` causes us to brute-force all candidate numbers d <= sqrt(n). (If d is composite, then n cannot still be divisible by d since we've already removed all factors < d. But this algorithm still attempts the trial division `while n % d == 0` anyway, even if d is composite. That's why this is very inefficient. The higher d gets, the more likely it's composite and hence doesn't need to be tested.) – smci Sep 09 '18 at 07:17
137

Actually there are several more efficient ways to find factors of big numbers (for smaller ones trial division works reasonably well).

One method which is very fast if the input number has two factors very close to its square root is known as Fermat factorisation. It makes use of the identity N = (a + b)(a - b) = a^2 - b^2 and is easy to understand and implement. Unfortunately it's not very fast in general.

The best known method for factoring numbers up to 100 digits long is the Quadratic sieve. As a bonus, part of the algorithm is easily done with parallel processing.

Yet another algorithm I've heard of is Pollard's Rho algorithm. It's not as efficient as the Quadratic Sieve in general but seems to be easier to implement.


Once you've decided on how to split a number into two factors, here is the fastest algorithm I can think of to find the largest prime factor of a number:

Create a priority queue which initially stores the number itself. Each iteration, you remove the highest number from the queue, and attempt to split it into two factors (not allowing 1 to be one of those factors, of course). If this step fails, the number is prime and you have your answer! Otherwise you add the two factors into the queue and repeat.

Will Ness
  • 62,652
  • 8
  • 86
  • 167
Artelius
  • 45,612
  • 11
  • 85
  • 102
  • 3
    Pollard rho and the elliptic curve method are much better at getting rid of small prime factors of your number than the quadratic sieve. QS has about the same runtime no matter the number. Which approach is faster depends on what your number is; QS will crack hard-to-factor numbers faster while rho and ECM will crack easy-to-factor numbers faster. – tmyklebu Sep 22 '14 at 17:02
  • Thank you for the Quadratic variation suggestion. I needed to implement this for one of my clients, the initial version I came up was something along the lines of what @mercutio suggested in his question. The quadratic solution is what is powering my client's tool now at https://math.tools/calculator/prime-factors/ . – dors Apr 03 '17 at 14:34
  • If there is an efficient way of solving this problem, doesn't that mean that web encryption is not not secure? – BKSpurgeon Apr 23 '20 at 23:55
18

My answer is based on Triptych's, but improves a lot on it. It is based on the fact that beyond 2 and 3, all the prime numbers are of the form 6n-1 or 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;
}

I recently wrote a blog article explaining how this algorithm works.

I would venture that a method in which there is no need for a test for primality (and no sieve construction) would run faster than one which does use those. If that is the case, this is probably the fastest algorithm here.

Community
  • 1
  • 1
sundar - Remember Monica
  • 6,647
  • 5
  • 40
  • 66
  • 12
    You can actually take this idea even further, e.g. beyond 2,3,5 all primes are of the form 30n+k (n >= 0) where k only takes those values between between 1 and 29 that are not divisible by 2,3 or 5, i.e. 7,11,13,17,19,23,29. You can even have this dynamically adapt after every few primes you found so far to 2*3*5*7*...*n+k where k must not be divisible by any of these primes (note that not all possible k need be prime, e.g. for 210n+k you have to include 121, otherwise you'd miss [331](http://www.wolframalpha.com/input/?i=isprime%202*3*5*7%2B11^2&dataset=)) – Tobias Kienzler Oct 07 '13 at 11:51
  • 2
    I guess it should be `while (multOfSix - 1 <= n)` – Nader Ghanbari Jul 16 '14 at 04:05
8

JavaScript code:

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

Usage Example:

let result = largestPrimeFactor(600851475143);

Here is an example of the code:

Vlad Bezden
  • 59,971
  • 18
  • 206
  • 157
7

Similar to @Triptych answer but also different. In this example list or dictionary is not used. Code is written 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
learnAsWeGo
  • 2,217
  • 2
  • 9
  • 17
Ugnius Malūkas
  • 2,151
  • 6
  • 26
  • 37
  • Finally something readable and instantly (in js) executable at the same time. I was trying to use infinite prime list and it was already too slow on 1 million. – Ebuall Apr 07 '18 at 16:39
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
    }
Holger Just
  • 45,586
  • 14
  • 98
  • 114
the_prole
  • 6,481
  • 11
  • 56
  • 120
  • 1
    have you tried your code with 1,000,000,000,039? it should run in a blink of an eye too. Does it? – Will Ness Apr 12 '14 at 11:57
  • I don't know Wily. I will have to try. – the_prole Apr 12 '14 at 14:23
  • 2
    You could know it in advance, without trying. 10^12 = (2*5)^12 = 2^12 * 5^12. So your `while` loop will go through `i` values of `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`. All of 60 iterations. But for (10^12+39) there will be (10^12+38) iterations, `i=2,3,4,5,6,...,10^12+39`. Even if 10^10 ops take one second, 10^12 will take 100 seconds. But only 10^6 iterations are really needed, and if 10^10 ops take a second, 10^6 would take 1/10,000th of a second. – Will Ness Apr 12 '14 at 15:51
  • Sorry Will, I didn't understand if you were being sarcastic. The speed of my code increases linearly with the size of the number. I don't see why my program would run any slower if I used one trillion and thirty nine. I wrote the code for general purpose factoring, not for specific numbers. I just used 600 billion as an example. So while your statement is technically correct, your method won't work for every number. Or will it? – the_prole Apr 12 '14 at 19:28
  • 1
    Because I didn't realize (10^12+39) was a prime number which I do now. I get exactly what you're saying. – the_prole Apr 14 '14 at 12:58
  • 1
    OK, so you can change your code so that there won't be such a big slowdown for the primes: if n = a*b and a <= b, then a*a <= b*a = n, i.e. a*a <= n. And if we've reached a+1, then n is surely a prime. (ping me if you edit your answer to incorporate this). – Will Ness Apr 14 '14 at 13:30
  • I am writing my thesis and don't very much time right now. As soon as I implement the Fermat/trial-divsion combination I will ping you... How DO I ping you? – the_prole Apr 17 '14 at 16:49
  • 1
    what happens when `long n = 2*1000000000039L`? Does it work as fast as it should? (also, can you simplify your code by using a `return;` statement?). (if you want me to stop nudging you, just say so ;)) – Will Ness Apr 18 '14 at 08:37
  • @WillNess So isn't the second edit in Triptych's post incorrect? Shouldn't he be using a counter as I did in my code? – the_prole Apr 18 '14 at 15:34
4

The simplest solution is a pair of mutually recursive functions.

The first function generates all the prime numbers:

  1. Start with a list of all natural numbers greater than 1.
  2. Remove all numbers that are not prime. That is, numbers that have no prime factors (other than themselves). See below.

The second function returns the prime factors of a given number n in increasing order.

  1. Take a list of all the primes (see above).
  2. Remove all the numbers that are not factors of n.

The largest prime factor of n is the last number given by the second function.

This algorithm requires a lazy list or a language (or data structure) with call-by-need semantics.

For clarification, here is one (inefficient) implementation of the above 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

Making this faster is just a matter of being more clever about detecting which numbers are prime and/or factors of n, but the algorithm stays the same.

Apocalisp
  • 33,619
  • 8
  • 100
  • 150
4

All numbers can be expressed as the product of primes, eg:

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

You can find these by simply starting at 2 and simply continuing to divide until the result isn't a multiple of your number:

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

using this method you don't have to actually calculate any primes: they'll all be primes, based on the fact that you've already factorised the number as much as possible with all preceding numbers.

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
  • 499,078
  • 194
  • 614
  • 709
  • Yes, but this is horribly inefficient. Once you've divided out all the 2s, you really shouldn't try dividing by 4, or by 6, or ...; It really is much more efficient in the limit to only check primes, or use some toher algorithm. – wnoise Oct 28 '08 at 05:30
  • 6
    +1 to offset wnoise, who I think is wrong. Trying to divide by 4 will only happen once, and will fail immediately. I don't think that's worse than removing 4 from some list of candidates, and it's certainly faster than finding all primes beforehand. – Triptych Jan 07 '09 at 16:15
  • Same as with Triptych - nothing with prime-numbers here, same code, other language. – Oliver Friedrich Jan 07 '09 at 16:55
  • 2
    @Beowulf. Try running this code before voting down. It returns prime factors; you just don't understand the algorithm. – Triptych Jan 07 '09 at 18:01
  • 3
    the code works ok, but is slow if the incoming number is a prime. I would also only run up to the square and increment by 2. It might be too slow for very big numbers, though. – blabla999 Jan 13 '09 at 19:11
  • 4
    blabla999 is exactly right. Example is 1234567898766700 = 2*2*5*5*12345678987667. When we've reached `currFactor = 3513642`, we know that 12345678987667 is prime, and should return it as the answer. Instead, this code will continue the enumeration until 12345678987667 itself. That's 3,513,642x slower than necessary. – Will Ness Apr 11 '14 at 18:04
3
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)

There are some modulo tests that are superflous, as n can never be divided by 6 if all factors 2 and 3 have been removed. You could only allow primes for i, which is shown in several other answers here.

You could actually intertwine the sieve of Eratosthenes here:

  • First create the list of integers up to sqrt(n).
  • In the for loop mark all multiples of i up to the new sqrt(n) as not prime, and use a while loop instead.
  • set i to the next prime number in the list.

Also see this question.

fish-404
  • 95
  • 2
  • 14
Ralph M. Rickenbach
  • 12,121
  • 5
  • 25
  • 47
2

I'm aware this is not a fast solution. Posting as hopefully easier to understand slow solution.

 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
  • 127
  • 2
1

Python Iterative approach by removing all prime factors from the number

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

I am using algorithm which continues dividing the number by it's current Prime Factor.

My Solution 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()))) 

Input : 10 Output : 5

Input : 600851475143 Output : 6857

Kalpesh Dusane
  • 1,281
  • 3
  • 16
  • 27
0

Here is my attempt in c#. The last print out is the largest prime factor of the number. I checked and it works.

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
  • 1,145
  • 1
  • 10
  • 15
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
0

Calculates the largest prime factor of a number using recursion in C++. The working of the code is explained below:

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
  • 3,803
  • 1
  • 27
  • 41
0

Here is my approach to quickly calculate the largest prime factor. It is based on fact that modified x does not contain non-prime factors. To achieve that, we divide x as soon as a factor is found. Then, the only thing left is to return the largest factor. It would be already prime.

The 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
  • 724
  • 9
  • 13
0

The following C++ algorithm is not the best one, but it works for numbers under a billion and its pretty fast

#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;
 }
s.n
  • 635
  • 1
  • 9
  • 17
0

Found this solution on the web by "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
  • 447
  • 1
  • 5
  • 13
0

Prime factor using sieve :

#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;
}
rashedcs
  • 2,709
  • 2
  • 29
  • 32
0

Here is my attempt in Clojure. Only walking the odds for prime? and the primes for prime factors ie. sieve. Using lazy sequences help producing the values just before they are needed.

(defn prime? 
  ([n]
    (let [oddNums (iterate #(+ % 2) 3)]
    (prime? n (cons 2 oddNums))))
  ([n [i & is]]
    (let [q (quot n i)
          r (mod n i)]
    (cond (< n 2)       false
          (zero? r)     false
          (> (* i i) n) true
          :else         (recur n is)))))

(def primes 
  (let [oddNums (iterate #(+ % 2) 3)]
  (lazy-seq (cons 2 (filter prime? oddNums)))))

;; Sieve of Eratosthenes
(defn sieve
  ([n] 
    (sieve primes n))
  ([[i & is :as ps] n]
    (let [q (quot n i)
          r (mod n i)]
    (cond (< n 2)       nil
          (zero? r)     (lazy-seq (cons i (sieve ps q)))
          (> (* i i) n) (when (> n 1) (lazy-seq [n]))
          :else         (recur is n)))))

(defn max-prime-factor [n]
  (last (sieve n)))
Vikas Gautam
  • 1,439
  • 18
  • 21
0

Guess, there is no immediate way but performing a factorization, as examples above have done, i.e.

in a iteration you identify a "small" factor f of a number N, then continue with the reduced problem "find largest prime factor of N':=N/f with factor candidates >=f ".

From certain size of f the expected search time is less, if you do a primality test on reduced N', which in case confirms, that your N' is already the largest prime factor of initial N.

Sam Ginrich
  • 95
  • 1
  • 3
-1

Compute a list storing prime numbers first, e.g. 2 3 5 7 11 13 ...

Every time you prime factorize a number, use implementation by Triptych but iterating this list of prime numbers rather than natural integers.

guoger
  • 177
  • 2
  • 8
-1

With Java:

For int values:

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

For long values:

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
  • 38,878
  • 15
  • 91
  • 139
-1

It seems to me that step #2 of the algorithm given isn't going to be all that efficient an approach. You have no reasonable expectation that it is prime.

Also, the previous answer suggesting the Sieve of Eratosthenes is utterly wrong. I just wrote two programs to factor 123456789. One was based on the Sieve, one was based on the following:

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

This version was 90x faster than the Sieve.

The thing is, on modern processors the type of operation matters far less than the number of operations, not to mention that the algorithm above can run in cache, the Sieve can't. The Sieve uses a lot of operations striking out all the composite numbers.

Note, also, that my dividing out factors as they are identified reduces the space that must be tested.

Loren Pechtel
  • 8,549
  • 3
  • 27
  • 45
  • that's what i said, but got voted down :( I guess the problem is that if the number has a really large prime factor (such as itself), then this method must loop all the way up to that number. In a lot of cases though, this method is quite efficient. – nickf Oct 28 '08 at 05:57
  • Reading back through yours it is the same but the first part of yours is confusing. – Loren Pechtel Oct 29 '08 at 01:56
  • Try that on this number 143816789988504044536402352738195137863656439, let me know how efficient this is... – MichaelICE May 08 '09 at 16:54
-2

This is probably not always faster but more optimistic about that you find a big prime divisor:

  1. N is your number
  2. If it is prime then return(N)
  3. Calculate primes up until Sqrt(N)
  4. Go through the primes in descending order (largest first)
    • If N is divisible by Prime then Return(Prime)

Edit: In step 3 you can use the Sieve of Eratosthenes or Sieve of Atkins or whatever you like, but by itself the sieve won't find you the biggest prime factor. (Thats why I wouldn't choose SQLMenace's post as an official answer...)

palotasb
  • 3,223
  • 1
  • 18
  • 28
  • 1
    Don't you need to do the trial factoring to determine if it is a prime number (step 2)? Also, consider finding the largest prime factor of 15. The primes up to sqrt(15) are 2 and 3; but the largest prime factor is 5, is it not? Similarly with 20. – Jonathan Leffler Jul 16 '16 at 06:52
-3

Here is the same function@Triptych provided as a generator, which has also been simplified slightly.

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

the max prime can then be found using:

n= 373764623
max(primes(n))

and a list of factors found using:

list(primes(n))
pedram
  • 2,559
  • 3
  • 21
  • 41
-4

I think it would be good to store somewhere all possible primes smaller then n and just iterate through them to find the biggest divisior. You can get primes from prime-numbers.org.

Of course I assume that your number isn't too big :)

Klesk
  • 507
  • 6
  • 9
-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
  • 1
  • 2