引入补码的原因


1.原码的符号位无法参与运算

1
2
3
4
//例如原码 3位数值位,1为符号位
[x]原 = 1 011 = -3
[y]原 = 0 101 = +5
[x]原+[y]原 = 1 011 + 0 101 = 0000 =0//值不为5-3=-2

2.将减法变加法

1
2
3
4
5
6
7
8
//只有负数才有补码
//原因是为了将减法变成加法,用到了取模运算,减去一个数,相当于加上这个数(负数)补码
//例如0-1
000 - 001 //等价于0往前走1格 -->到了-1
000 + 111 //等价于0往后走7格 -->到了-1,因为有个取模运算
//上面这个例子就揭示了补码的意义
//注意只有负数才需要补码,正数不需要,因为机器可以处理正数相加
//这里正数相加也需要取模

image.png
image.png

补码的“补”的含义


其中M=10000,所以对于1111来说他的补码就是10000 - 1111 =0001
image.png

补码加减运算


补码相加相减应该并不陌生。但是由于bit限制,存储的位数不够,补码相加或相减得到的数字超过最大或最小值时,就会发生符号位进位–>也就是溢出
image.png

这个时候就需要通过取模运算,即有点像循环数组,超过最大模,则回到开始位置
所以要想补码计算正确,前提是,两数相加或相减不能超过模的绝对值,不然取模就不准确。
image.png

image.png

补码取模

  • 定点小数
  • 定点整数

补码取模,对于这个具体模的选取,有下面这样的规律。
image.png

当参加运算的数是定点小数时,模M=2
image.png

image.png

当参加运算的数是定点整数时
模M=2^(n+1),n+1表示n位数值位,1位符号位;n+1代表总共存储位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[x]补 = 1100 0000 
[y]补 = 1110 0000

[x]补 + [y]补 = 1100 0000+1110 0000 = 1 0010 0000 -->然后再取模2^8 --> 0010 0000 (使得数值又落在范围之内)


再举个小一点的例子
[x]补 = 110 --> -2
[y]补 = 111 --> -1
[x]补 + [y]补 = 110 + 111 = 1 101 -->取模2^3 --> 101 (数值又落回在范围内,恰好表示-3)

[x]补 = 011 --> 3
[y]补 = 010 --> 2
[x]补 + [y]补 = 011 + 010 =101 --> -3

计算正确的前提是参与运算的数字不能大于模。若是大于模,模也需要变大

image.png

1
2
3
[x]补 = 100 --> -4
[y]补 = 111 --> -1
[x]补 + [y]补 = 100 + 111 =1 011 --> 取模 --> 011 -->-3

image.png