我希望人们准确地解释以下功能。
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 );
}
答案 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)
答案 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 = b0
和bj * 2^j % 2 = 0
j >= 1
时2^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
这是第二个关键事实。
所以,让我们把我们学到的东西放在一起。
n
的二进制表示是n
的二进制表示,其中附加了n % 2
的二进制表示的最后一位数字。 这是关键的第二个事实。
n = 0
的二进制表示的最后一位可以通过计算n
来计算。 这是关键事实第一。
所有这一切都是正确的,除了一个案例: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);
}
从这段代码中,您可以看到它:
考虑到给定基数为10的数字,我们可以除以10.余数和被除数是最低有效数字,数字分别移位一位数。这也适用于二进制:然而,除了除以10,我们除以2。
基本上,算法是这样的:
如果以递归形式编写,然后交换递归和打印,则按照从最重要到最不重要的顺序打印数字。瞧。
答案 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,其余部分是下一个最低有效位。重复此过程,直到商变为零。