双递归函数

时间:2018-04-15 21:11:19

标签: c++ recursion ackermann

我想编写S. Wolf的 A Tour Through Mathematical Logic 中定义的函数(Ackermann函数的修改版本),如下所示:

  

每n <(n,n)= n + 1

     

A(1,0)= 2

     

A(2,0)= 0

     

每m的A(m + 3,0)= 1

     

每m和n的A(m + 1,n + 1)= A(m,A(m + 1,n))

为了制作更快的程序,我使用了

这一事实
  • A(1,N)= N + 2

  • A(2,n)的= 2

  • A(3中,n)= 2 ^ N

以下是代码:

#include <iostream>
#include <cmath>

using namespace std;

long long A(long long m, long long n)
{
    if(m==0)
        return n+1;
    else if(m==1)
        return n+2;
    else if(m==2)
        return 2*n;
    else if(m==3)
        return pow(2,n);
    else if(m>=4 && n==0)
        return 1;
    else
        return A(m-1,A(m,n-1));
}

int main(void)
{
    long long m,n;
    cout << "m=";
    cin >> m;
    cout << "n=";
    cin >> n;
    cout << "A(m,n)=" << A(m,n) << endl;
    return 0;
}

似乎工作正常:用手,A(5,3)= 2 ^ 16,这就是我得到的结果。但是,程序输出A(5,4)= 4和A(5,5)= 2 ^ 16,而正确的结果非常大。我无法在代码中发现错误。你能告诉我有什么问题吗?提前谢谢。

1 个答案:

答案 0 :(得分:0)

正如NeilButterworth在评论中所说,错误结果背后的原因是溢出。

正如RobertAndrzejuk在评论中所建议的那样,我使用另一个库(GMP)处理大量数据。这是新代码:

#include <iostream>
#include <cmath>
#include <gmpxx.h>

using namespace std;

mpz_class pow(int a,mpz_class b)
{
    mpz_class res=1;
    for(int i=1;i<=b;++i)
        res*=a;
    return res;
}

mpz_class A(mpz_class m, mpz_class n)
{
    if(m==0)
        return n+1;
    else if(m==1)
        return n+2;
    else if(m==2)
        return 2*n;
    else if(m==3)
        return pow(2,n);
    else if(m>=4 && n==0)
        return 1;
    else
        return A(m-1,A(m,n-1));
}

int main(void)
{
    mpz_class m,n;
    cout << "m=";
    cin >> m;
    cout << "n=";
    cin >> n;
    cout << "A(m,n)=" << A(m,n) << endl;
    return 0;
}

该程序能够计算A(4,5),其中有19729位数字(我无法验证结果是否正确,但A(4,5)的确切位数确实是19729所以我相信结果是正确的)。然后当我要求它计算A(5,4)时,程序指示了分段错误,这真的很大。