原码,反码,补码,和取反运算——适用于二进制底层的概念理解


首先,看这篇文章之前,你需要的是不必纠结,比如:为什么正数的原码反码补码就一样呢,负数的原码反码补码就各不相同呢?

看这篇文章之前你只需要记住,这是人为规定的。你可能会想,为什么要这样人为规定呢,我现在只能告诉你,这样规定有利于计算机底层对数字进行操作,

也就是说,这种规定对计算机的底层硬件要求简化了,技术实现起来更简单。

 

我们日常用的数字是给我们人类用的,所以叫真值。而机器(计算机)理解的数字通常是二进制所组成的数字,所以称为机器数。

二进制在内存中以补码形式在其中存储,计算机计算数字是通过补码的形式进行计算的,也就是说不管正数,还是负数在计算机里面,都要用补码来表示。

 

在原码,反码,补码中,最高位来表示正负,用0表是正,1表示负;

如十进制的10表示为:+1010--->原码:0 1010;-1010--->原码: 1 1010;

 

 

笔记一:原码,反码,补码

*规则:

正数中:原码=反码=补码;例子拿上面的:+1010---> 0 1010;

+1010--->原码: 0 1010;(最高位0表示正号)

+1010--->反码: 0 1010;

+1010--->补码: 0 1010;

+1010--->移码: 1 1010(补码符号位取反)

负数中的规则如下:例子拿上面的:-1010---> 1 1010;

-1010--->原码: 1 1010;(最高位1表示负号)

-1010--->反码: 1 0101;(符号位不变,数值位:0变1,1变0)

-1010--->补码: 1 0110;(符号位不变,数值位:0变1,1变0。最后得出来的数字再加1。简单点总结为:“反码加1”)

-1010--->移码: 0 0110(补码符号位取反)

最后注释:移码:无论正负数,都是补码的符号位取反。

 

 还有这里解释一下,为什么计算机实际计算数字是用补码进行运算的,如果你看了我上面的例子的话,应该清楚了,不管是正数,还是负数,在计算机中,补码最高位都是1,

意思就是说,补码的作用,把正数规定还是正数,而负数还是负数,但是正负数进行运算的时候转变为加法形式,例如:3-5变成3+(-5).这样子,计算机底层很容易实现加法运算。

这样子我们设计程序的时候,实际在设计加法运算。

 

 推荐你看一下这篇文章:https://www.jianshu.com/p/2f9630dd2016,因为如果负数不采用补码进行运算,那么其实会发生溢出的。

 

再讲深一点的话:

关于补码,我们做进一步解释:

 (1)化减为加:

由于计算中的CPU只有加法器,没有减法器,采用补码可以化减数运算为加数,例如原来的:1-1=0,化为计算机可处理的1+(-1)=0

(2)10000000与00000000都是零吗?——关于-128的由来

补码还解决了原码中存在两个0 的问题(即+0 和 -0),以8进制为例,java中byte的取值范围应该是-127~ -0和+0~ 127 即存在-0和+0 ,

但是在两个0转换为补码后,分别为10000000和00000000,00000000它还是0,但是我们人为地规定10000000表示-128,这就是上面取值范围中-128的由来。

这里再强调一下,10000000和00000000都是补码,而不是原码。

 

 如果你还想了解为什么需要反码,补码,可以看看另外一篇文章:https://www.cnblogs.com/hmy-666/p/12551063.html

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

笔记二:取反。

注意:取反运算不等同于求反码!

*“~”这个小波浪号叫取反(下面例子都是10进制化2进制取反)。~10=-11,~(-10)=9。

规则:对一个数进行取反运算时,先对这个数按位取反得出值X1,再对X1求补码,即得出结果。

例子:对57进行取反。

其57按位取反后二进制表示为(表示一个字节  8bit) 1100 0110

1100 0110  (最前面的第一位表示符位 )

1表示次数为负数

1100 0110  可表示为     -(2^6+2^2+2^1) = -70;

不管正数,还是负数在计算机里面,都要用补码来表示

即补码=符号位以后的按位取反后加1    

反之减1

所以 -70 = 1100 0110 符号位以后按位取反后再加一为 1011 1010 = -58

即~57 = -58;

负数反之即可。

其实简单点,这个符号的运算法则是:如果一个数取反,那么值等于这个数的相反数再减去1。总结:~X=(-X-1)。

------------------------------------------------------------------------------------------------------------------------------------------------------

 注:八位二进制扩展到十六位二进制

负数扩展,扩展的高位不断补1

-13
8位原码:1000 1101
8位补码:1111 0011
16位补码:1111 1111 1111 0011          根据负数转换规则由16位补码可以推出16位原码:1000 0000 0000 1101
根据前面的知识,由于-13的最高位为1,所以直接在最高位前面添加8个1即可变为16位补码,即1111 1111 1111 0011(与前面由原码求补码的结果一致)。

正数扩展,扩展的高位不断补0
13
8位原码:0000 1101
8位补码:0000 1101
16位补码:0000 0000 0000 1101    根据正数转换规则由16位补码可以推出16位原码:0000 0000 0000 1101

根据前面的知识,由于13的最高位为0,所以直接在最高位前面添加8个0即可变为16位补码,即0000 0000 0000 1101(与前面由原码求补码的结果一致)。

 

 

 

 

 

注:除了1000 0000人为规定为-128外,其它都是根据规则转换为原码输出的形式


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM