Ackermann函数和递归

时间:2012-01-01 16:15:01

标签: java function recursion if-statement ackermann

我试图在Java中编写递归Ackermann函数。但我觉得我在某个地方出错了!任何人都可以看看,检查并指出我正确的方向纠正我的代码?谢谢!

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;

        }

    }

5 个答案:

答案 0 :(得分:5)

这部分错了:

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

那应该是 A(m - 1,1)

答案 1 :(得分:5)

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

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));
    }
}

m == 0 && n == 0案例中应包含m == 0案例。

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

答案 2 :(得分:2)

有趣的是,您的问题的所有答案都指出了您在第一个版本中的错误,但没有说明第二个版本中的大错误

 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)&amp;&amp;(n == 0))。

答案 3 :(得分:1)

'if m = 0'规则适用于n的所有值,因此A(0,0)为1.

只有当m和n在进入函数时都是负数时才能使用'else'子句,这可以被诊断为异常。实际上,如果m或n为负数,则应诊断错误。或者,由于A(m,n)从不返回零,否则0可以被视为发出错误信号。

请注意,评估A(m,n)所需的堆栈深度与答案相同 - 而A(m,n)变得非常快。不要费心去尝试评估A(4,4);你的电脑没有足够的内存。

答案 4 :(得分:0)

第一个代码段没问题,但在第二种情况下它返回ackermann(m-1, n)而不是ackermann(m-1, 1)。默认情况,应该永远不会发生,应该抛出IllegalStateException,以防它实际发生。