[干货]按位取反怎么算?~图文详解
时间:2019-04-26 00:00:00
来源:信盈达
作者:信盈达
学习电路,C语言或者其他上层语言都会涉及到位操作符,而其中的按位取反~最令人费解,牵扯出一连串的东西:原码,反码,补码等等,让人看得云里雾里,计算不出正确的结果,真真的是让人恨得牙痒痒。
所谓天下武功唯套路不破,今天小编就给大家解答下按位取反的计算套路,让你以后遇到无论正数还是负数取反都不会心里犯怵,清清楚楚的计算流程,明明白白的确定答案。
1、二进制
在了解计算规则之前,我们要先来了解下二进制是什么,为什么要使用二进制。
像我们日常使用的数字:1,2,3,4......等,在计算机中被称为十进制数,逢十进一,底数为10。
那么类似地二进制也是一种计数的方式,使用0和1两个数码来表示数字,逢二进一,它的底数为2。
电脑处理的数据不管输入内容是什么形式,都会转换为二进制数后再处理。
所以我们在进行位运算的时候,也要将十进制的数转为二进制的数后,再计算。
那么,十进制数如何转化为二进制数呢?我们以125为例,来计算下它对应的二进制数。
计算过程:十进制数除以2,商作为第二次的被除数,每一次的余数保留,直到最后的商小于2为止。然后将所有的余数倒着写,每4位为一组(二进制在书写时,通常以4位为一组),最右边不够四位的补0。
如:111 1101 最左边不够4位,要补0凑够4位,即0111 1101。
接下来,我们再来看一下二进制转十进制:
二进制是逢二进一的,也就是二进制的1就是十进制的1,当二进制的1加上1时,它就进位了,变成了10,也就是说:
1是一个1, .......20
10是两个1就是一个2 .......21
100是10*10即两个2相乘 ...... 22
1000是10*10*10即三个2相乘 ....... 23
........
所以,二进制转十进制时,先将二进制的位数每四个为一组补齐,然后使用每位上面的数字乘以对应的2的幂次,从左到右依次是20,21,22,23.......,然后再相加,如:
0
|
1
|
1
|
0
|
1
|
0
|
0
|
1
|
27
|
26
|
25
|
24
|
23
|
22
|
21
|
20
|
128
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
所以,二进制的0110 1001对应的十进制数计算就是:
0*27+1*26+1*25+0*24+1*23+0*22+0*21+1*20
=1*64+1*32+1*8+1*1
=105
2、按位取反运算符
位操作符有:&(按位与)、|(按位或)、^(按位异或)、~(按位取反)、<<(按位左移)、>>(按位右移),今天我们只说~(按位取反)这个运算符。
既然是位运算符,那么它操作的就是二进制数据,那我们一定要先将要操作的数先变成二进制再计算,一般我们使用的都是十进制数,十进制数转二进制数的方法上面我们已经说过了,这里就不赘述了。
首先,让我们来看一下取反操作的定义:~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1变0。原理简单但是实际使用起来并不容易。
在计算机中一个整型数(int)占4字节,1字节8位,所以数字5在计算机中存储占32位,比如:5,我们很容易能够得到它的二进制是:
0000 0000 0000 0000 0000 0000 0000 0101
那么按照定义的取反就是
1111 1111 1111 1111 1111 1111 1111 1010
最高位是1表示它是个负数,其他位进行二进制转十进制数,这个数值非常大,但是因为是负数,所以它代表的数很小很小。
然而,计算机的运算结果是:
那么,这个-6是怎么算出来的呢?
这里就要涉及到正、负数在计算机里的存储问题了。
3、数据存储与计算
在计算之前,我们要先了解数据在计算机中的存储问题。
计算机内部在做数学运算时(也就是计算机的0和1的运算),都是以补码为标准的,说白了 计算机中就一种码那就是补码,而现实社会中的编码规则,例如原码、反码都是我们自定义的,为了和计算机中的补码形成转换关系。
所以说在我们手工计算这类由计算机计算的01运算,要站在计算机的角度。因此首先就要将我们的原码反码什么的全都先转为补码,再来计算,这样才能使得正数和负数的表示统一起来。
3.1、求补码
那么,正数和负数的补码如何求呢?这里我们以7和-7为例来讨论下正数和负数求补码的方法。
3.1.1、正数补码
正数的原、反、补码都是它本身;这是一条定理,所以直接使用就ok。
因此7的补码就是:
0000 0000 0000 0000 0000 0000 0000 0111
这里我们可以简写成:0000 0111
3.1.2、负数补码
这里我们分两种情况,一种是求十进制负数的补码,一种是正数取反后获得的二进制负数的补码。
3.1.2.1、十进制负数求补码
规则:负数的绝对值取反后,+1
以-7为例:
|-7| = 7
原码
|
0000
|
0111
|
取反
|
1111
|
1000
|
+1
|
1111
|
1001
|
所以得到-7的补码就是:
1111 1001
这就是-7在计算机中的表现形式。
3.1.2.2、二进制负数求补码
规则:保持符号位不变,其他位取反后,+1
以(1111 1000)为例:
原码
|
1111
|
1000
|
取反
|
1000
|
0111
|
+1
|
1000
|
1000
|
*红色字体代表的是负数的符号位。
因此二进制负数 1111 1000的补码就是:
1000 1000
有了补码之后我们就要去做取反操作了。
3.2、取反
|
7
|
-7
|
计算机中补码形式
|
0000 0111
|
1111 1001
|
取反
|
1111 1000
|
0000 0110
|
结果类型
|
负数
|
正数
|
结果要以补码形式存储
|
结果原码 1111 1000
结果反码 1000 0111
结果补码 1000 1000
|
结果原码 0000 0110
结果反码 0000 0110
结果补码 0000 0110
|
结果十进制数
|
-8
|
6
|
*红色字体代表的是负数的符号位。
取反总结
-
取反:正数变负数,负数变正数
-
取反后,如果结果为负数,要计算它的补码,根据计算出的补码得到最后的十进制结果。
-
取反后,如果为正数,则其原码、反码、补码一样,因此,可以直接计算出十进制结果。
取反使用的定理
-
二进制正数的原码、反码、补码都一样
-
二进制负数的在计算机中采用补码的方式表示,所以遇到负数先求补码。
3.3、取反公式
前辈们在大量实验的基础上总结出了取反的计算公式:
~x = -(x+1)
大家可以使用这个公式去验证一下自己的计算结果是否正确。
4、总结计算流程
4.1、正数取反
步骤一:按位取反
步骤二:结果为负数,求结果补码(方法:负数符号位不变,其他位取反,然后+1)
步骤三:得到结果,计算出十进制结果
4.2、负数取反
步骤一:先求补码(方法:绝对值的二进制形式取反,然后+1)
步骤二:得到补码,即负数在计算机中的表现形式,然后取反
步骤三:得到正数,直接计算十进制结果
相信到这里,大家对取反操作的计算都明白了吧?赶紧去验证一波吧!
如果想要获取更多嵌入式相关课程信息及学习资料,可以咨询课程顾问老师:高老师(18925216388)