原码一位乘:
计算 a * b, a = -0.1101, b = 0.1011, a/b 均为二进制表示
0.1101 14
×0.1011 ×14
———————— ————————
1101 56
1101 14
0000 ——————————
1101 196
———————————————
0.10001111
1、通过两种比较可以看出:
1)二进制乘法和十进制乘法的列竖式的规则相同
2)每取一位乘数,就可以确定一位未确定的最低位
因此,可以将暂时未确定的结果存放到 acc 中,将乘数存放到 mq 中,每计算
一次,将 acc 和 mq 整体右移一位,将确定的一位结果存到 mq,同时将使用
过的乘数的无用的一位剔除。
2、上面 1 描述的过程可以通过证明得到:
a * b = a * 0.1011 = 0.1a + 0.00a + 0.001a + 0.0001a
= 2 ^ (-1) a + 0 * a + 2 ^ (-3) a + 2 ^ (-4) a
= 2 ^ (-1) * [ a + 0 * a + 2 ^ (-2) a + 2 ^ (-3) a ]
= 2 ^ (-1) * { a + 2 ^ (-1) * [ 0 * a + 2 ^ (-1) a + 2 ^ (-2) a ] }
= 2 ^ (-1) * { a + 2 ^ (-1) * { 0 * a + 2 ^ (-1) * [ a + 2 ^ (-1) a ] } }
= 2 ^ (-1) * { a + 2 ^ (-1) * { 0 * a + 2 ^ (-1) * [ a + 2 ^ (-1) (a + 0 ) ] } }
从上述得到的结果表达式可以看出,这是一个递归过程,结果初始值为 0,每
一次加上一个 除数对应位 * a 后乘一个 2 ^ (-1),相当于右移一位(除以2),
依次执行的过程就是 1 中描述的过程。
3、上面的运算只能得到数值位运算的结果,符号位需要另行判断,最后 在数值上
添加上符号位即可。
4、原码一位乘 加 n 次,移 n 次,n 为乘数数值位的位数
原码一位乘具体规则:
1、被乘数和乘数均取绝对值参加运算,符号位单独处理
2、被乘数取双符号位
3、从乘数的最低位开始判断:
最低位为1,则部分积(上面提到的暂未确定的结果)加上被乘数绝对值,右移一位
最低位为0,则部分积加上0,右移一位
4、重复 3,判断 n 次(n为数值位位数)
原码一位乘特点:
1、绝对值运算
2、用移位的次数判断乘法是否结束
3、逻辑移位
原码一位乘具体步骤示例(实际为表格形式):
|部分积 |乘数 |说明
|00.0000 |1011 | 初始状态,部分积 = 0
|00.1101 | | yn(乘数最低位) = 1, 加被乘数|a|
———————————————————————————————————————————
|00.1101 | |
|00.0110 |1 101 | ——> 1(右移), 形成新的部分积
|00.1101 | | yn = 1, 加被乘数 |a|
———————————————————————————————————————————
|01.0011 |1 |
|00.1001 |11 10 | ——> 1, 形成新的部分积
|00.0000 | | yn = 0, 加 0
———————————————————————————————————————————
|00.1001 |11 |
|00.0100 |111 1 | ——> 1, 形成新的部分积
|00.1101 | | yn = 1, 加被乘数 |a|
———————————————————————————————————————————
|01.0001 |111 |
|00.1000 |1111 | ——> 1, 得结果
符号位:as 异或 bs = 0 异或 1 = 1
所以 a * b = 1.10001111, 即 - 0.10001111
1、上面的双符号位为了保存进位和符号位,原码一位乘符号位不考虑,
用一位符号位也可,但为了规范起见,尽量用两位符号位。
2、上面的具体示例中乘数中间本没有空格,只是为了区分结果和乘数
特意加上的,()也没有,为了说明具体符号内涵而加上的
补码一位乘:
设[X]补 = xs.x1x2---xn [Y]补 = ys.y1y2---yn
1、校正法:
1)被乘数任意,乘数为正
[X]补 = xs.x1x2 …xn = 2 + X = 2n + 1 + X (mod 2)
[Y]补 = Y = 0.y1y2… yn
[X]补 * [Y]补 = ( 2n + 1 + X ) * Y = 2n + 1 * Y + X * Y
=2 * 2n * 0.y1y2… yn + X * Y
=2 + X * Y = [X * Y]补 (mod 2)
即:[X]补 * [Y]补 = [X * Y]补 = [X]补 * Y
所以:这种情况可以按原码一位乘法的规则运算,结果不需要矫正
2)被乘数任意,乘数为负
[X]补 = xs.x1x2 …xn
[Y]补 = 1.y1y2… yn = 2 + Y (mod 2)
则 Y = [Y]补 - 2 = 1.y1y2… yn-2 = 0.y1y2… yn - 1
X * Y =X * (0.y1y2… yn - 1) = X * 0.y1y2… yn - X
故 [X * Y]补 = [X * 0.y1y2… yn ]补 + [- X ]补
将上式中 0.y1y2… yn 视为一个正数,正好与情况 1) 相同
则 [X * Y]补= [X]补 * ( 0.y1y2… yn ) + [- X ]补
所以:这种情况可以先把 [y]补 的符号位丢掉不管,仍按原码一位乘运
算,最后加 [-x]补 进行矫正
结果综合:
[x * y]补 = [x]补 * (0.y1y2---yn) Y>0
[x * y]补 = [x]补 * (0.y1y2---yn) + [-x]补 Y<0
2、比较法(booth算法):
由矫正法知:
[x * y]补 = [x]补 * (0.y1y2---yn) Y>0
[x * y]补 = [x]补 * (0.y1y2---yn) + [-x]补 Y<0
合并,有:
[x * y]补 = [x]补 * (0.y1y2---yn) + [-x]补 * ys
= [x]补 * (y1 * 2 ^ (-1) + y2 * 2 ^ (-2) + --- + yn * 2 ^ (-n)) - [x]补 * ys
= [x]补 * (-ys + y1 * 2 ^ (-1) + y2 * 2 ^ (-2) + --- + yn * 2 ^(-n))
= [x]补 * [ -ys + (y1 - y1 * 2 ^ (-1)) + (y2 * 2 ^ (-1) - y2 * 2 ^ (-2)) + --- + yn * 2 ^ (-(n - 1) - yn * 2 ^ (-n))]
= [x]补 * [(y1 - ys) + (y2 - y1) * 2 ^ (-1) + --- + (yn - y(n-1) * 2 ^ (-(n - 1))) + (0 - yn) * 2 ^ (-n)]
= [x]补 * [(y1 - ys) + (y2 - y1) * 2 ^ (-1) + --- + (yn - y(n-1) * 2 ^ (-(n - 1))) + (y(n + 1) - yn) * 2 ^ (-n)]
接着,类似于开头中证明的那样提 2 ^ (-1) 使得这个多项式成为开头证明的那种形式,但是这样做会使得最终的表达式非常长,不利于
观看,所以,这里用booth递推算法来得到公式:
令[z0]补 = 0
[z1]补 = 2 ^ (-1) * { ( y(n + 1) - yn ) [x]补 + [z0]补 } y(n + 1) = 0
[zi]补 = 2 ^ (-1) * { (y(n - i + 2) - y(n - i + 1))[x]补 + [z(i - 1)]补 }
[zn]补 = 2 ^ (-1) * { (y2 - y1)[x]补 + [z(n - 1)]补 }
最后得到:
[x * y]补 = [zn]补 + (y1 - ys)[x]补
所以,求解 [x * y]补 的重点就落到了求 y(i + 1) - yi上,由此,对 y(i + 1) - yi 的取值规定一些操作:
| yi y(i + 1) | y(i + 1) - yi | 操作
| 0 0 | 0 | ——>1
| 0 1 | 1 | + [x]补 ——>1
| 1 0 | -1 | + [-x]补 ——>1
| 1 1 | 0 | ——>1
booth算法具体运算规则:
1、参加运算的数均以补码表示
2、符号位参加运算
3、被乘数和部分积去双符号位参加运算,部分积初值为0
4、乘数取单符号位,以决定最后一步是否需要矫正,即是否要加[-x]补
5、乘数末位增加附加位 y(n + 1),且初始值为0
6、乘数的最低两位 yn 和 y(n + 1) 构成了各步运算的判断位,如下表所示
7、一位按补码右移规则进行
8、按照上述运算进行 n + 1 步操作,但第 n + 1 步不移位,仅根据 y0 与 y1 的比较结果判断加或者不加
1、对于上面的矫正法,只需要记住综合后面的公式,套公式即可
上述过程可能较为复杂,我们具体拿题来看:
1、校正法:
已知 x = +0.1101 y = – 0.1011 求[x·y]补
解:
[x]补 = 00.1101
[y]补 = 11.0101
[-x]补 = 11.0011
| 部分积 | 乘数 | 说明
| 00.0000 | 0101 | 初始状态,部分积为 0
| 00.1101 | | yn = 1, + [x]补
—————————————————————————————————————————
| 00.1101 | |
| 00.0110 | 1 010 | ——>1, 形成新的部分积
| 00.0000 | | yn = 0, + 0
—————————————————————————————————————————
| 00.0110 | |
| 00.0011 | 01 01 | ——>1, 形成新的部分积
| 00.1101 | | yn = 1, + [x]补
—————————————————————————————————————————
| 01.0000 | |
| 00.1000 | 0010 | ——>1, 形成新的部分积
| 00.0000 | | yn = 0, + 0
—————————————————————————————————————————
| 00.1000 | |
| 00.0100 | 0001 | ——>, 形成新的部分积 // 这部分之前和原码一位乘类似,只不过加的是 [x]补 和 0
| 11.0011 | | + [-x]补 (因为乘数是负数) // 对结果进行校正,遵循上面的公式
—————————————————————————————————————————
| 11.0111 | 0001 | (这里不移位)
所以:[x * y]补 = 11.01110001
x * y = -0.10001111
2、比较法:
已知 x = +0.0011 y = – 0.1011 求[x·y]补
解:[x]补 = 00.0011
[-x]补 = 11.1101
| 部分积 | 乘数 | y(n + 1) | 说明
| 00.0000 | 1.0101 | 0 |
| 11.1101 | | | + [-x]补 // 这里遵循上面的 y(i + 1) - yi 的那张表,y(i + 1) 是该表中的 y(n + 1), 他每一次用乘数最后一位更新,yi 是当前乘数的最后一位。
——————————————————————————————————————
| 11.1101 | | |
| 11.1110 | 1 1010 | 1 | ——>1
| 00.0011 | | | + [x]补
——————————————————————————————————————
| 00.0001 | 1 | |
| 00.0000 | 11 101 | 0 | ——>1
| 11.1101 | | | + [-x]补
——————————————————————————————————————
| 11.1101 | 11 | |
| 11.1110 | 111 10 | 1 | ——>1
| 00.0011 | | | + [x]补
——————————————————————————————————————
| 00.0001 | 111 | |
| 00.0000 | 1111 1 | 0 | ——>1
| 11.1101 | | | + [-x]补
——————————————————————————————————————
| 11.1101 | 1111 | | 最后一步不移位
1、补码一位乘比较法连同符号位一起运算
校正法的被乘数符号位加入运算,乘数的符号位不加入运算,只决定最后是否加 [-x]补 进行校正
2、补码一位乘校正法加 n 次(没算校正加的那次),移 n 次, n 为乘数数值位数
比较法加 n + 1 次, 移位 n 次,n 为乘数数值位位数
最后:如果这篇文章有什么错误的地方,欢迎评论区留言,小编一定尽快改正。