0

我使用递归算法来计算 30 个完美数字,但只计算前 4 个,然后程序抛出错误。

在此处输入图像描述

public class PerfectNumbers {
  /**
  * @param args the command line arguments
  */
  public static void main(String[] args) {
    getPerfectNumbers(1,1);
  }

  static void getPerfectNumbers(long out,long number) {
    long total = 0;
    if(out==30) {
      return;
    }
    for ( int i=1;i<number;i++) {
      if(number%i==0) {
        total+=i;
      }
    }
    if(total==number) {
      System.out.println("Perfect Number "+number);
      out++;
    }
    number++;
    getPerfectNumbers(out,number);  
  }
}

算法有什么问题?

4

2 回答 2

3

完美的数字开始于:

6、28、496、8128、33550336

8128使用接受两个参数的方法执行嵌套调用long对于 JVM 通常是可行的。
我精确“两个参数”,因为堆栈的大小对 JVM 接受的嵌套调用的数量很重要。
但是从某种级别的嵌套调用来看,JVM 抛出一个Error:java.lang.StackOverflowError定义为:

当由于应用程序递归太深而发生堆栈溢出时引发。

而且33550336嵌套的调用肯定太多了。

该算法可能是正确的,但您应该更喜欢循环而不是递归,以防止堆栈溢出。

于 2018-05-25T17:10:31.940 回答
1

第 5 个完美数是如此之大,以至于达到它所需的递归量会导致StackOverflowError。手动检查每个数字在技术上是可行的,但远非最佳,因为即使是第 5 个完美数字也是 33550336,这将花费比合理计算更长的时间。一种更有效的技术是检查数字是否可以用2^(p-1)*(2^p-1)、 wherep2^p-1是素数来表示。然而,话虽如此,使用递归或循环技术,您几乎肯定无法计算出 8 个完美数字,更不用说 30 个了,因为这些数字很快就会变得太大。

于 2018-05-25T17:13:00.913 回答