Even More Fun with LINQ - Finding Perfect Numbers

If you look up the definition of a perfect number in Wikipedia it states - "A Perfect number is defined as a positive integer which is the sum of its proper positive divisors (not including the number itself)".  For example, 6 is a perfect number because its divisors are 1,2, and 3.  1+2+3 = 6.  In this C# Corner BLOG, we show you how to use LINQ to search for all perfect numbers up to 10000.

Euclid proved that

2n-1(2n - 1)

gives an even perfect number whenever 2n-1 is prime.

Here are some other cool facts about perfect numbers:

1) if you sum the reciprocal of the divisors, they always equal 2:

e.g.  1/1 + 1/2 + 1/3  + 1/6 = 2

2) The only even perfect number of the form x^3 + 1 is 28

3) The first 39 even perfect numbers are 2n-1(2n - 1) for

n = 2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269, 2976221, 3021377, 6972593, 13466917

    (The numbers start getting quite large after 7)

Anyway here is the linq code that finds the numbers with n = 2,3,5,7.  It loops through all numbers from 1-10000,  gets each numbers divisors with LINQ and sums the divisors with LINQ.  If the sum of the divisors equals the number itself, we found a perfect number.

private static void WriteOutPerfectNumbers()

{

List<int> allNumbers = new List<int>(); // list of range of numbers to check

List<int> perfectNumbers = new List<int>();

int numbersToSearchTo = 10000; // look for perfect numbers up to 10000

// get a list of all numbers from, 2 - 10000 (1 is not considered perfect) 

var allNumbersVar = System.Query.Sequence.Range(2, numbersToSearchTo - 1);

allNumbers = allNumbersVar.ToList<int>();

// loop through all numbers and see if each one is perfect

for (int nextNumber = 1; nextNumber < allNumbers.Count; nextNumber++)

{

// first get all the unique divisors of the number

List<int> divisors = new List<int>();

var allPossibleFactors = System.Query.Sequence.Range(2, nextNumber);

var divisorsVar = from num in allPossibleFactors where nextNumber % num == 0 && (int) nextNumber > num select num;

divisors = divisorsVar.ToList<int>();

divisors.Insert(0, 1); // insert 1, because it counts as a divisor

// if the number is not prime, check it for 'perfection'
if (divisors.Count() > 1)
{

  // get the sum of the divisors
  int sumVal = divisors.Sum();

  // if the sum of the divisors equals the number itself
  // we found a perfect number!!

  if (sumVal == nextNumber)
   {
    
perfectNumbers.Add(nextNumber);
   }

  }

 }

// write out all the perfect numbers we found
foreach (var num in perfectNumbers)
 {
  
Console.Write("{0}, ", num);
 }

 
Console.WriteLine();
 
Console.ReadLine(); // wait for enter key to exit

}

 

If your run this method in .NET 3.0, you should get the following output

Happy LINQing!