2013-03-19 107 views
1

我真的很難從遞歸函數轉換爲使用MPIR庫變量「mpz_t」而非「unsigned __int64」的非遞歸函數 。我也在想如何編寫循環。當我遞歸時,它很容易,但是當我試圖使它不遞歸時,它很難!問題的C++重寫一個遞歸函數爲非遞歸 - 涉及MPIR&非常困難

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。除非我們真的必須...

請幫助,我真的很強調。謝謝。

回答

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個值替換堆棧的頂部,直到可以立即計算一個值,然後將其添加到最終結果中,重複此操作直到堆棧中沒有更多值。

0

一個指針的指針可能是解決方案:你的指針按值傳遞指針和修改指針,它指向你的願望