函数从dec转换为bin,由3行组成,需要说明

时间:2013-08-07 05:05:58

标签: c

我希望人们准确地解释以下功能。

void ToBin(int n){
  if (n>1)
     ToBin( n/2 );
  printf( "%d", n%2 );
}

例如:
如果我输入7,那么转换为二进制111会发生什么(函数行为)。

我希望我能逐步解释。


修改
相同的功能,但更清楚地打印结果。

void ToBin( int n ){
   printf("%d/2= %d -> %d\n", n, n/2 ,n%2);
   if (n>1)
      ToBin( n/2 );
}

10 个答案:

答案 0 :(得分:5)

特别是7:

首先,n = 7,所以n>因此,在n / 2 = 3时再次调用ToBin。

现在,n = 3,所以n>因此,在n / 2 = 1时再次调用ToBin。

现在,n = 1,因此n不大于1.因此,打印1%2 = 1,控制跳回到前一帧。

这里,n = 3,打印3%2 = 1,控制再次跳回一帧。

这里,n = 7,打印7%2 = 1,当剩下这个函数并且不再有ToBin帧时,控制权返回到最初调用ToBin的函数。

通常,此功能的工作原理如下:

数字的二进制表达式等于该数字的一半的二进制表达式,并附加原始数字的最低位。

因此,该函数重复获得输入一半的二进制表达式,直到该值为单个位。然后,打印该位作为数字的最重要位,随后,每个位按重要性的降序排列。

答案 1 :(得分:3)

这是一个递归函数调用。 n%2基本上只是截断整数的最后一位(二进制表示)。 (2因为二进制是基数2,所以两个可能的基数)。 n/2删除最低有效位(通过整数除法)并将其传递给下一个递归级别。

因此,每个递归级别都会修剪它传递的整数的最低有效位,直到某个级别的整数不为1.如果为1,则if失败并且不再进行递归调用。现在递归回滚。首先执行最后一次递归调用的printf,它将打印调用者传递的整数的最低有效位。因此,在级别k,数字的k ^位基本上被打印。因为在k级别,在递归函数调用链上删除了k-1最低有效位,并且级别k处的调用具有k-1最低有效位的整数除去。因此,在每个级别,printf打印它传递的整数的LSB,直到递归回滚到顶部。

这是一个图形表示。为n = 10。然后n的二进制文件为1010。尝试用不同的值自己绘制这些图表,以便更好地理解。

          ToBin (10 = 1010)          print 10%2 = 0
             |                           ^
             call ToBin (10/2)           |
             |                           |
             V                           |
          ToBin (5 = 101)            print 5%2 = 1
             |                           ^
             call ToBin (5/2)            |
             |                           |
             V                           |
          Tobin (2 = 10)             print 2%2 = 0
             |                           ^
             call ToBin (2/2)            |
             |                           |
             V                           |
          ToBin (1 = 1)              print 1%2 = 1
             |                           ^
             if condition fails,         |
             |  roll back.               |
             |                           |
             |                           |
             +------>------>------>------+

答案 2 :(得分:2)

order    call    print
  1    ToBin(7)    1
          ↓        ↑
  2    ToBin(3)    1
          ↓        ↑
  3    ToBin(1) →  1

那是Recursion

也许你应该找到它的递归方程式。

答案 3 :(得分:2)

为了找到数字的base-2表示,我们寻找位b0...bn,使

n = bn * 2^n + b_(n - 1) * 2^(n - 1) + ... + b1 * 2^1 + b0 * 2^0

现在我们专注于寻找b0, b1, ..., bn。注意

(bn * 2^n + b_(n - 1) * 2^(n - 1) + ... + b1 * 2^1 + b0 * 2^0) % 2 = b0

b0 * 2^0 % 2 = b0bj * 2^j % 2 = 0 j >= 12^j % 2 = 0 j >= 1 n = bn * 2^n + b_(n - 1) * 2^(n - 1) + ... + b1 * 2^1 + b0 * 2^0 => n % 2 = (bn * 2^n + b_(n - 1) * 2^(n - 1) + ... + b1 * 2^1 + b0 * 2^0) % 2 = b0 b0 = n % 2所以,

n / 2 = (bn * 2^n + b_(n - 1) * 2^(n - 1) + ... + b1 * 2^1 + b0 * 2^0)
      = bn * 2^(n - 1) + b_(n - 1) * 2^(n - 2) + ... + b1 * 2^1

我们发现n / 2这个关键事实第一

现在,让我们除以2:

n

现在,让我们停在这里。让我们仔细看看 n = bn b_(n-1) ... b1 b0 n / 2 = b_n b_(n-1) ... b1 的二进制表示。请注意,它恰好等于n的二进制表示,只是最后一位被切断。那是

n / 2

这是第二个关键事实

所以,让我们把我们学到的东西放在一起。

  1. n的二进制表示是n的二进制表示,其中附加了n % 2的二进制表示的最后一位数字。 这是关键的第二个事实

  2. n = 0的二进制表示的最后一位可以通过计算n来计算。 这是关键事实第一

  3. 所有这一切都是正确的,除了一个案例:0时。在这种情况下,2的二进制表示为n = 0。如果我们尝试使用n除以的规则,我们永远不会停止除以2.因此,我们需要一个在n / 2时捕获的规则。

    因此,要计算n % 2的二进制表示,首先计算n = 0的二进制表示,然后附加// print binary representation of n void ToBin(int n) { if(n > 1) { // this is to handle zero! ToBin(n / 2); // this will print the binary representation of n } print(n % 2); // this will print the the last digit } 的结果,但一定要处理{{1}的情况}}。我们在代码中写一下:

    {{1}}

答案 4 :(得分:1)

你输入7所以

call 1) 7>1 true ,call ToBin(7/2)=ToBin(3.5) , pending print(7%2)=1
call 2) 3>1 true ,call ToBin(3/2)=ToBin(1.5) , pending print(3%2)=1
call 3) 1>1 false ,dont call ToBin(1/2), print(1%2)=1

print 1
pop function activation record for call 3)
pending print 1
pop function activation record for call 2)
pending print 1
pop function activation record for call 1)
So your output is 111

答案 5 :(得分:1)

递归可能会让它更难以理解。首先,请注意,如果我们重新排序语句:

void ToBin(int n){
  printf( "%d", n%2 );
  if (n>1)
     ToBin( n/2 );
}

现在将以相反的顺序打印数字。当然,这不是你想要的,但是现在递归调用最后,转换成迭代形式更容易:

void ToBin(int n) {
  do {
    printf( "%d", n%2 );
    n = n/2;
  } while(n > 1);
}

从这段代码中,您可以看到它:

  • 打印模数为二的数字。
  • 将数字除以2。
  • 如果数字大于1,则重复。

考虑到给定基数为10的数字,我们可以除以10.余数和被除数是最低有效数字,数字分别移位一位数。这也适用于二进制:然而,除了除以10,我们除以2。

基本上,算法是这样的:

  • 打印最不重要的数字。
  • 将数字移到一位数。
  • 如果数字大于1,请重复。

如果以递归形式编写,然后交换递归和打印,则按照从最重要到最不重要的顺序打印数字。瞧。

答案 6 :(得分:1)

ToBin(7)
n=7 if(7>1)
    ToBin(7/2=3) call ToBin(3)
    {
     ToBin(3)
     n=3 if(3>1)
     ToBin(3/2=1) call ToBin(1)
     {
       ToBin(1)
       n=1 if(1>1)
         false
       print n%2=> 1%2= 1
      }     
    print n%2=> 3%2= 1
    }
print n%2=> 7%2= 1

答案 7 :(得分:0)

通过以下面的方式除以2来递归打印剩余(%操作)

ToBin()在输入参数n大于1

之前调用自身
 2 | 7
 ------     remainder   /|\
 2 | 3  ---> 1           |    down to top
 ------                  |
   | 1  ---> 1           |
     -------------------->

答案 8 :(得分:0)

如果n为7,则每个级别的递归调用都是

 1.ToBin(7)--> 2. ToBin(3) --> 3. ToBin(1)

现在返回值,并且在第一种情况下为1,因为7%2是1,

在第二种情况下1为3%2为1,在第三种情况下为1,1%2为1。

因此111是输出

注意:每个递归调用在其堆栈中都有自己的n,因此n在第一次调用时为7,在第二次调用中为3,在第三次调用中为1。

答案 9 :(得分:0)

函数ToBin使用递归(函数调用自身)并使用this algorithm

  

要从基数为10的整数转换为基数为2(二进制)的等价数,则将数除以2,其余为最低有效位。 (整数)结果再次除以2,其余部分是下一个最低有效位。重复此过程,直到商变为零。