符号位单独计算,对于数值部分,则只需要像正常乘法那样
比如 x = − 0.1110 , y = − 0.1101 x=-0.1110,y=-0.1101 x=−0.1110,y=−0.1101,求 [ x ⋅ y ] 原 [x\cdot y]_原 [x⋅y]原
所有的右移过程均为逻辑右移
z z z为部分积, x ∗ x^* x∗为被乘数, y ∗ y^* y∗为乘数
乘数判断位 y n − 1 y n y_{n-1}y_n yn−1yn | 标志位 C j C_j Cj | 操作内容 |
---|---|---|
00 | 0 | 部分积右移2位,乘数右移两位, C j C_j Cj保持0 |
01 | 0 | 部分积加上一个被乘数,右移2位,乘数右移2位, C j C_j Cj保持0 |
10 | 0 | 部分积加上2倍的被乘数,右移2位,乘数右移2位, C j C_j Cj保持0 |
11 | 0 | 部分积减去一个被乘数数,右移2位,乘数右移2位, C j C_j Cj置1 |
00 | 1 | 部分积加上一个被乘数,右移2位,乘数右移2位, C j C_j Cj置0 |
01 | 1 | 部分积加上2倍的被乘数,右移2位,乘数右移2位, C j C_j Cj置0 |
10 | 1 | 部分积减去一个被乘数,右移2位,乘数右移2位, C j C_j Cj保持1① |
11 | 1 | 部分积右移2位, C j C_j Cj保持1② |
①:应该是部分积加上三倍的被乘数,即 z + 3 x ∗ z+3x^* z+3x∗,转换成 z − x ∗ z-x^* z−x∗,然后整体右移两位后,对于下一次迭代, C j C_j Cj为1,一定会加上一个 x ∗ x^* x∗,那么对于上一次迭代的 z z z来说,相当于是加上了一个左移了两位的 x ∗ x^* x∗,即 4 x ∗ 4x^* 4x∗,由于上次迭代减去了一个 x ∗ x^* x∗,所以最终相当于是加上了 3 x ∗ 3x^* 3x∗
②:大致与①类似,不过是少了减 x ∗ x^* x∗这一步
原理(以小数为例):
设被乘数为 [ x ] 补 = x 0 . x 1 x 2 ⋯ x n [x]_补 = x_0.x_1x_2\cdots x_n [x]补=x0.x1x2⋯xn
乘数 [ y ] 补 = y 0 . y 1 y 2 ⋯ y n [y]_补 = y_0.y_1y_2\cdots y_n [y]补=y0.y1y2⋯yn
补码与真值的转换公式
设 [ x ] 补 = x 0 . x 1 x 2 ⋯ x n [x]_补 = x_0.x_1x_2\cdots x_n [x]补=x0.x1x2⋯xn
x ≥ 0 x\ge 0 x≥0时, x 0 = 0 x_0=0 x0=0
[ x ] 补 = 0. x 1 x 2 ⋯ x n = ∑ i = 1 n x i 2 − i = x [x]_补 = 0.x_1x_2\cdots x_n = \sum_{i = 1}^n x_i2^{-i} = x [x]补=0.x1x2⋯xn=∑i=1nxi2−i=x
x < 0 x < 0 x<0时, x 0 = 1 x_0=1 x0=1
[ x ] 补 = 1. x 1 x 2 ⋯ x n = 2 + x [x]_补 = 1.x_1x_2\cdots x_n=2+x [x]补=1.x1x2⋯xn=2+x
x = 1. x 1 x 2 ⋯ x n − 2 = − 1 + 0. x 1 x 2 ⋯ x n = − 1 + ∑ i = 1 n x i 2 − i x=1.x_1x_2\cdots x_n - 2 = -1+0.x_1x_2\cdots x_n = -1 + \sum_{i = 1}^{n} x_i2^{-i} x=1.x1x2⋯xn−2=−1+0.x1x2⋯xn=−1+∑i=1nxi2−i
最终,无论x大于零还是小于零,我们可以使用统一的式子来表示
x = − x 0 + ∑ i = 1 n x i 2 − i x=-x_0 + \sum_{i=1}^{n}x_i2^{-i} x=−x0+i=1∑nxi2−i
补码的右移
正数右移一位,相当于乘以 1 2 \frac{1}{2} 21
设 [ x ] 补 = x 0 . x 1 x 2 ⋯ x n [x]_补=x_0.x_1x_2\cdots x_n [x]补=x0.x1x2⋯xn
∵ x = − x 0 + ∑ i = 1 n x i 2 − i x=-x_0 + \sum_{i=1}^{n}x_i2^{-i} x=−x0+∑i=1nxi2−i
∴ 1 2 x = − 1 2 x 0 + 1 2 ∑ i = 1 n x i 2 − i \frac{1}{2}x = \frac{-1}{2}x_0 + \frac{1}{2}\sum_{i=1}^{n}x_i2^{-i} 21x=2−1x0+21∑i=1nxi2−i
= − x 0 + 1 2 x 0 + 1 2 ∑ i = 1 n x i 2 − i = -x_0 + \frac{1}{2}x_0 + \frac{1}{2}\sum_{i=1}^{n}x_i2^{-i} =−x0+21x0+21∑i=1nxi2−i
= − x 0 + 1 2 ∑ i = 0 n x i 2 − i = -x_0 + \frac{1}{2}\sum_{i=0}^{n}x_i2^{-i} =−x0+21∑i=0nxi2−i
∴
[ 1 2 x ] 补 = x 0 . x 0 x 1 x 2 ⋯ x n [\frac{1}{2}x]_补 = x_0.x_0x_1x_2\cdots x_n [21x]补=x0.x0x1x2⋯xn
即:要获得 [ 2 − i x ] 补 [2^{-i}x]_补 [2−ix]补,只需要将 [ x ] 补 [x]_补 [x]补连同符号右移i位即可
这里我们证明了,补码通过带符号的整体移动来实现乘除过程
若被乘数x为任意符号,乘数y为正
[ x ] 补 = x 0 . x 1 x 2 ⋯ x n = 2 + x = 2 n + 1 + x [x]_补 = x_0.x_1x_2\cdots x_n = 2 + x = 2^{n + 1} + x [x]补=x0.x1x2⋯xn=2+x=2n+1+x (mod 2) ①,
因为是在模2的情况下,一个小数x无论是加上2(10.00…0)还是加上 2 n + 1 即 ( 100 ⋯ 0 ⏟ n + 2 位 . 00 ⋯ 0 ) 2^{n+1}即(\underbrace{100\cdots 0}_{n+2位}.00\cdots 0) 2n+1即(n+2位 100⋯0.00⋯0)都不会影响最终的结果
[ y ] 补 = 0. y 1 y 2 ⋯ y n = y [y]_补 = 0.y_1y_2\cdots y_n = y [y]补=0.y1y2⋯yn=y ②
[ x ] 补 ⋅ [ y ] 补 = [ x ] 补 ⋅ y = ( 2 n + 1 + x ) ⋅ y = 2 n + 1 ⋅ y + x y [x]_补\cdot [y]_补 = [x]_补 \cdot y = (2^{n+1} + x)\cdot y = 2^{n+1}\cdot y + xy [x]补⋅[y]补=[x]补⋅y=(2n+1+x)⋅y=2n+1⋅y+xy③
由②可知, y = 0. y 1 y 2 ⋯ y n = ∑ i = 1 n y i 2 − i y=0.y_1y_2\cdots y_n = \sum_{i = 1}^{n}y_i 2^{-i} y=0.y1y2⋯yn=∑i=1nyi2−i
则 2 n + 1 ⋅ y = 2 ∑ i = 1 n y i 2 n − i 2^{n+1}\cdot y = 2\sum_{i = 1}^{n}y_i2^{n-i} 2n+1⋅y=2∑i=1nyi2n−i是一个2倍整数
解释一下,当我们在接触二进制的时候,面对随意一个二进制数10110101(假设这个二进制数是 w 8 w 7 ⋯ w 1 w_8w_7\cdots w_1 w8w7⋯w1)是如何计算它的十进制的?
n = ∑ i = 1 8 w i 2 i − 1 n=\sum_{i=1}^{8}w_i 2^{i-1} n=∑i=18wi2i−1
由于 y = 0. y 1 y 2 ⋯ y n y=0.y_1y_2\cdots y_n y=0.y1y2⋯yn是反过来排序的,
∑ i = 1 n y i 2 n − i \sum_{i = 1}^{n}y_i2^{n-i} ∑i=1nyi2n−i
其实跟我们计算二进制的十进制数的流程是一样的,同时也说明
2 n + 1 ⋅ y = 2 ∑ i = 1 n y i 2 n − i 2^{n+1}\cdot y = 2\sum_{i = 1}^{n}y_i2^{n-i} 2n+1⋅y=2∑i=1nyi2n−i是一个整数的2倍
所以 2 n + 1 ⋅ y 2^{n+1}\cdot y 2n+1⋅y 进行模2操作后结果应该为0
在模2的情况下, 2 n + 1 ⋅ y 2^{n+1}\cdot y 2n+1⋅y与2是等效的
从上面的推理我们知道 2 n + 1 ⋅ y 2^{n+1}\cdot y 2n+1⋅y是一个偶数,我们假设它为6(110.0000)
假设一个小数0.1001
(0.1001 + 10.0000) mod 2 = (0.1001 + 110.0000 ) mod 2
根据模运算的性质,有 2 n + 1 ⋅ y = 2 2^{n+1}\cdot y = 2 2n+1⋅y=2 (mod 2)
所以由③可知 [ x ] 补 ⋅ [ y ] 补 = 2 n + 1 ⋅ y + x y = 2 + x y = [ x ⋅ y ] 补 [x]_补 \cdot [y]_补 = 2^{n+1} \cdot y + xy = 2 + xy = [x\cdot y]_补 [x]补⋅[y]补=2n+1⋅y+xy=2+xy=[x⋅y]补 (mod 2)
即:
当y大于零的时候, [ x ⋅ y ] 补 = [ x ] 补 ⋅ [ y ] 补 = [ x ] 补 ⋅ y [x\cdot y]_补 = [x]_补 \cdot [y]_补 = [x]_补 \cdot y [x⋅y]补=[x]补⋅[y]补=[x]补⋅y
这时候我们便可以使用原码乘法的规则
[ z 0 ] 补 = 0 [ z 1 ] 补 = 2 − 1 ( y n [ x ] 补 + [ z 0 ] 补 ) . . . [ x ⋅ y ] 补 = [ z n ] 补 = 2 − 1 ( y 1 [ x ] 补 + [ z n − 1 ] 补 ) [z_0]_补 = 0\\ [z_1]_补 = 2^{-1}(y_n[x]_补 + [z_0]_补)\\ ...\\ [x\cdot y]_补 = [z_n]_补 = 2^{-1}(y_1[x]_补+[z_{n-1}]_补) [z0]补=0[z1]补=2−1(yn[x]补+[z0]补)...[x⋅y]补=[zn]补=2−1(y1[x]补+[zn−1]补)
乘以 2 − 1 2^{-1} 2−1其实就是右移的过程,
还记得我们在前置知识里面提到过的右移规则吗,当你计算的时候右移记得保持符号位。
若被乘数x为任意符号,乘数y为负
[ x ] 补 = x 0 . x 1 x 2 ⋯ x n [x]_补 = x_0.x_1x_2\cdots x_n [x]补=x0.x1x2⋯xn
[ y ] 补 = 1. y 1 y 2 ⋯ y n = 2 + y [y]_补 = 1.y_1y_2\cdots y_n = 2 + y [y]补=1.y1y2⋯yn=2+y (mod 2)
y = [ y ] 补 − 2 = 1. y 1 y 2 ⋯ y n − 1 − 1 = 0. y 1 y 2 ⋯ y n − 1 y = [y]_补 - 2 = 1.y_1y_2\cdots y_n - 1 - 1 = 0.y_1y_2\cdots y_n - 1 y=[y]补−2=1.y1y2⋯yn−1−1=0.y1y2⋯yn−1
x ⋅ y = x ( 0. y 1 y 2 ⋯ y n − 1 ) = x ( 0. y 1 y 2 ⋯ y n ) − x x \cdot y = x(0.y_1y_2\cdots y_n - 1) = x(0.y_1y_2\cdots y_n) - x x⋅y=x(0.y1y2⋯yn−1)=x(0.y1y2⋯yn)−x
[ x ⋅ y ] 补 = [ x ( 0. y 1 y 2 ⋯ y n ) ] 补 + [ − x ] 补 [x\cdot y]_补 = [x(0.y_1y_2\cdots y_n)]_补 + [-x]_补 [x⋅y]补=[x(0.y1y2⋯yn)]补+[−x]补
如果将 ( 0. y 1 y 2 ⋯ y n ) (0.y_1y_2\cdots y_n) (0.y1y2⋯yn)视为一个正数
即:
当乘数y小于0的时候, [ x ⋅ y ] 补 = [ x ( 0. y 1 y 2 ⋯ y n ) ] 补 + [ − x ] 补 = [ x ] 补 ( 0. y 1 y 2 ⋯ y n ) + [ − x ] 补 [x\cdot y]_补 = [x(0.y_1y_2\cdots y_n)]_补 + [-x]_补 = [x]_补 (0.y_1y_2\cdots y_n) + [-x]_补 [x⋅y]补=[x(0.y1y2⋯yn)]补+[−x]补=[x]补(0.y1y2⋯yn)+[−x]补
而上式中, [ x ( 0. y 1 y 2 ⋯ y n ) ] 补 [x(0.y_1y_2\cdots y_n)]_补 [x(0.y1y2⋯yn)]补正是乘数为正数( 0. y 1 y 2 ⋯ y n 0.y_1y_2\cdots y_n 0.y1y2⋯yn为正数)时候的乘法结果,
算出来后再加上 [ − x ] 补 [-x]_补 [−x]补,就是最终结果
这个,便是校正法
使用校正法列式计算的时候,过程如原码计算一样,但是要注意这里使用了双符号位来计算
说的再多,不如直接用事实说话
唐朔飞版《计算机组成原理》p251页例6.19
已知 [ x ] 补 = 1.0101 , [ y ] 补 = 0.1101 [x]_补=1.0101,[y]_补=0.1101 [x]补=1.0101,[y]补=0.1101,求 [ x ⋅ y ] 补 [x\cdot y]_补 [x⋅y]补
问题出在我画红框的位置,在运算过程中结果超过了1,应该是2点几,但是由于只有一个符号位,符号位直接干成零了,进位被丢弃了,可以说,运算过程中出现了溢出现象,本来好好的负数,一捣鼓成了正数了,所以为了避免这个情况,使用双符号位。
[ − x ] 补 = − [ x ] 补 [-x]_补 = -[x]_补 [−x]补=−[x]补 (mod 2)
证明过程如下,兄弟们可以跳过不看:
若 [ x ] 补 [x]_补 [x]补为正数
∴ x = 0. x 1 x 2 ⋯ x n x = 0.x_1x_2\cdots x_n x=0.x1x2⋯xn
∴ − x = − 0. x 1 x 2 ⋯ x n -x = -0.x_1x_2\cdots x_n −x=−0.x1x2⋯xn
∴ [ − x ] 补 = 1. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n ( m o d 2 ) [-x]_补 = 1.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n} \pmod{2} [−x]补=1.x1ˉx2ˉ⋯xnˉ+2−n(mod2) ①
这里要解释一下,一般我们原码求补码为“数值取反再加一”,这里我们对x的所有小数位取反,然后加上 2 − n 2^{-n} 2−n即 0. 00 ⋯ 1 ⏟ n 0.\underbrace{00\cdots1}_n 0.n 00⋯1
∵ [ x ] 补 = 0. x 1 x 2 ⋯ x n \because [x]_补 = 0.x_1x_2\cdots x_n ∵[x]补=0.x1x2⋯xn
∴ − [ x ] 补 = − 0. x 1 x 2 ⋯ x n = 0 − 0. x 1 x 2 ⋯ x n ≡ 2 − 0. x 1 x 2 ⋯ x n ( m o d 2 ) \therefore -[x]_补=-0.x_1x_2\cdots x_n = 0 -0.x_1x_2\cdots x_n \equiv 2-0.x_1x_2\cdots x_n\pmod{2} ∴−[x]补=−0.x1x2⋯xn=0−0.x1x2⋯xn≡2−0.x1x2⋯xn(mod2)
= 1 + 1 − 0. x 1 x 2 ⋯ x n = 1 + 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n = 1. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n =1+1-0.x_1x_2\cdots x_n = 1 + 0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n} = 1.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n} =1+1−0.x1x2⋯xn=1+0.x1ˉx2ˉ⋯xnˉ+2−n=1.x1ˉx2ˉ⋯xnˉ+2−n ②
≡ \equiv ≡是同余符号。 a ≡ b ( m o d 2 ) a \equiv b \pmod{2} a≡b(mod2)代表a和b模2同余
解释一下这个计算:
1 + 1 − 0. x 1 x 2 ⋯ x n = 1 + 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n 1+1-0.x_1x_2\cdots x_n = 1 + 0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n} 1+1−0.x1x2⋯xn=1+0.x1ˉx2ˉ⋯xnˉ+2−n
我们可以这么想:
0. x 1 x 2 ⋯ x n + 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ = 0. 11 ⋯ 1 ⏟ n 0.x_1x_2\cdots x_n + 0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} = 0.\underbrace{11\cdots 1}_n 0.x1x2⋯xn+0.x1ˉx2ˉ⋯xnˉ=0.n 11⋯1
0. x 1 x 2 ⋯ x n + 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n = 1 0.x_1x_2\cdots x_n + 0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n} = 1 0.x1x2⋯xn+0.x1ˉx2ˉ⋯xnˉ+2−n=1
所以
1 − 0. x 1 x 2 ⋯ x n = 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n 1-0.x_1x_2\cdots x_n = 0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n} 1−0.x1x2⋯xn=0.x1ˉx2ˉ⋯xnˉ+2−n
由①和②可知 [ − x ] 补 = − [ x ] 补 [-x]_补 = -[x]_补 [−x]补=−[x]补 (mod 2)
若 [ x ] 补 [x]_补 [x]补为负数
∴ [ x ] 补 = 1. x 1 x 2 ⋯ x n \therefore [x]_补 = 1.x_1x_2\cdots x_n ∴[x]补=1.x1x2⋯xn
∴ x = − ( 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n ) \therefore x = -(0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n}) ∴x=−(0.x1ˉx2ˉ⋯xnˉ+2−n)
∴ − x = 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n \therefore -x = 0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n} ∴−x=0.x1ˉx2ˉ⋯xnˉ+2−n
∴ [ − x ] 补 = 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n \therefore [-x]_补 = 0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n} ∴[−x]补=0.x1ˉx2ˉ⋯xnˉ+2−n①
∵ [ x ] 补 = 1. x 1 x 2 ⋯ x n \because [x]_补 = 1.x_1x_2\cdots x_n ∵[x]补=1.x1x2⋯xn
并且 1. x 1 x 2 ⋯ x n + 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n = 2 1.x_1x_2\cdots x_n + 0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n} = 2 1.x1x2⋯xn+0.x1ˉx2ˉ⋯xnˉ+2−n=2
∴ [ x ] 补 = 1. x 1 x 2 ⋯ x n = 2 − ( 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n ) ≡ − ( 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n ) ( m o d 2 ) \therefore [x]_补= 1.x_1x_2\cdots x_n = 2-(0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n}) \equiv -(0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n}) \pmod{2} ∴[x]补=1.x1x2⋯xn=2−(0.x1ˉx2ˉ⋯xnˉ+2−n)≡−(0.x1ˉx2ˉ⋯xnˉ+2−n)(mod2)
∴ − [ x ] 补 = 0. x 1 ˉ x 2 ˉ ⋯ x n ˉ + 2 − n \therefore -[x]_补 = 0.\bar{x_1}\bar{x_2}\cdots \bar{x_n} + 2^{-n} ∴−[x]补=0.x1ˉx2ˉ⋯xnˉ+2−n②
∴ [ − x ] 补 = − [ x ] 补 ( m o d 2 ) \therefore [-x]_补 = -[x]_补 \pmod{2} ∴[−x]补=−[x]补(mod2)
这时候我直接copy前面的校正法中的语句
当y大于零的时候, [ x ⋅ y ] 补 = [ x ] 补 ⋅ [ y ] 补 = [ x ] 补 ⋅ y [x\cdot y]_补 = [x]_补 \cdot [y]_补 = [x]_补 \cdot y [x⋅y]补=[x]补⋅[y]补=[x]补⋅y
当乘数y小于0的时候, [ x ⋅ y ] 补 = [ x ( 0. y 1 y 2 ⋯ y n ) ] 补 + [ − x ] 补 = [ x ] 补 ( 0. y 1 y 2 ⋯ y n ) + [ − x ] 补 [x\cdot y]_补 = [x(0.y_1y_2\cdots y_n)]_补 + [-x]_补 = [x]_补 (0.y_1y_2\cdots y_n) + [-x]_补 [x⋅y]补=[x(0.y1y2⋯yn)]补+[−x]补=[x]补(0.y1y2⋯yn)+[−x]补
综合来看也就是少一个 [ − x ] 补 [-x]_补 [−x]补和多一个 [ − x ] 补 [-x]_补 [−x]补的问题
这完全可以使用 y 0 y_0 y0来控制,y大于0的时候 y 0 y_0 y0等于0,y小于0的时候 y 0 y_0 y0等于1,正好对应着 [ − x ] 补 [-x]_补 [−x]补的有无
即:
[ x ⋅ y ] 补 = [ x ] 补 ( 0. y 1 y 2 ⋯ y n ) + y 0 [ − x ] 补 [x\cdot y]_补 = [x]_补 (0.y_1y_2\cdots y_n) + y_0[-x]_补 [x⋅y]补=[x]补(0.y1y2⋯yn)+y0[−x]补
通过前置知识我们知道了
[ − x ] 补 = − [ x ] 补 ( m o d 2 ) [-x]_补 = -[x]_补 \pmod{2} [−x]补=−[x]补(mod2)
所以
[ x ⋅ y ] 补 = [ x ] 补 ( 0. y 1 y 2 ⋯ y n ) − y 0 [ x ] 补 [x\cdot y]_补 = [x]_补 (0.y_1y_2\cdots y_n) - y_0[x]_补 [x⋅y]补=[x]补(0.y1y2⋯yn)−y0[x]补
= [ x ] 补 ( − y 0 + y 1 2 − 1 + y 2 2 − 2 ⋯ y n 2 − n ) = [x]_补(-y_0+y_12^{-1}+y_22^{-2}\cdots y_n2^{-n}) =[x]补(−y0+y12−1+y22−2⋯yn2−n)
= [ x ] 补 ( − y 0 + y 1 ( 1 − 2 − 1 ) + y 2 ( 2 − 1 − 2 − 2 ) ⋯ y n ( 2 − n + 1 − 2 − n ) = [x]_补(-y_0+y_1(1 - 2^{-1})+y_2(2^{-1}-2^{-2})\cdots y_n(2^{-n+1}-2^{-n}) =[x]补(−y0+y1(1−2−1)+y2(2−1−2−2)⋯yn(2−n+1−2−n)
= [ x ] 补 ( ( y 1 − y 0 ) + 2 − 1 ( y 2 − y 1 ) + 2 − 2 ( y 3 − y 2 ) ⋯ + 2 − n ( 0 − y n ) ) = [x]_补((y_1-y_0)+2^{-1}(y_2-y_1)+2^{-2}(y_3-y_2)\cdots + 2^{-n}(0-y_n)) =[x]补((y1−y0)+2−1(y2−y1)+2−2(y3−y2)⋯+2−n(0−yn))
这时候我们设 y n + 1 = 0 y_{n+1} = 0 yn+1=0
则 [ x ⋅ y ] 补 = [ x ] 补 ( ( y 1 − y 0 ) + 2 − 1 ( y 2 − y 1 ) + 2 − 2 ( y 3 − y 2 ) ⋯ + 2 − n ( y n + 1 − y n ) ) [x\cdot y]_补=[x]_补((y_1-y_0)+2^{-1}(y_2-y_1)+2^{-2}(y_3-y_2)\cdots + 2^{-n}(y_{n+1}-y_n)) [x⋅y]补=[x]补((y1−y0)+2−1(y2−y1)+2−2(y3−y2)⋯+2−n(yn+1−yn))
那么现在我们可以了解一下乘法的递推公式了
[ z 0 ] 补 = 0 [ z 1 ] 补 = 2 − 1 ( [ z 0 ] 补 + ( y n + 1 − y n ) [ x ] 补 ) . . . [ z n ] 补 = 2 − 1 ( [ z n − 1 ] 补 + ( y 2 − y 1 ) [ x ] 补 ) [ x ⋅ y ] 补 = [ z n ] 补 + ( y 1 − y 0 ) [ x ] 补 [z_0]_补=0\\ [z_1]_补 = 2^{-1}([z_0]_补+(y_{n+1}-y_n)[x]_补)\\ ...\\ [z_n]_补 = 2^{-1}([z_{n-1}]_补+(y_2 - y_1)[x]_补)\\ [x\cdot y]_补 = [z_n]_补 + (y_1-y_0)[x]_补 [z0]补=0[z1]补=2−1([z0]补+(yn+1−yn)[x]补)...[zn]补=2−1([zn−1]补+(y2−y1)[x]补)[x⋅y]补=[zn]补+(y1−y0)[x]补
我们需要记住整体公式
[ x ⋅ y ] 补 = [ x ] 补 ( ( y 1 − y 0 ) + 2 − 1 ( y 2 − y 1 ) + 2 − 2 ( y 3 − y 2 ) ⋯ + 2 − n ( y n + 1 − y n ) ) [x\cdot y]_补=[x]_补((y_1-y_0)+2^{-1}(y_2-y_1)+2^{-2}(y_3-y_2)\cdots + 2^{-n}(y_{n+1}-y_n)) [x⋅y]补=[x]补((y1−y0)+2−1(y2−y1)+2−2(y3−y2)⋯+2−n(yn+1−yn))
共n+1项,对应着递推公式的n+1步,前n步都需要乘以 2 − 1 2^{-1} 2−1即对部分积进行右移操作,到达第 n + 1 n+1 n+1步的时候,不需要乘 2 − 1 2^{-1} 2−1即不需要右移操作
如果同志你理解了上面的过程,我觉得 y i y i + 1 y_iy_{i+1} yiyi+1对应的状态表就是多余的了,但是打上,更有助于理解
y i y i + 1 y_iy_{i+1} yiyi+1 | y i + 1 − y i y_{i+1}-y_i yi+1−yi | 操作 |
---|---|---|
00 | 0 | 部分积直接右移 |
01 | 1 | 部分积加上 [ x ] 补 [x]_补 [x]补 |
10 | -1 | 部分积减去 [ x ] 补 [x]_补 [x]补 |
11 | 0 | 部分积直接右移 |
减去,计算机怎么直接做减法呢?
还记得我们前置知识里面证明的结论吗?
[ − x ] 补 = − [ x ] 补 ( m o d 2 ) [-x]_补 = -[x]_补 \pmod{2} [−x]补=−[x]补(mod2)
所以上表我们可以更新成
y i y i + 1 y_iy_{i+1} yiyi+1 | y i + 1 − y i y_{i+1}-y_i yi+1−yi | 操作 |
---|---|---|
00 | 0 | 部分积直接右移 |
01 | 1 | 部分积加上 [ x ] 补 [x]_补 [x]补 |
10 | -1 | 部分积加上 [ - x ] 补 [-x]_补 [-x]补 |
11 | 0 | 部分积直接右移 |
计算机:“这个我会!”
那么这就要求我们在计算过程中首先要把 [ x ] 补 和 [ − x ] 补 [x]_补和[-x]_补 [x]补和[−x]补计算出来
还有就是,我们要求被乘数和部分积为双符号位,这个要求的原因可以从校正法中寻找
乘数需要保留一位符号位,Why?
还记得我们的递推公式吗
[ z 0 ] 补 = 0 [ z 1 ] 补 = 2 − 1 ( [ z 0 ] 补 + ( y n + 1 − y n ) [ x ] 补 ) . . . [ z n ] 补 = 2 − 1 ( [ z n − 1 ] 补 + ( y 2 − y 1 ) [ x ] 补 ) [ x ⋅ y ] 补 = [ z n ] 补 + ( y 1 − y 0 ) [ x ] 补 [z_0]_补=0\\ [z_1]_补 = 2^{-1}([z_0]_补+(y_{n+1}-y_n)[x]_补)\\ ...\\ [z_n]_补 = 2^{-1}([z_{n-1}]_补+(y_2 - y_1)[x]_补)\\ [x\cdot y]_补 = [z_n]_补 + (y_1-y_0)[x]_补 [z0]补=0[z1]补=2−1([z0]补+(yn+1−yn)[x]补)...[zn]补=2−1([zn−1]补+(y2−y1)[x]补)[x⋅y]补=[zn]补+(y1−y0)[x]补
我们最后一步要用到 y 0 y_0 y0也就是符号位,所以保留符号位,强硬一点来说,你必须要保留符号位。
叨叨了那么多,做个题缓缓吧
[王道2021年计算机组成原理考研复习指导,p44 例2.8]
机器字长为5位(含1位符号位,n=4),x=-0.1101,y=0.1011,采用Booth算法求 x ⋅ y x\cdot y x⋅y
求得 [ x ] 补 [x]_补 [x]补=11.0011, [ − x ] 补 [-x]_补 [−x]补=00.1101, [ y ] 补 [y]_补 [y]补=0.1011