Java Ackermann函数与递归

Java Ackermann函数与递归,java,function,recursion,if-statement,ackermann,Java,Function,Recursion,If Statement,Ackermann,我尝试用Java编写递归Ackermann函数。但我想我在某个地方出了很大的错!有谁能看一看,检查一下,也许可以指出我的正确方向,纠正我的代码?谢谢 我对代码的问题是,在我编写它之后,我想,如果n==0,m==0,那么没有一个区域可以这样做呢?这是属于if(m==0)还是需要自己的if语句 我下面的解决方案正确吗?如果我以不同的顺序给它相同的数字,它会给出不同的结果,我不确定这是不是真的 public static int ackermann(int m, int n) {

我尝试用Java编写递归Ackermann函数。但我想我在某个地方出了很大的错!有谁能看一看,检查一下,也许可以指出我的正确方向,纠正我的代码?谢谢

我对代码的问题是,在我编写它之后,我想,如果n==0,m==0,那么没有一个区域可以这样做呢?这是属于if(m==0)还是需要自己的if语句

我下面的解决方案正确吗?如果我以不同的顺序给它相同的数字,它会给出不同的结果,我不确定这是不是真的

public static int ackermann(int m, int n) {

        if (m == 0) {

            return n + 1;

        } else if ((m > 0) && (n == 0)) {

            return ackermann(m-1, n);

        } else if ((m > 0) && (n > 0)) {

            return ackermann(m-1, ackermann(m,n-1));

        } else {

            return 0;

        }

    }
我想了很多,我想我犯了更多的错误。如果你不能理解我做了什么,我会给每个If语句一个相反的结果,因为我认为如果m和n的值是以不同的方式给出的,那么下面的代码就可以工作了。显然没有,但有人能解释一下我错在哪里吗

public static int ackermann(int m, int n) {

        if (m == 0) {

            return n + 1;

        } else if (n == 0) {

            return m + 1;

        } else if ((m > 0) && (n == 0)) {

            return ackermann(m-1, n);

        } else if ((n > 0) && (m == 0)) {

            return ackermann(n-1, m);

        } else if ((m > 0) && (n > 0)) {

            return ackermann(m-1, ackermann(m,n-1));

        } else if ((n > 0) && (m > 0)) {

            return ackermann(n-1, ackermann(n, m-1));

        } else {

            return 0;

        }

    }

“if m=0”规则适用于n的所有值,因此(0,0)是1

“else”子句只能在m和n在函数输入时均为负值时使用,这可以诊断为异常。事实上,如果m或n为负值,则应诊断错误。或者,由于A(m,n)永远不会返回零,否则,0可以被视为发送错误信号

请注意,计算A(m,n)所需的堆栈深度与答案相同,并且A(m,n)很快变得非常大。不要费心去评估A(4,4);您的计算机内存不足。

此部分错误:

    } else if ((m > 0) && (n == 0)) {
        return ackermann(m-1, n);

这应该是一个(m-1,1)

第一个代码段是正常的,除了它返回
ackermann(m-1,n)
而不是第二种情况下的
ackermann(m-1,1)
。默认情况下,不应该发生,应该抛出一个
IllegalStateException
,以防它实际发生。

我认为您的第一个版本几乎是正确的。我会稍微修改一下:

public static int ackermann(int m, int n) {
    if (m < 0 || n < 0) {
        throw new IllegalArgumentException("Non-negative args only!");
    }

    if (m == 0) {
        return n + 1;
    } else if (n == 0) {
        return ackermann(m-1, 1); // Corrected!
    } else {
        // perforce (m > 0) && (n > 0)
        return ackermann(m-1, ackermann(m,n-1));
    }
}
publicstaticintackermann(intm,intn){
if(m<0 | | n<0){
抛出新的IllegalArgumentException(“仅限非负参数!”);
}
如果(m==0){
返回n+1;
}else如果(n==0){
返回阿克曼(m-1,1);//更正!
}否则{
//性能(m>0)和(n>0)
返回阿克曼(m-1,阿克曼(m,n-1));
}
}
m==0&&n==0
案例应包含在
m==0
案例中


编辑:请注意,仅为非负参数定义。特别是,
ackermann(0,-1)
应该抛出异常。因此,您不能将最后一个
else
子句转换为
throw

有趣的是,您的问题的所有答案都在第一个版本中指出了您的错误,而在第二个版本中却没有提到重大错误

 else if (n == 0) {
        return m + 1;
    } 
对于正整数​, 与条件相同

else if ((m > 0) && (n == 0)) {
        return ackermann(m-1, n);
    } 

因此,您的函数将返回m+1,而不是ackermann(m-1,1),对于第二种情况((m>0)和(&&&n==0))。

您的最终
else
应抛出
InvalidArgumentException
。实际上,ackermann函数仅为非负参数定义。(例如,对于m==0,n==-1,它没有定义。)同意:但是Java代码采用带符号的整数,因此在调用时可能会被误用——也许代码应该对此进行诊断。我的观点是,当前的代码在使用(0,-1)调用时会愉快地返回0。更改
else
子句不足以解决此问题。