首先,看这篇文章之前,你需要的是不必纠结,比如:为什么正数的原码反码补码就一样呢,负数的原码反码补码就各不相同呢?
看这篇文章之前你只需要记住,这是人为规定的。你可能会想,为什么要这样人为规定呢,我现在只能告诉你,这样规定有利于计算机底层对数字进行操作,
也就是说,这种规定对计算机的底层硬件要求简化了,技术实现起来更简单。
我们日常用的数字是给我们人类用的,所以叫真值。而机器(计算机)理解的数字通常是二进制所组成的数字,所以称为机器数。
二进制在内存中以补码形式在其中存储,计算机计算数字是通过补码的形式进行计算的,也就是说不管正数,还是负数在计算机里面,都要用补码来表示。
在原码,反码,补码中,最高位来表示正负,用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外,其它都是根据规则转换为原码输出的形式