【问题标题】:Explanation of return modulo返回模数的解释
【发布时间】:2012-03-17 09:18:12
【问题描述】:

我需要一些关于以下代码的解释:

用于将十进制数转换为二进制数的代码: 它来自一个教程,但它让我感到困惑。

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();
}

我使用断点观察数据通过程序,但最后我无法跟踪它。

我看到了什么:

它需要一个数字,如果数字

但在此之前,它首先计算该数字的模数并将其放入余数中。 然后它向 number 的右边移动一点或者做同样的事情,直到 number 小于或等于 1。

但随后它会多次保持“cout 余数”(取决于计算出多少 0/1) 但这怎么可能? 余数是缓冲区吗? (我认为它一直被覆盖(因为它是 int),但看起来一直在添加位然后打印几次)???

谁能给我慢慢解释一下?

【问题讨论】:

  • 这个问题真的是关于递归的。一旦你理解了递归的概念,代码就会变得有意义。

标签: c++ if-statement modulo


【解决方案1】:

int 不会被覆盖,因为 每次您递归调用函数 binary() 时,它 [int] 都会重新分配为自动变量,因此如果您调用它 n 次递归地,你实际上为remainder分配了n不同的ints。

因此,它被“记住”,因为它们是不同的局部变量。分配通常在调用堆栈上进行

它是如何工作的:让我们看一下堆栈示例:binary(5):

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

现在,你用number = 5/2=2重新调用binary()

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

再次使用number = 2/2 = 1 现在,你用number = 5/2=2 重新调用binary(),得到:

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

现在,停止条件为真,因为number &lt;= 1 -,所以你打印number [which is 1] 并从调用堆栈中弹出第一个元素:

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

并打印 0,因为它是调用堆栈顶部的余数。

并对调用堆栈中的下一个“元素”执行相同的操作:

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

并打印最后的余数 1。

【讨论】:

    【解决方案2】:

    任何数字都可以写成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 &gt;&gt; 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
    

    【讨论】:

      【解决方案3】:

      由于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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-03
        • 1970-01-01
        • 2015-01-16
        • 1970-01-01
        • 2021-09-01
        • 2013-03-25
        • 2018-05-10
        • 2020-11-21
        相关资源
        最近更新 更多