这个算法是计算机中用于计算有符号二进制数(补码)乘法的一种高效算法。它由Andrew Donald Booth于1950年提出。
第一部分:为什么需要Booth算法?------ 动机
在讲解补码时我们提到,有符号数的乘法可以通过"先取绝对值计算,再修正符号"的方式实现。但这需要额外的步骤和电路来判断符号和转换补码。
Booth算法的伟大之处在于:它可以直接对两个用补码表示的有符号数进行乘法运算,而无需进行任何预处理(如判断正负、取绝对值等),并且对于连续的0或1,它能减少加法操作的次数,从而提高运算速度。
它的核心思想是:通过检测二进制位的变化,将连续的乘法操作转换为更少的加法和减法操作。
第二部分:算法核心思想
1. 关键观察
考虑一个二进制乘法,例如 0011110
(十进制30)。用传统乘法方式(移位相加): X * 0011110 = X * (2^4 + 2^3 + 2^2 + 2^1) = (X << 4) + (X << 3) + (X << 2) + (X << 1)
这需要4次加法操作。
但我们可以换一种角度看这个乘数 0011110
: 0011110 = 0100000 - 0000010
(即 32 - 2 = 30
) 那么,X * 0011110 = X * (2^5 - 2^1) = (X << 5) - (X << 1)
这只需要2次操作(一次减法和一次加法)!效率大大提升。
Booth算法正是基于这种"用减法代替一连串加法"的智慧。
2. 编码规则
Booth算法通过检查乘数中相邻两位 的变化来决定对部分积(Partial Product)进行何种操作。它会在乘数的最低有效位(LSB)右边添加一个辅助位 Q_{-1}
,初始值为0。
我们检查乘数当前的两位:Q_0
(当前最低位)和 Q_{-1}
(右边的辅助位)。
Q_0 (当前位) |
Q_{-1} (前一位) |
操作说明 | 执行的操作 |
---|---|---|---|
0 | 0 | 遇到了一串连续的0 | 仅算术右移 |
0 | 1 | 遇到了一串连续的1的结束(从1变为了0) | 加上被乘数,然后右移 |
1 | 0 | 遇到了一串连续的0的结束(从0变为了1) | 减去被乘数,然后右移 |
1 | 1 | 遇到了一串连续的1 | 仅算术右移 |
记忆技巧:
-
"01" -> 串结束(加)
-
"10" -> 串开始(减)
-
"00" 和 "11" -> 串中间(光移位)
算术右移(Arithmetic Right Shift) :对于有符号数(补码),右移时最高位(符号位)保持不变,而不是简单地补0。例如,1010 ( -6 )
算术右移一位后是 1101 ( -3 )
。
第三部分:Booth算法详细步骤与示例
我们现在用一个完整的例子来演示算法流程:计算 (-3) × 5。
-
被乘数
M = -3
(4位补码:1101
) -
乘数
Q = 5
(4位补码:0101
) -
预期结果:
(-3) × 5 = -15
(8位补码:11110001
)
我们使用一个4位的系统,但需要双倍长度的寄存器来存放结果。因此,我们使用三个寄存器:
-
A:4位,初始为0,用于存放部分积的高位。
-
Q:4位,初始为乘数。
-
Q_{-1}:1位,初始为0。
整个操作需要循环4次(等于乘数的位数)。
循环计数 | 步骤 | A | Q | Q_{-1} | 操作判断 (Q_0, Q_{-1}) | 执行的操作 |
---|---|---|---|---|---|---|
初始 | 初始化 | 0000 |
0101 |
0 |
||
1 | 判断 | 0000 |
0101 |
0 |
(1, 0) -> "10" | A = A - M |
执行减法 | 0011 |
0101 |
0 |
(M=-3=1101, -M=3=0011, A=0000+0011=0011) | ||
算术右移 (A, Q, Q_{-1}) | 0001 |
1010 |
1 |
(A和Q作为一个整体右移,A的符号位不变) | ||
2 | 判断 | 0001 |
1010 |
1 |
(0, 1) -> "01" | A = A + M |
执行加法 | 1110 |
1010 |
1 |
(A=0001, M=1101, A+M=1110) | ||
算术右移 (A, Q, Q_{-1}) | 1111 |
0101 |
0 |
|||
3 | 判断 | 1111 |
0101 |
0 |
(1, 0) -> "10" | A = A - M |
执行减法 | 0010 |
0101 |
0 |
(A=1111, -M=0011, A+(-M)=0010) | ||
算术右移 (A, Q, Q_{-1}) | 0001 |
0010 |
1 |
|||
4 | 判断 | 0001 |
0010 |
1 |
(0, 1) -> "01" | A = A + M |
执行加法 | 1110 |
0010 |
1 |
(A=0001, M=1101, A+M=1110) | ||
算术右移 (A, Q, Q_{-1}) | 1111 |
0001 |
0 |
|||
结束 | 1111 |
0001 |
最终结果 :将A和Q寄存器连接起来,A Q = 1111 0001
。 这正好是 -15
的8位补码表示 (11110001
= -128 + 64 + 32 + 16 + 1 = -15)。计算正确!
第四部分:Booth算法的变种与优势
1. 位对编码(Radix-4 Booth编码)
基本的Booth算法每次检查1位,需要n次循环(n为位数)。位对编码 每次检查3位 (当前位对和右边一位),将循环次数减少到大约 n/2 次,速度更快。
它检查三位组合 (Q_1, Q_0, Q_{-1})
,操作包括:
-
000
: 移位2位(相当于乘以0) -
001
,010
: +X, 移位2位 -
011
: +2X,移位2位(相当于X左移一位) -
100
: -2X,移位2位 -
101
,110
: -X, 移位2位 -
111
: 移位2位(相当于乘以0)
2. 优势总结
-
统一处理有符号数:直接对补码进行操作,无需额外的符号处理电路,简化了硬件设计。
-
速度可能更快:当乘数中包含连续的0或1时,Booth算法可以跳过这些位,减少加法/减法操作的次数。平均而言,它比传统的"移位-相加"算法更快。
-
易于硬件实现:算法流程规整(判断->加/减->移位),非常适合用硬件流水线实现。
3. 注意事项
-
最坏情况 :如果乘数是交替的
0101...01
模式,Booth算法每次循环都需要进行加/减操作,性能与传统方法相同。 -
位宽扩展:为了保证结果正确,寄存器A和Q的位宽需要是原始操作数的两倍。
总结
Booth算法是一个巧妙而强大的算法,它深刻理解了二进制补码的特性。其核心在于:
-
动机:高效地直接计算补码乘法。
-
核心 :通过检测乘数中 "01" 和 "10" 的跳变,将连续的加法转换为一次减法或加法。
-
流程 :判断 -> 执行(加/减/无操作) -> 算术右移,循环n次。
-
结果:最终结果存放在连接在一起的A和Q寄存器中。