信盈达—您身边的嵌入式&人工智能专家
全国免费咨询热线:400-8788-909

[干货]按位取反怎么算?~图文详解

时间: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