摘要:本文介绍补码进行运算为什么是有效的。
通过求同“同余”将减法变成加法;而求补码就是求同余。
1. 原码、反码和补码
1.1 原码
原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值.
>
[+1]原 = 0000 0001
[- 1]原 = 1000 0001
1.2 反码
正数的反码是其本身
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
1.3 补码
正数的补码就是其本身
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
2. 同余
定义1:两个整数a,b,若它们除以整数m所得的余数相等,则称a,b对于模m同余。
例如,当 m=12 时,3跟15是同余的,因为 3mod12=3=15mod12
对于同余,有如下结论:
- a,b是关于m同余的,当且仅当,二者相差m的整数倍,
a−b=k×m,withk=……−2,−1,0,1,2,……
即,
a=b+k×m,withk=……−2,−1,0,1,2,……- 一个数x加a对m取余,等于x加a的同余b对m取余,即,
(x+a)modm=(x+b)modm.
由1.易知2.是成立的。
3. 为什么补码是有效的
3.1 将减法变成加法
我们知道计算机只有加法器,没有减法器,那么就需要将加法变成加法。怎么变?
经过上面的介绍,我们知道,在对m取余的情况下,加上一个数,相当于加上这个数的同余,即,
若,
b=a+m
,则
(x+a)modm=(x+b)modm
.
举个例子:
以时钟的时针为例,因为,10 = -2 + 12。
当前时刻 t=3 ,向后拨2个小时得, (t−2)mod12=1mod12=1 ;
也就相当于向前拨10个小时, (t+10)mod12=13mod12=1 。
结论:通过同余,减法操作变成了加法操作。
3.1 求同余就是求补码
我们通过证明:负数的补码和原码之和等于m,来证明求同余的过程就是求补码。
定义2:
定义m为除去符号位后,能表示的数字的个数。
例如,用8位表示整数,除去符号位,还剩7位,能表示的数字的就是000 0000~111 1111,共128个数字。所以此时 m=128.
负数的补码等于原码的符号位不变,其它位取反,再加1。
那么不看不符号位,将负数的补码和原码相加等于多少呢?
全1再加1,就等于m!
例如,用8位表示整数-3,原码为1000 0011,补码为,1111 1101,不看符号位,将二者相加得,1000 0000 = 128.
3.2 用同余进行计算
后面我都将以用8位表示的整数运算, 3−2 为例进行分析。
由于8位除去符号位后的m等于128,那么 128−2=126 ,即 126=−2+128 ,根据上面的分析:
(3−2)mod128=(3+126)mod128题外话:为什么要模128,因为我们只关注后7位,如果和大于等于128,将进位。
这样,减法就变成了加法,也可以看成,将所有含负数的运算变成了只含正数的运算。工作还没有完。
我们进行上述计算:
- 3的编码为:0000 0011(由于是正数,原码反码补码相同)
- 126的编码:0111 1110
- 二者相加得,1000 0001
结果错误,这是负1的编码。
我们发现上述运算的结果正好差一个负号,怎么办?这时候就轮到符号位出场了,刚才我们说的运算都忽略了符号位,现在把它加上:
- 3的编码:0000 0011
- 126的编码:1111 1110(因为126对应的是-2,因此其符号位为1)
- 二者相加得:1 0000 0001,因为我们只看8位,得 0000 0001.
结果正确!这就叫符号位参与运算。
以上过程就是补码参与运算的过程。
4. 总结
计算机只能用有限的位表示整数本来是个劣势,而正是这个劣势让减法变成加法成为可能。塞翁失马焉知非福。
以上。