Ackermann函数和递归

问题描述 投票:4回答:5

我试图用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;

        }

    }
java function recursion if-statement ackermann
5个回答
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


5
投票

这部分是错的:

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

应该是A(m - 1,1)


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


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);你的电脑没有足够的内存。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.