C ++将递归函数重写为非递归函数 - 涉及MPIR&非常困难

时间:2013-03-19 09:55:52

标签: c++ gmp

我很难将函数从递归转换为非递归 使用MPIR的库变量“mpz_t”而不是“unsigned __int64”的函数。我也在考虑如何编写循环。当我把它递归时,它很容易,但是当我试图使它非递归时,很难!

unsigned __int64 exampleFunc( unsigned __int64 a,
                              unsigned __int64 b,
                              unsigned __int64 c )
{
    if( a <= 2 )
        return a + 1;
    if( b <= 4 )
        return b;
    if( c == 3 )
        return c - 1;
    if( b == 5 )
        c += 2;
    // How will I put these into a loop?
    return exampleFunc( a - 1, b - 2, c ) + exampleFunc( 0, b + 1, c - 1 );
};

部分问题是我们无法编写一个返回mpz_t值的函数。 我们只能写一个值(就像一个指针)。所以,这样的事情 不会起作用:

mpz_t exampleFunc( ... );

这意味着,这样的事情可以起作用:

void exampleFunc( mpz_t out, ... );

甚至是全局变量(不强烈推荐):

mpz_t g_out;
mpz_init( g_out );
void exampleFunc( ... ) { g_out = ? };

注意:

我们应该尽量不使用数组甚至是向量,因为数字会非常大 - 这就解释了为什么我从无符号__int64切换到mpz_t。除非我们真的需要......

请帮助,我真的很强调。感谢。

2 个答案:

答案 0 :(得分:1)

关于gmp的问题:尝试使用gmpxx.h - 你可以像返回一个整数那样返回mpz_class对象。

mpz_class withgmp( const mpz_class &a, const mpz_class &b, mpz_class c )
{
    if( a <= 2 )
        return a + 1;
    if( b <= 4 )
        return b;
    if( c == 3 )
        return c - 1;
    if( b == 5 )
        c += 2;
    return withgmp( a - 1, b - 2, c ) + withgmp( 0, b + 1, c - 1 );
}

请注意,我按值传递c,因为它可能在函数中被修改。

或者,如果必须使用普通C,则应该为结果传递第四个参数,如下所示:

void withmpz( mpz_t a, mpz_t b, mpz_t c, mpz_t result)
{
     // ... leaving out the boundary conditions
     mpz_t left; mpz_init(left);
     // ... leaving out code for adjusting a,b and c
     withmpz(a,b,c, left);
     mpz_t rightt; mpz_init(right);
     // ... leaving out code for adjusting a,b and c
     withmpz(a,b,c, right);
     mpz_add(result, left, right);
}

请注意mpz_t看起来好像是按值传递,但实际上它总是通过引用传递,所以a,b,c在调用withmpz之后会发生变化

问题的第二部分,如何将其转换为迭代,确实更难。一种方法是将其更改为基于堆栈的算法,其中每个迭代步骤用需要添加的2个值替换堆栈的顶部,直到可以立即计算一个,然后将其添加到最终结果,重复此直到堆叠中没有更多值。

答案 1 :(得分:0)

指向指针的指针可能是解决方案:您通过值传递指针指针并根据需要修改指针和指向的数据