1
import java.util.Scanner;

//create AckermannsFunction class
public class Ackermann
{
   public static void main(String[] args) {

      //instance variables
      String input; //holds user input for the numbers
      int num1; //holds first number
      int num2; //holds second number

      //create new Scanner
      Scanner keyboard = new Scanner(System.in);

      do {
         //get first number from user
         System.out.println("Enter a number: ");
         input = keyboard.nextLine();
         num1 = Integer.parseInt(input);

         //get second number from user
         System.out.println("Enter another number: ");
         input = keyboard.nextLine();
         num2 = Integer.parseInt(input);

         System.out.println("Result: \n Ackermann: (" + num1 + "," + num2 + ") = " + ackermann(num1, num2));
      }

      //while(Integer.parseInt(input) != -1);
      while(num1 != -1 || num2 != -1);

      System.out.println("Bye!");
   }

   public static int ackermann(int m, int n) {
      //calculate if m = 0
      if(m == 0)
         return n + 1;
      if(n == 0)
         return ackermann(m - 1, 1);
      else
         return ackermann(m - 1, ackermann(m, n - 1));
   }
}

这是我不断收到的错误:

Exception in thread "main" java.lang.StackOverflowError
    at Ackermann.ackermann(Ackermann.java:44)

每当我为第一个数字输入 -1 为第二个数字输入 -1 时,这种情况就会发生很多次。我知道它与 while 循环有关,并且尝试了很多方法来修复它,但想不出更好的方法来解决它。

4

2 回答 2

1

您的ackermann方法的基本情况(负责终止递归)不处理小于零的数字,因此您继续无限地进入 else 子句,或者直到您用完堆栈,以先到者为准....

  public static int ackermann(int m, int n) {
      if(m == 0)  <--nope
         return n + 1;
      if(n == 0) <--nope
         return ackermann(m - 1, 1);
      else
         return ackermann(m - 1, ackermann(m, n - 1)); <-- here we go again
   }

我不记得ackermann函数的精确定义,但你可以很容易地防止StackOverflowError当 m < 0 时:

  public static int ackermann(int m, int n) {
      if(m <= 0)
         return n + 1;
      if(n == 0)
         return ackermann(m - 1, 1);
      else
         return ackermann(m - 1, ackermann(m, n - 1));
   }
于 2015-02-21T01:25:41.570 回答
1
  1. 顺便说一句,对于更大的参数(m > 3 和 n > 12,默认堆栈大小),您仍然会得到堆栈溢出错误,因为即使对于 Ackermann(3,15),我们也有 45811673828 次函数调用,但要计算 Ackermann(3,16 ) 我们需要最大堆栈大小 > 10 mb
  2. Ackermann(4,2) = 2^65536-3,所以 int 类型不足以表示这个巨大的数字(19 729 个十进制数字)。您可以使用 BigDecimal 或类似的东西。
于 2015-12-10T00:12:59.117 回答