-1

As the title says, I'm supposed to write a program that outputs all the perfect numbers between 2-20,000. The program I have written looks correct to me, but it only outputs "6" even though it's in a for loop and it should be giving me the rest of the numbers, right? I'm a new computer science student, so I'm still trying to learn all this.

public static void partC(System [] args){
   int number = 2;
   
   while(number <= 20000){
      int factorNum = 1;
      
      for(int sum = 0; number % factorNum == 0; factorNum++){
         if(number % factorNum == 0){
            sum += factorNum;
         }
         if(number == sum){
            System.out.println(number);
         }
      }
      ++number
   }
}   
rgettman
  • 176,041
  • 30
  • 275
  • 357
  • 2
    Why is your method taking an array of `System`, a class that can't be instantiated? Did you miss the semicolon on `++number`? – rgettman Apr 06 '23 at 20:37

3 Answers3

1

You're not computing your divisors correctly. You need to set sum to 1 and then iterate starting at 2 while factorNum < number. But a somewhat better method is to consider that if a % b == 0 then both b and a/b are divisors. So you only need to check factors <= to the square root of the test number. It would look like the following:

int sum = 1;
int limit = (int)Math.sqrt(number);
for (int factorNum = 2; factorNum <= limit; factorNum++) {        
     if (number % factorNum == 0) {
         sum += (factorNum + number/factorNum);
     }   
}

But even the above is not very efficient for finding larger perfect numbers. As they get large very quickly, the loop is very time consuming. A better way is to use BigInteger to allow for arbitrarily large numbers and to take advantage of their form as detailed in Perfect Number. An abbreviated explanation is provided below.

If p is prime and 2p-1 is prime then then (2p-1)(2p-1) is a perfect number. So the following will find all perfect numbers up to a given maximum. You can adjust it as required, but the max I have chosen is 2150. The only thing that is special about the following is that BigInteger is used along with its test for primality. The computations are just basic mathematical operations.

int p = 2;
// BigInteger max = BigInteger.valueOf(22_000);
BigInteger max = BigInteger.TWO.pow(150);
BigInteger perfect = BigInteger.ZERO;
while(perfect.compareTo(max) < 0) {
    if (BigInteger.valueOf(p).isProbablePrime(50)) {
        BigInteger powerOfTwo = BigInteger.TWO.pow(p-1);
        BigInteger mersenne = powerOfTwo.multiply(BigInteger.TWO).subtract(BigInteger.ONE);
        if(mersenne.isProbablePrime(50)) {
            perfect = powerOfTwo.multiply(mersenne);
            System.out.println(perfect);
        }
    }
    p += p > 2 ? 2 : 1;
}

prints

6
28
496
8128
33550336
8589869056
137438691328
2305843008139952128
2658455991569831744654692615953842176
191561942608236107294793378084303638130997321548169216


WJS
  • 36,363
  • 4
  • 24
  • 39
0

Your code will exit from for loop everytime "number % factorNum == 0" is not true. So it works when number is 6 because factorNum's are 1,2,3 and it will exit the code when factorNum is 4.

My solution:

public class partC {
    public static void main(String[] args) {
        int number = 2;

        while (number <= 20000) {
            int sum = 0;
            for (int factorNum = 1; number > factorNum; factorNum++) {
                
                if (number % factorNum == 0) {
                    sum += factorNum;
                }
                
            }
            if (number == sum) {
                    System.out.println(number);
            }
            number++;
        }
    }
}

Instead of checking if sum is equal to the number in for loop, you can just calculate the sums of factorNums in for loop and check if sum is equal to that number after the for loop.

Arson1st
  • 27
  • 5
0

My solution:

import java.util.Scanner;

public class Main {
public static void main(String[] args) {

    for(int loopNumber = 1; loopNumber<20000; loopNumber++) {

        int controlValue = 0;

        for (int i = 1; i <= loopNumber; i++) {
            if (loopNumber % i == 0) {
                controlValue = (controlValue += i);
            }
        }

        if (controlValue == loopNumber*2) {
            System.out.println("This number is perfect number: "+loopNumber);
        }
    }

  }
}
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 11 '23 at 12:03