为什么负数的补码等于反码加一
前言
对于这个计算机的基础问题,讲的人很多,讲的简单清楚的人太少。回顾自己的学习历程,发现《深入理解计算机系统》这本书,把这个问题讲的最浅显易懂;于是自己根据此书的讲解,进行了归纳总结,形成了此文。
1,基本概念(看看了解一下就好)
计算机通过将最高位设置为符号位来表示正负数:
符号位为 1 时,代表这个数为负数;符号位为 0 时,代表这个数为正数。
为了方便理解,本文中的例子全部用 4 位二进制数举例
原码:除符号位外的其他位,保存该二进制数的绝对值。
例如 1:0001 -1:1001
反码:正数的反码等于原码;
负数的反码就是其原码除符号位外,按位取反。
例如 1:0001 -1: 1110
补码:正数的补码等于其原码
负数的的补码等于反码加一
例如 1:0001 -1:1111
2,原码、补码
原码、反码、补码都可以通过符号位非常方便的表示正负数,但是在进行加法计算时,原码和反码都存在这样或那样的问题:
注: 计算机 cpu 的运算器只实现了加法器,而没有实现减法器,计算机是通过加上一个负数来做减法的
原码:
1 + 1 = 0001 + 0001 = 0010 = 2
1 + -1 = 0001 + 1001 = 1010 = -2
从上面的计算可以看出,原码无法通过加上一个负数来实现减法
反码
1 + -1 = 0001 + 1110 = 1111 = -0
1 + -2 = 0001 + 1010 = 1011 = -4
从上面的计算可以看出,反码也无法实现加上一个负数来实现减法
原码和反码都不能解决的事情,只有通过寻找一种可以完美支持件“减法“的二进制数的表示方法来解决!
3,补码
一个 4 位的二进制数能表示的数是有限的,从 0000 ~ 1111 ,0000 表示 0,1111 表示 - 1,最大值 7(0111),最小值-8(1000)。
看下面这组计算:
0000 + 0001 = 0 + 1 = 0001 = 1
0001 + 0001 = 1 + 1 = 0010 = 2
0010 + 0001 = 2 + 1 = 0011 = 3
...
0111 + 0001 = 7 + 1 = 1000 = -8
1000 + 0001 = -8 + 1 = 1001 = -7
1001 + 0001 = -7 + 1 = 1010 = -6
...
1111 + 0001 = -1 + 1 = 0000 = 0
0000 + 0001 = 0 + 1 = 0001 = 1
0000 每次加上 0001 ;当最大值 7 + 1 时,正溢出,结果为最小值-8;最小值-8 加上 8 后,又变成了 0000,就像钟表一样,循环往复。
比如说现在有一个数字 2,我们想让它变成 0,怎么办?
有两种方法:
1. 减去 2 个 1 即:0010 - 0010 = 0000
2. 加上 14 个 1 即:0010 + 1110 = 0000
我们可以总结出,当一个四位的二进制数 abcd 减去 另一个四位的二进制数 efgh : abcd - efgh = abcd + (1111 + 1 - efgh) 。
efgh 和 (1111 + 1 - efgh) 对模 (1111 + 1)同余。
如果不太理解,就可以想象一个钟表的时针停在 10 点的位置,如果想让时针停在 8 点的位置,可以逆时针的旋转 2 个刻度,也可以顺时针的旋转 10 个刻度。
通过公式 abcd - efgh = abcd + (1111 + 1 - efgh) ,我们可以得出,如果计算机使用(1111 + 1 -efgh)来表示 -(efgh) ,就可以解决减法的问题。这就是我们补码的原理。
由于 1111 - efgh 等于 efgh 的反码 ,所以 efgh 的补码等于 efgh 的反码加上 1。
评论