| 项目 | 值 |
|---|---|
| 加减法 | 补码直接加减,丢弃溢出位 |
| 乘法 | 原码一位乘:符号异或,数值绝对值相乘 |
| 除法 | 恢复余数法 / 加减交替法 |
定点数的算术运算是计算机最基本的操作。现代计算机普遍采用补码进行加减运算,乘法和除法有多种实现方式。溢出判断是保证运算正确性的关键。
[X + Y]补 = [X]补 + [Y]补 (mod 2ⁿ⁺¹)
直接将两个补码相加,符号位参与运算,舍弃最高位进位。
[X - Y]补 = [X]补 + [-Y]补
关键操作:求 $[-Y]_补$ 的方法——$[Y]_补$ 连同符号位全部取反,末位加 1。
X = +1011, Y = +0011 → X+Y = +1110
[X]补 = 0,1011
[Y]补 = 0,0011
0,1011
+ 0,0011
----------
0,1110 → +14 ✓(无溢出)
X = +0111, Y = +1001 → X-Y = -0010
[X]补 = 0,0111
[Y]补 = 0,1001
[-Y]补 = 1,0111
0,0111
+ 1,0111
----------
1,1010 → 负数,取反加1得 -0010 = -2 ✓
$Cs =$ 符号位进位,$C1 =$ 最高数值位进位
溢出 $V = Cs ⊕ C1$
$V=0$ 无溢出,$V=1$ 有溢出
00 正数,11 负数,01 正溢出(上溢),10 负溢出(下溢)
两个符号位相同 → 无溢出
两个符号位不同 → 溢出
设 A、B 为操作数符号,S 为结果符号
溢出 = (A·B·S̄) + (Ā·B̄·S)
即:两正数加出负数,或两负数加出正数
8位补码:65 + 66 = ?
[65]补 = 01000001
[66]补 = 01000010
01000001
+ 01000010
-----------
10000011 → -125(显然错误!)
两正数相加得负数 → 溢出 ✓
算法(手算模拟):
1. 初始化:A=0(部分积),B=被乘数,C=乘数
2. 检查C最低位:
- 若为1:A = A + B
- 若为0:A不变
3. A和C一起右移一位
4. 重复步骤2-3,共n次
Booth算法步骤:
1. 初始化:A=0,Yn+1=0
2. 检查(Yn, Yn+1):
- 00 或 11:只右移
- 01:A = A + [X]补,然后右移
- 10:A = A + [-X]补,然后右移
3. 重复n次,最后一次不移位
X = -3 (1101), Y = -5 (1011)
[-X]补 = 0011
步骤:(A, Y, Yn+1)
初始:0000, 1011, 0
1. YnYn+1=10 → A=A+[-X]=0011 → 右移:0001, 1101, 1
2. YnYn+1=11 → 右移:0000, 1110, 1
3. YnYn+1=01 → A=A+[X]=1101 → 右移:1110, 1111, 0
4. YnYn+1=10 → A=A+[-X]=0001 → 不移位:0001, 1111
结果:0001111 = +15 → 补码:(-3)×(-5) = +15 ✓
1. 符号位单独处理
2. |被除数| - |除数|,够减商1,不够减商0并恢复余数
3. 余数左移一位,重复步骤2
4. 商的符号 = 被除数符号 ⊕ 除数符号
1. 够减:余数左移,减除数
2. 不够减:余数左移,加除数(代替恢复余数再减)
3. 最后一次不够减时,需恢复余数
| 移位类型 | 左移 | 右移 |
|---|---|---|
| 原码 | $\times2$(低位补 0) | $\div2$(高位补 0) |
| 补码 | $\times2$(低位补 0) | $\div2$(高位补符号位) |
| 反码 | $\times2$(低位补 0) | $\div2$(正数补 0,负数补 1) |
| 运算 | 原码 | 补码 |
|---|---|---|
| 加法 | 需判断符号 | 直接加 |
| 减法 | 需判断符号 | 转为加法 |
| 乘法 | 符号单独处理 | Booth 算法,符号参与 |
| 除法 | 符号单独处理 | 符号参与运算 |
↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。