以前的一个同学去面试嵌入式软件工程师,然后遇到下面的题,一时半会居然不知道怎么做,发给我问我有没有思路,我看了一下
问题:
int x=0;int a=18;int b=24;求下列x的值。
x=(a&b)
x=(a&&b)
x=(a|b)
x=(a^b)
这个题目如果用代码来做也许非常简单,打开ide,输入以下代码
一分钟就能得到答案。
然而如果用笔算呢?
参考
https://blog.youkuaiyun.com/xiaopihaierletian/article/details/78162863
了解&,&&,|,^的运算
先看x=(a&b),
一个整数&上一个整数,按照规则,应该先将两个整数都转化成为2进制,然后按照与的规则逐位操作,
1、先把18转成2进制,关于转换规则参考如下
10进制转2进制,把18除2除2再除2
18/2=9,余0
9/2=4,余1
4/2=2,余0
2/2=1,余0
1/2=0,余1
余数从下往上,变成从左往右,即10010
记忆口诀:除2除到等于0,余从下往上,变成从左往右
2、再把24也转过来
24/2=12,余0
12/2=6,余0
6/2=3,余0
3/2=1,余1
1/2=0,余1
得11000
然后执行计算,
10010
&11100
=10000
按位与,全1为1,其他为0(相当于乘法计算)
然后转回10进制
2进制转10进制:
abcd.ef(2进制)=d*(2^0)+c*(2^1)+b*(2^2)+a*(2^3)+e*(2^-1)+f*(2^-2) (10进制)
个位数为 数值*(2^0),次方向左+1,向右-1
比如
1101.01(2)=1*(2^0)+0*(2^1)+1*(2^2)+1*(2^3)+0*(2^-1)+1*(2^-2)
比如之前计算出18是10010(2),可以验证一下,
0*1+1*2+0*4+0*8+1*16=18
然后负次方即为正次方的倒数,故
2^-2=1/(2^2)=0.25
所以上式=0.25+0+1+0+4+8=13.25
有一种更简便的计算,首先是个位数为 数值乘1,然后1向左乘2一次,向右÷2一次
abcd.ef(2进制)=d*(1)+c*(2)+b*(4)+a*(8)+e*(0.5)+f*(0.25) (10进制)
比如
1101.01(2)=1*(1)+0*(2)+1*(4)+1*(8)+0*(0.5)+1*(0.25)
=1+0+4+8+0+0.25=13.25
所以
10000=0*1+0*2+0*4+0*8+1*16=16
这就跟上面IDE的结果一样了
然后再看&&,
这个计算就非常简单了,只要不是0,都看做1,比如-1也看做1
那么18 && 24就是1,||同理
至于|,
则跟&一样,要转化为2进制,然后按照“或”的规则运算,即
10010
| 11000
= 11010
转为10进制
0*1+1*2+0*4+1*8+1*16=26
如果发现不对就检查一下10进制转2进制的计算,那里很容易出问题。
最后是^
这个符号在数学里是指数,但是在C语言里是异或,异或的运算一般我们比较难理解,它的运算规则是,相异为1,相同为0
0^0=0
0^1=1
1^0=1
1^1=0
还有一个说法,异或是或的不进位算法,也就是二进制加法中去掉高位只保留第一位的算法,注意上面的运算中,前三条都是或运算,只有最后一条1^1,在2进制计算中1+1应该等于10(2),那么去掉高位,就是0。
那么上面的运算就很简单了
10010
| 11000
=01010
转换为10进制:
01010(2)=0*1+1*2+0+1*8+0=10
那么问题到此结束,这一道题目看起来不难,但是需要一定的知识积累,包括进制转换的规则,运算符的理解等等。