首先是理解该方法的理论基础:
1.移位运算符的语法及运算规则
2.函数 scanf() 是从标准输入流stdio中读内容的通用子程序(注意是流,和c++中的cout一样)
如果不理解,请查阅资料,否则无法理解这个方法
下面进入正题:
假设一个二进制数11,我们都知道它对应的十进制数是3,
大部分人脑中进行了如下的惯性思维式思考:
第一位是1,第二位是2,所以1+2=3
但是如果是一个很长的二进制数呢?习惯了10进制数计算的人必然无法快速算出其十进制值,这是因为这种传统的方法涉及到了算术运算.有算术运算就涉及到数学上的公式,算法,那么有没有一种方法,可以让我们避免采用这种方法,把这种繁琐的步骤交给电脑来算,最后输出结果就行了呢?有的!
假设以下情形:
我们有一个十进制整型数n,n的值是0.于是此时n的二进制形式也是0。
这时,我们要将二进制数11转化成十进制数3,而不使用传统的算数方法(在本案例中传统方法是1+1乘 2的1次方)
移位法的思想既是:
由于int型的n为0,而十进制的0与二进制的0都是0,所以,我们可以对n进行移位,通过移位将n的二进制形式从0变成11,又因为n是int型,所以输出n的时候,是将n作为十进制整型输出的,也就是3。这就完成了二进制到十进制的转换。
PS:n虽然是整型,但当对n使用移位运算符时,编译器是将n看成一个二进制数,再移位的,移位后返回int型结果,也就是说,对十进制数使用移位运算符包含两次隐式转换,第一次是将n变成二进制数,第二次是将移位后的n变回十进制数.
举例:通过移位将11转化成10进制数3
首先,我们有一个初始的int型数n,n无论十进制值还是二进制值都为0,如何将二进制0变成二进制11呢?将11从左到右一个数字一个数字的读取,首先读取到第一个1,然后将n左移一位(由于此时n值为0,所以移位后n仍然是0),然后把刚才读取的1加到n上,此时n的二进制值变成1了;然后读取第二个1,然后将n左移一位(此时n的值为1,所以移位后n是10),然后把刚才读取的1加到n上,此时n的二进制值就变成11了;OK,n的二进制形式已经完成了由0到11的转变,此时直接以int型输出n,就得到了3。
以上过程中,我们仅仅将n的二进制形式通过移位变成了11,至于二进制11怎么变成十进制3的,这个过程我们不需要知道,因为我们把这个工作交给了编译器来处理。
以下是代码:
#include<stdio.h>
int main(void)
{int n=0;
char c;
printf("请输入一个二进制数:");
scanf("%c",&c); /*由于c为char型,所以scanf一次只能将一个数字储存在c中,剩下的数字和敲击的回车,仍然在输入流中,等待while循环体中的scanf读取*/
while(c=='0'||c=='1') /*该循环体的作用是将n的二进制形式0通过移位转变成以上输入的二进制数*/
{printf("%c",c); /*参考第12行*/
n=(n<<1)+c-'0'; /*一次(每读取一个数字)向左移一位,c为每一次读取的数字的ASCII值*/
scanf("%c",&c); /*重复循环读取输入流中的数字,直到遇到回车,循环终止*/
}
printf("的十进制数=%d\n",n); /*将转变完后的二进制数以十进制整型输出,得到结果("的"前面为刚才输入的二进制数,由第8行的printf输出)*/
return 0;
}
对于第9行中c-‘0’的解释:
c是字符型,所以c储存的是字符的ASCII值,而不是这个字符,’0’是一个字符常量,其值是对应的ASCII值,
由于ASCII表中0的值是48,1的值是49,而此处c只有可能是49或48,即当前的c若是1,则n的二进制形式在左移一位的同时,右边补上一个1,若是0,同理,补上一个0。与循环和移位配合,最终达到n的二进制形式与我们输入的二进制数相等的目的。