8

I am looking for an algorithm to find if a given number is a perfect number.

The most simple that comes to my mind is :

  1. Find all the factors of the number
  2. Get the prime factors [except the number itself, if it is prime] and add them up to check if it is a perfect number.

Is there a better way to do this ?. On searching, some Euclids work came up, but didnt find any good algorithm. Also this golfscript wasnt helpful: https://stackoverflow.com/questions/3472534/checking-whether-a-number-is-mathematically-a-perfect-number .

The numbers etc can be cached etc in real world usage [which I dont know where perfect nos are used :)]
However, since this is being asked in interviews, I am assuming there should be a "derivable" way of optimizing it.

Thanks !

Community
  • 1
  • 1
codeObserver
  • 6,521
  • 16
  • 76
  • 121
  • 2
    Beware, for your step #2, it is not the sum of its _prime_ factors, but of _all_ its factors. eg. 28 is perfect because 1 + 2 + 4 + 7 + 14 = 28 (note the 4 and 14 factors). – mjv Jul 04 '11 at 02:42

4 Answers4

11

If the input is even, see if it is of the form 2^(p-1)*(2^p-1), with p and 2^p-1 prime.

If the input is odd, return "false". :-)

See the Wikipedia page for details.

(Actually, since there are only 47 perfect numbers with fewer than 25 million digits, you might start with a simple table of those. Ask the interviewer if you can assume you are using 64-bit numbers, for instance...)

Nemo
  • 70,042
  • 10
  • 116
  • 153
  • 8
    Having been on both ends of interview questions like this, I kind of wonder if they are expecting something like the table answer. It seems like it is asking about awfully specific knowledge. I want somebody who can program, not someone who knows number theory. – andrewdski Jul 04 '11 at 04:12
  • 1
    Note the specialized [Lucas-Lehmer test](http://en.wikipedia.org/wiki/Lucas%E2%80%93Lehmer_primality_test) for primality of Mersenne numbers (2^p)-1. – hardmath Jul 04 '11 at 12:57
  • thnx for the link. I think there is no derivable optimization .. so if using a table doesnt work ...then probably the interviewers need a mathematician who can write code more than a programmer who can use maths ! – codeObserver Jul 05 '11 at 04:21
  • [Odd perfect numbers are larger than 10**1500 if they exist. (2012)](http://www.lirmm.fr/~ochem/opn/opn.pdf) i.e., you need >4Kbit integers before you start worrying about odd perfect numbers. – jfs Oct 08 '14 at 18:29
  • Only the first 43 numbers do not contain gaps i.e., there are 48 (2013) known perfect numbers (one-to-one relationship with [Mersenne primes](http://en.wikipedia.org/wiki/Mersenne_prime#List_of_known_Mersenne_primes)) but there could be others in between the last 5. – jfs Oct 08 '14 at 18:38
0
#include<stdio.h>
#include<stdlib.h>
int sumOfFactors(int ); 

int main(){
int x, start, end;
    printf("Enter start of the range:\n");
    scanf("%d", &start);
    printf("Enter end of the range:\n");
    scanf("%d", &end);

    for(x = start;x <= end;x++){
        if(x == sumOfFactors(x)){
            printf("The numbers %d is a perfect number\n", x);
        }
    }   
    return 0;
}

int sumOfFactors(int x){
    int sum = 1, i, j;
    for(j=2;j <= x/2;j++){
        if(x % j == 0)
            sum += j;
    }
    return sum;
}
0

Here's a quick algorithm just for fun, in PHP - using just a simple for loop. You can easliy port that to other languages:

function isPerfectNumber($num) {
        $out = false;

        if($num%2 == 0) {
            $divisors = array(1);
            for($i=2; $i<$num; $i++) {
                if($num%$i == 0)
                    $divisors[] = $i;
            }

            if(array_sum($divisors) == $num)
                $out = true;
        }

        return $out ? 'It\'s perfect!' : 'Not a perfect number.';
    }

Hope this helps, not sure if this is what you're looking for.

bobsoap
  • 4,844
  • 7
  • 30
  • 43
  • While functionally correct, this implementation is far from optimal but its main drawback is that its operational range is bound to that of the PHP integer which in the world of perfect numbers / mersennes is a rather small number ;-) You should use GMP (arbitrary length integers) if you want to go past the 2^PHP_INT_SIZE limit. – mjv Jul 04 '11 at 03:57
  • thnx, I was looking for some faster way of doing this. Getting it for larger numbers would be slow ? – codeObserver Jul 04 '11 at 04:03
  • Wouldn't it make more sense to add the divisors right after you find them rather than save them and add later? Also, seeing as i starts from 2, shouldn't the if condition be `$sum+1 == $num` – rath Apr 16 '13 at 22:36
0

Edit: Dang, I failed the interview! :-(
In my over zealous attempt at finding tricks or heuristics to improve upon the "factorize + enumerate divisors + sum them" approach, I failed to note that being 1 modulo 9 was merely a necessary, and certainly not a sufficient condition for at number (other than 6) to be perfect...
Duh... with on average 1 in 9 even number satisfying this condition, my algorithm would sure find a few too many perfect numbers ;-).
To redeem myself, persist and maintain the suggestion of using the digital root, but only as a filter, to avoid the more expensive computation of the factor, in most cases.


[Original attempt: hall of shame]

If the number is even,<br>
   compute its [digital root][1].
       if the digital root is 1, the number is perfect, otherwise it isn't.

If the number is odd...
   there are no shortcuts, other than...
       "Not perfect" if the number is smaller than 10^300
       For bigger values, one would then need to run the algorithm described in 
       the question, possibly with a few twists typically driven by heuristics
       that prove that the sum of divisors will be lacking when the number
       doesn't have some of the low prime factors.

My reason for suggesting the digital root trick for even numbers is that this can be computed without the help of an arbitrary length arithmetic library (like GMP). It is also much less computationally expensive than the decomposition in prime factors and/or the factorization (2^(p-1) * ((2^p)-1)).   Therefore if the interviewer were to be satisfied with a "No perfect" response for odd numbers, the solution would be both very efficient and codable in most computer languages.


[Second and third attempt...]

If the number is even,<br>
   if it is 6
      The number is PERFECT
   otherwise compute its [digital root][1].
       if the digital root is _not_ 1
           The number is NOT PERFECT
       else ..., 
           Compute the prime factors
           Enumerate the divisors, sum them
           if the sum of these divisor equals the 2 * the number
                it is PERFECT
           else
                it is NOT PERFECT

If the number is odd...
    same as previously

On this relatively odd interview question...
I second andrewdski's comment to another response in this post, that this particular question is rather odd in the context of an interview for a general purpose developer.
As with many interview questions, it can be that the interviewer isn't seeking a particular solution, but rather is providing an opportunity for the candidate to demonstrate his/her ability to articulate the general pros and cons of various approaches. Also, if the candidate is offered an opportunity to look-up generic resources such as MathWorld or Wikipedia prior to responding, this may also be a good test of his/her ability to quickly make sense of the info offered there.

mjv
  • 73,152
  • 14
  • 113
  • 156
  • 1
    Hmm. The digital root of 6 is ... 6. I could have sworn 6 was the first perfect number. Yes, the digital root trick works for even perfect numbers with more than 1 digit. But it is only a necessary condition for a perfect number. The digital root of 10 is also 1, and I could have sworn that 10 was not perfect. –  Jul 04 '11 at 08:56
  • @woodchips: Thanks for bringing me back to reality. When something looks too nice to be true is usually is the case. With all the connection of Perfect Numbers to Mersenne Numbers (and aside from the fact that the digital root test is essentially a modulo 9 test), I should have thought that it wouldn't be that easy :-( – mjv Jul 04 '11 at 14:30
  • 1
    Your second algorithm is better, allowing you to exclude roughly 90% of the even numbers as not possibly perfect. However it will still miss identifying 6 as a perfect number since the digital root of 6 is 6, not 1. –  Jul 04 '11 at 14:51
  • @woodchips Thanks again. I fixed accordingly. Maybe I should stay away from algorithms on this sunny 4th of July... – mjv Jul 04 '11 at 15:00