2012-12-07 21 views
5

阿克曼函數的我寫在C程序,其計算用於由用戶輸入的2個非負整數的阿克曼值。程序檢查整數是否爲非負數,如果它們是計算它們的阿克曼值,然後詢問新輸入或退出。該程序在C工作正常,我沒有問題。這裏是我的代碼:備選實現用C

int ackermann(int m, int n){ 
     if (m == 0) return n + 1; 
     if (n == 0) return ackermann(m - 1, 1); 
     return ackermann(m - 1, ackermann(m, n - 1)); 
} 

,但事實上,因爲我們用C的修改版本(基本相同,但有一些不同的語法規則),它模擬了語法大學課程的需求和規則MIPS彙編語言。更具體地說,我們使用寄存器來處理除數組和結構之外的所有數據。此外,我們還不能使用,同時,或做-while循環,我們使用如果轉到語句來代替。所以我用這種語言編寫了以下程序(正如我所說的,它不過是C語言)。我的問題是,它只適用於(x,0)和(0,y)用戶輸入(x和y是非負數)。它不適用於(4,1),(3,2)和通常所有沒有零點的輸入。我知道,由於大量的這些計算,它不能有效地處理像(10,10)這樣的大數字。但我希望它像阿克曼(3,1)== 13.一些簡單的工作,投入更多關於阿克曼功能,請看到這一點:http://en.wikipedia.org/wiki/Ackermann_function 這裏是我的代碼:

//Registers --- The basic difference from C is that we use registers to manipulate data 
int R0=0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15,R16,R17,R18,R19,R20,R21, 
R22,R23,R24,R25,R26,R27,R28,R29,R30,R31; 

int ackermann(int m, int n){ 

    R4 = m; 
    R5 = n; 

    if(R4 != 0) 
     goto outer_else; 
    R6 = R5 + 1; 
    return R6; 

    outer_else: 
     if(R5 != 0) 
      goto inner_else; 
     R7 = R4 - 1; 
     R6 = ackermann(R7, 1); 
     return R6; 

     inner_else: 
      R8 = R5 - 1; 
      R9 = ackermann(R4, R8); 
      R10 = R4 - 1; 
      R6 = ackermann(R10, R9); 
      return R6; 
} 

回答

6

我覺得你的問題是,這些寄存器的值定義爲全局變量,他們正在被以ackermann()內呼叫更新,而外部呼叫的方式取決於這些價值觀不改變。例如,看看在你的ackermann()註冊版inner_else條款:調用ackermann(R4, R8),並在接下來的語句依賴於R4的電流值,但它到達賦值語句前的遞歸調用改變R4的設置。

兩個常見的解決方案:

  1. 定義您註冊爲本地變量,讓編譯器跟蹤每個函數調用狀態的爲您服務。

  2. 在進入您的ackermann()函數時,手動保存所有寄存器的狀態,然後在退出時恢復它們。

雖然解決方案1是比較容易的,我懷疑你的老師可能更喜歡解決方案2,因爲它說明了使用由編譯器在其生成的彙編代碼來處理實際登記管理的一種技術。

+0

關於第二溶液,將其登記我應該壓入和彈出?我應該在哪裏恢復它們(流行)?謝謝您的回答:) – mgus

+0

的安全,天真的解決方案是保存(恢復)在進入所有寄存器(所有的出口點)。更有效的方法是隻保存在遞歸函數中任何地方修改的寄存器,然後在退出時恢復那些相同的寄存器。最有效的方法是在寫入之前節省需求,這樣只會節省那些真正改變的寄存器。後一種選擇的缺點是你必須跟蹤你修改了哪些寄存器(所以你知道哪些要恢復),這需要另一個數據結構和一些額外的邏輯。 –

+0

我寧願去安全的方式..我根據你告訴我的內容改變了代碼,但仍然不起作用。首先,我使用了6個全局變量** int a,b,c,d,e,f; **,然後在賦值後的Ackermann函數中** R4 = m; R5 = n; ** I增加:/ * PUSH */ a = R4; b = R5; c = R7; d = R8; e = R9; f = R10;並在每次返回之前添加:/ * POP */ a = R4; b = R5; c = R7; d = R8; e = R9; f = R10;我究竟做錯了什麼?請幫忙:)謝謝@Marc Cohen – mgus