反码补码
反码补码
原码:第一位表示符号位,0是正,1是负。其余表示值。 反码:正数的反码和原码相同。负数时第一个符号位不变,其他取反。 补码:正数的补码与与原码相同。负数时第一个符号位不变,其余各位取反,然后再加1。即负数时补码为反码加1。
原码 +1 0000 0001
-1 1000 0001
反码 +1 0000 0001
-1 1111 1110
补码 +1 0000 0001
-1 1111 1111
为何要有反码、补码
我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了。
如果用原码来计算1-1 = 0
1 - 1 =
1 + (-1) =
[00000001]原 + [10000001]原 =
[10000010]原 =
-2
如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.
为了解决原码做减法的问题, 出现了反码:
1 - 1 =
1 + (-1) =
[0000 0001]原 + [1000 0001]原 =
[0000 0001]反 + [1111 1110]反 =
[1111 1111]反 = [1000 0000]原 =
-0
发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.
于是补码的出现, 解决了0的符号以及两个编码的问题:
1-1 =
1 + (-1) =
[0000 0001]原 + [1000 0001]原 =
[0000 0001]补 + [1111 1111]补 =
[0000 0000]补=
[0000 0000]原
这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:
(-1) + (-127) =
[1000 0001]原 + [1111 1111]原 =
[1111 1111]补 + [1000 0001]补 =
[1000 0000]补
-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示
.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)
简单总结:原码运算不能让符号位参与运算、反码运算会出现
使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127]。
一个+0表示为:00000000,一个-0表示为:1000000,因为符号位不算在里面,所以就会有两个0,所以从一开始发明二进制的时候,就把-0规定为-128,之所以这样是因为[1000 0000]补 就是-128.
(这是国内教材中的解释)
补码可以表示负数,且与其他数运算的时候符号位也一起参与运算。这样减法可以用加法实现。除法可以用减法实现,10 /3 可化为 10 -3 -3 -3最后余1,见了3次,就是商3余1。乘法直接用加法实现即可。