2012-03-17 49 views
0

我需要對下面的一段代碼一些解釋:回報的說明模

它用於將十進制數二進制數字代碼: 距離的教程,但我感到困惑。

void binary(int); 

void main(void) { 
int number; 

cout << "Please enter a positive integer: "; 
cin >> number; 
if (number < 0) 
    cout << "That is not a positive integer.\n"; 
else { 
    cout << number << " converted to binary is: "; 
    binary(number); 
    cout << endl; 
    //cin.get(); 
} 
} 

void binary(int number) { 
int remainder; 

if(number <= 1) { 
    cout << number; 
    return; 
} 

remainder = number%2; 
binary(number >> 1);  
cout << remainder; 
//cin.get(); 
} 

我用斷點來觀察數據通過程序,但最後我不能跟着它。

什麼我看到:

它需要一個數,並且如果所述數目< = 1它打印該數字(0或1)。

但在它之前,它首先計算該數字的模數,並將其餘數。 然後它移動到數字的右邊或者相同,直到數字小於或等於1.

但是然後它將「cout餘數」保持多次(取決於計算的多少0/1) 但這怎麼可能? 餘數是一個緩衝區嗎? (我認爲它保持覆蓋(因爲它是int),但它看起來像不斷增加位,然後打印幾次)?

有人可以解釋這對我來說慢?

+4

這個問題實際上是關於遞歸。一旦你理解了遞歸的概念,代碼就會有意義。 – masaers 2012-03-17 09:25:38

回答

1

的int不被覆蓋,因爲它[INT]被重新分配作爲每次調用該函數binary()遞歸,所以如果調用它n倍自動變量遞歸,實際上分配n不同int s爲remainder

因此,它被「記住」,因爲它們是不同的局部變量。分配通常是在調用堆棧

做它的工作原理:讓我們來看一個例子的堆棧:binary(5)

|number=5, remainder = 1| 
------------------------- 

現在,你重新調用binary()number = 5/2=2

|number=2, remainder = 0| 
|number=5, remainder = 1| 
------------------------- 

並再次用number = 2/2 = 1 現在,您重新調用binary()number = 5/2=2,並獲得:

|number=1, remainder = 1| 
|number=2, remainder = 0| 
|number=5, remainder = 1| 
------------------------- 

現在,停止條件是真的,因爲number <= 1 - ,讓您打印number [這是1],彈出從調用堆棧中的第一個元素:

|number=2, remainder = 0| 
|number=5, remainder = 1| 
------------------------- 

和打印0,因爲它是調用堆棧頂部的剩餘部分。

做同樣在調用堆棧中的下一個「元素」:

|number=5, remainder = 1| 
------------------------- 

和打印最後剩餘部分,1。

+0

謝謝。非常清楚。調用堆棧。 – Plumbum7 2012-03-17 09:36:04

0

任何數字可以寫爲sum(ai*2^i)以及sum(bi*10^i)。 我會解釋小數,因爲它更清晰。鑑於12345,

檢索數字,你做

12345 % 10 = 5 (op1) 
12345/10 = 1234.5 = 1234 in a int (op2) 
1234 % 10 = 4 (restart) 
1234/10 = 123.4 = 123 in a int 

等等

在這種情況下

op1 is equivalent to remainder = number%2; (modulo by the base) 
op2 is equivalent to number >> 1; (division by the base. bitshifting is division by 2) 

restart意味着分工的結果重新啓動。這就是爲什麼我們有一個遞歸 調用,使用binary(number >> 1);假設我在基地調用這個函數與abcdef 2.

binary(abcdef) 
    binary(abcde) 
    binary(abcd) 
     binary(abc) 
      binary(ab) 
       binary(a) 
        cout << number;//a 
       cout << remainer;//b 
      cout << remainer;//c 
     cout << remainer;//d 
    cout << remainer;//e 
    cout << remainer;//f 
0

由於binary是一個遞歸函數,你有這樣的事情發生(每個縮進是一個附加級別遞歸):

binary call #0 
calculate remainder0 
    recursive binary call #1 
    calculate remainder #1 
     recursive binary call #2 
     calculate remainder #2 
      recursive binary call #3 
      print number 
     print remainder #2 
    print remainder #1 
print remainder #0 

遞歸使用打印餘在計算的相反的順序,因爲你可以看到上方。不要混淆number參數 - 它是否在每次遞歸調用時被複制都不相關。你也可以使用一個全局變量,它可以工作(然後,它將被「就地修改」,這就是你所說的「被覆蓋」)。

重要的部分是,對於每次遞歸調用,原始數字向右移一位,這就是number參數。

這裏是沒有遞歸相當於:

#include <iostream> 
#include <sstream> 
#include <algorithm> 

using namespace std; 

string binary(int); 

int main(void) { 
    int number; 

    cout << "Please enter a positive integer: "; 
    cin >> number; 
    if (number < 0) 
     cout << "That is not a positive integer.\n"; 
    else { 
     cout << number << " converted to binary is: "; 
     cout << binary(number) << endl; 
    } 
    return 0; 
} 

string binary(int number) { 
    stringstream ss; 

    do { 
     ss << number % 2; 
     number >>= 1; 
    } while (number >= 1); 

    string s = ss.str(); 
    reverse(s.begin(), s.end()); 
    return s; 
}