-2

How to improve the efficiency of this code?

Suppose you have to deal with really big inputs.

‪#‎include‬ <iostream>
using namespace std;
int main()
{   //This program finds out the largest prime factor of given input
    long int n,big=1;
    cin>>n;
    for (long int i=2;i<n;i=i+2)
    {
        if (n%i==0)
           big=i;
    }
    cout<<big;
    return 0;
}
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 3
    well, for starters, it needs to find the largest prime factor – Keith Nicholas Sep 07 '15 at 05:09
  • fairly sure this is the 3rd project euler question. – sashang Sep 07 '15 at 05:10
  • 1
    I'm voting to close this question as off-topic because the code is completely wrong that the question can't be answered – Keith Nicholas Sep 07 '15 at 05:11
  • Read more about [prime numbers](https://en.wikipedia.org/wiki/Prime_number) & [primality tests](https://en.wikipedia.org/wiki/Primality_test). It not much related to C++; notice that every prime p above 11 is either a 6j+1 or a 6j+5 and that you don't need to test p once p*p > n – Basile Starynkevitch Sep 07 '15 at 05:25
  • This is a pointless question, but for the sake of whatever, exactly how big a number you want to find the prime factors for? 10 digits? 1000 digits? A million digits? – yzt Sep 07 '15 at 08:23

1 Answers1

3

For a start, I don't think the code you have is giving you the largest prime factor anyway, it's simply giving you the largest factor, whether that be prime or composite(1).

If you're after the largest prime factor (or zero if there is none), it can be found by repeated integer division, similar to the way many implementations of the UNIX factor program work, and along the lines of:

def largestPrimeFactor(n):
    if n < 2: return 0            # Special case

    denom = 2                     # Check every denominator
    big = 0
    while denom * denom <= n:     # Beyond sqrt, no factors exist
        if n % denom == 0:        # Check factor, then divide
            big = denom
            n = n / denom
        else:
            denom = denom + 1     # Or advance to next number

    if n > big:                   # What's left may be bigger
        big = n

    return big

If you wanted even more efficiency, you can change the way you modify the denominator each time through the loop. Once you've checked two, every other prime must be odd so you could avoid rechecking even numbers, effectively halving the time taken:

def largestPrimeFactor(n):
    if n < 2: return 0            # Special case

    while n % 2 == 0: n = n / 2   # Check and discard twos
    if n == 1: return 2           # Return if it was ALL twos

    denom = 3                     # Check every denominator
    big = 0
    while denom * denom <= n:     # Beyond sqrt, no factors exist
        if n % denom == 0:        # Check factor, then divide
            big = denom
            n = n / denom
        else:
            denom = denom + 2     # Or advance to next odd number

    if n > big:                   # What's left may be bigger
        big = n

    return big

There's also another method which skips more composites and it relies on the mathematical fact that, other than 2 and 3, every other prime number is of the form 6n±1(2).

Some composites also have this form, such as 25 and 33, but you can wear a small amount of inefficiency here.

While the change to using odd numbers shaved off 50% from the original effort, this one shaves off another 33% from the odd-number variant:

def largestPrimeFactor(n):
    if n < 2: return 0            # Special case

    while n % 2 == 0: n = n / 2   # Check and discard twos
    if n == 1: return 2           # Return if it was ALL twos

    while n % 3 == 0: n = n / 3   # Check and discard threes
    if n == 1: return 3           # Return if it was ALL threes

    denom = 5                     # Check every denominator
    adder = 2                     # Initial value to add
    big = 0
    while denom * denom <= n:     # Beyond sqrt, no factors exist
        if n % denom == 0:        # Check factor, then divide
            big = denom
            n = n / denom
        else:
            denom = denom + adder # Or advance to next denominator,
            adder = 6 - adder     #    alternating +2, +4

    if n > big:                   # What's left may be bigger
        big = n

    return big

The trick here is to start at five, alternately adding two at four:

                      vv         vv        (false positives)
5  7 11 13  17 19  23 25  29 31  35 37  41 ...
    9     15     21     27     33     39   (6n+3, n>0)

and you can see it skipping every third odd number (9, 15, 21, 27, ...) since it's a multiple of three, which is where the 33% further reduction comes from. You can also see the false positives for primes (25 and 33 in this case but more will happen).


(1) Your original heading called for the largest even prime factor and the most efficient code for finding that would be the blindingly fast:

if (n % 2 == 0)
    cout << 2 << '\n';
else
    cout << "None exists\n";

(since there's only one even prime). However, I doubt that's what you really wanted.


(2) Divide any non-negative number by six. If the remainder is 0, 2 or 4, then it's even and therefore non-prime (2 is a special case here):

6n + 0 = 2(3n + 0), an even number.
6n + 2 = 2(3n + 1), an even number.
6n + 4 = 2(3n + 2), an even number.

If the remainder is 3, then it is divisible by 3 and therefore non-prime (3 is a special case here):

6n + 3 = 3(2n + 1), a multiple of three.

That leaves just the remainders 1 and 5, and those numbers are all of the form 6n±1. So, handling 2 and 3 as special cases, start at 5 and alternately add 2 and 4 and you can guarantee that all the primes (and a few composites) will be caught in the net.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • If you're looking for prime factors, you can divide the number as you find the smaller prime factors (repeatedly: `while (target % test == 0) target /= test;`), which alters the workload for composite numbers (but doesn't help with primes, but then it isn't clear that starting from the square root helps with primes either). – Jonathan Leffler Sep 07 '15 at 05:01