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