原码:十进制数的带符号的二进制形式,例如-5的原码是1000 0101
。
以计算 (+3) + (-5)
为例,如果直接将两个数的原码相加,有两个问题:
- 符号位相加没有意义,因为一个正数和一个负数的符号位相加始终为负数的符号位,与这两个数相加的实际结果的正负没有关系
- 非符号位的相加实际上相当于两个数的绝对值相加,这不符合预期
0000 0011
+1000 0101
----------
1000 1000 = -8 ≠ -2
反码:正数的反码等于原码,负数的反码等于除符号位之外的所有位取反,故而
+3 原码:0000 0011 反码:0000 0011
-5 原码:1000 0101 反码:1111 1010
反码相加:
0000 0011
+1111 1010
----------
1111 1101 (反码) => 原码:1000 0010 => -2
看起来没啥问题,然而我们再计算:
-3反 1111 1100
+5反 0000 0101
---------------
0000 0001 => 原 0000 0001 => 1 ???
-2反 1111 1101
+2反 0000 0010
--------------
1111 1111 => 原 1000 0000 => -0 ???
负数补码等于反码加1,解决+0和-0的问题。
-3补 1111 1101
+5补 0000 0101
--------------
0000 0010 => +2
-2补 1111 1110
+2补 0000 0010
--------------
0000 0000 => +0
+3补 0000 0011
-5补 1111 1011
--------------
1111 1110 => 反 1111 1101 => 原 1000 0010 => -2
下面两个加法:
1000 0001 <= 1000 0000 <= 1111 1111 <= -127
1111 1111 <= 1111 1110 <= 1000 0001 <= -1
+++++++++
2111 1112
1000 0000 => 0111 1111 => 0111 1111 => 127???
0111 1101 <= 0111 1101 <= 0111 1101 <= 125
0000 0010 <= 0000 0010 <= 0000 0010 <= 2
+++++++++
0111 1111 => 0111 1111 => 0111 1111 => 127!!!
这里注意,两个数和为0,意味着和的补码为0000 0000
,同时意味着不会有任何两个数的和的补码能够为1000 0000
,而如果按照通常的思路理解有符号整数,0000 0000
和1000 0000
都应该表示十进制整数0。我们只用0000 0000
表示0,而1000 0000
用来表示另一个特别的数字-128,并且该数字的原反补码也都相同,均为1000 0000
,这样
1000 0010 <= 1000 0001 <= 1111 1110 <= -126
1111 1110 <= 1111 1101 <= 1000 0010 <= -2
+++++++++
2111 1120
1000 0000 => -128 ok!
评论区