网站首页 波兰世界杯 世界杯球星排名 直播吧世界杯
首页 >> 直播吧世界杯
补码一位乘法

补码一位乘法

补码一位乘法 为什么要使用补码乘法? 在计算机中,使用一般乘法的话,对符号位还要重新进行异或操作,这样会大大降低运算速度,而使用...

补码一位乘法

为什么要使用补码乘法?

在计算机中,使用一般乘法的话,对符号位还要重新进行异或操作,这样会大大降低运算速度,而使用补码乘法运算,就可以找到一种通用的解法来解决符号位的重复计算,而将符号位作为数字一起带入运算器进行计算

补码一位乘法规则

首先说明一下,为了便于证明,下面的证明都是在小数的基础上进行的,小数证明以后便可以直接推广整数

假设被乘数为

[

x

]

[x]_补

[x]补​

[

x

]

=

x

0

x

1

x

2

x

3

.

.

.

x

n

[x]_补=x_0x_1x_2x_3...x_n

[x]补​=x0​x1​x2​x3​...xn​ 乘数为

[

y

]

[y]_补

[y]补​

[

y

]

=

y

0

y

1

y

2

y

3

.

.

.

y

n

[y]_补=y_0y_1y_2y_3...y_n

[y]补​=y0​y1​y2​y3​...yn​

两者均为任意的符号位,则有补码乘法公式:

[

x

y

]

=

[

x

]

y

[x*y]_补=[x]_补*y\\

[x∗y]补​=[x]补​∗y 而由补码与其真值的关系:

[

y

]

=

2

+

y

(

m

o

d

2

)

y

=

y

0

+

i

=

1

n

y

i

2

i

[y]_补=2+y\ \ (mod\ \ 2)\\ y=-y_0+\sum_{i=1}^ny_i2^{-i}

[y]补​=2+y (mod 2)y=−y0​+i=1∑n​yi​2−i (这个还是比较好证明的,对于正数,前面+2直接溢出了,所以还是等于y,而对于负数,第一次+1相当于是进行了一次模1运算,使其数值位跟补码一致,第二次+1相当于纠正了符号位为负数)

我们可以得到:

[

x

y

]

=

[

x

]

(

y

0

+

i

=

1

n

y

i

2

i

)

[x*y]_补=[x]_补*(-y_0+\sum_{i=1}^ny_i2^{-i})\\

[x∗y]补​=[x]补​∗(−y0​+i=1∑n​yi​2−i) 在此我们可以对以上的补码乘法公式进行证明

[

x

]

=

x

0

x

1

x

2

.

.

.

x

n

=

(

2

x

0

+

x

)

m

o

d

2

=

(

2

n

+

1

x

0

+

x

)

m

o

d

2

[

y

]

=

0

y

1

y

2

.

.

.

y

n

=

y

[

x

]

y

=

(

2

n

+

1

x

0

+

x

)

y

=

2

n

+

1

x

0

y

+

x

y

y

=

(

y

0

+

i

=

1

n

y

i

2

i

)

[

x

]

y

=

(

2

n

+

1

x

0

y

0

+

2

x

0

i

=

1

n

y

i

2

n

i

)

+

x

y

(

m

o

d

2

)

=

2

+

x

y

(

m

o

d

2

)

2

=

[

x

y

]

\begin{aligned} &\ \ \ [x]_补=x_0x_1x_2...x_n=(2x_0+x)\ \ mod\ \ 2=(2^{n+1}x_0+x)\ \ mod\ \ 2\\ &\ \ \ [y]_补=0y_1y_2...y_n=y\\ \therefore&\ \ \ [x]_补*y=(2^{n+1}x_0+x)y=2^{n+1}x_0y+xy\\ \because&\ \ \ y=(-y_0+\sum_{i=1}^ny_i2^{-i})\\ \therefore&\ \ \ [x]_补*y=(-2^{n+1}x_0y_0+2x_0\sum_{i=1}^ny_i2^{n-i})+xy\ \ (mod\ \ 2)\\ &\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =2+xy \ \ \ (mod\ \ 2)【这里要根据模2性质进行推导】\\ &\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =[xy]_补 \end{aligned}

∴∵∴​ [x]补​=x0​x1​x2​...xn​=(2x0​+x) mod 2=(2n+1x0​+x) mod 2 [y]补​=0y1​y2​...yn​=y [x]补​∗y=(2n+1x0​+x)y=2n+1x0​y+xy y=(−y0​+i=1∑n​yi​2−i) [x]补​∗y=(−2n+1x0​y0​+2x0​i=1∑n​yi​2n−i)+xy (mod 2) =2+xy (mod 2)【这里要根据模2性质进行推导】 =[xy]补​​ 其实由上面的共识我们可以很容易得到公式:

[

x

y

]

=

[

x

]

(

0

y

1

y

2

.

.

.

y

n

)

[

x

]

y

0

[xy]_补=[x]_补(0y_1y_2...y_n)-[x]_补*y_0

[xy]补​=[x]补​(0y1​y2​...yn​)−[x]补​∗y0​ 使用这样的公式来求补码乘法,我们称之为校正法

对了,记住在使用校正法时应该是使用算数右移,即移动的时候ACC寄存器中补位的数应该跟ACC寄存器中的第一位一致

为什么要用Booth算法?

在一般的补码乘法中,我们进行加法运算的次数和加法中1的个数存在直接关系,而对于乘数中1比较多的情况,如果还是采用一般的补码乘法运算显然就比较低效,因此我们使用的Booth算法,这样只有在前后两位产生01的变化时才需要进行加法(或者减法,但是计算机中的减法其实就是加法,所以不用细究)运算。这样就可以大大提高运算效率了

Booth算法规则

第一,我们需要知道补码的运算规律是使用n轮加法与移位,最后在多进行一次加法,关于为什么要多一次加法,如果大家使用乘法分配律来理解就很容易知道了,因为最后一定会加一个数,不要问为什么,只要理解了乘法分配律就知道了

其次,补码一位乘法中,每次加法加的可能是

0

[

x

]

[

x

]

0、[x]_补、[-x]_补

0、[x]补​、[−x]补​,这又与原码移位算法不一样了

还有,对于补码一位乘法,每次移位只能是算数移位,也就是在前面补位时,补的位和符号位一样(只有第一位才是符号位嗷)

最最最关键的一点,在补码一位运算中,符号位也会参与运算!!!

符号位参与运算❓

大家一定会疑惑,为什么符号位也能参与运算?

原因很简单,在补码中,符号位并不是真的没有意义的,因为我们会发现,在真值跟补码的关系中,我们是可以找到一种方式将他们联系起来的

补码只对负数存在特别之处,但是对于正数跟原码是没有区别的,我们会发现,比如-1,他的补码其实就是

11111111

11111111

11111111

当我们对他进行+1操作以后,它就会变成100000000,但是由于最大表示位只有八位(在例子中),所以最后的结果会默认变成00000000也就是0

所以说,我们可以认为对于负数t来说,补码就是

2

n

+

t

2^n+t

2n+t的二进制位(要去掉超出的位数,n为最大位数),而我们会发现,对于0和正数来说,这个规律同样适用

所以我们会发现,这个所谓的符号位其实也可以当作数来计算,但是它同样担负着确认正负的重要职责,所以在转化的时候,我们只会将符号位转化为正负,而不会转化成数值

但是我们在计算过程中其实可以将它当作数值来看待,反正超出的位对我们没有什么影响(电路自动进行模运算)

运算法则

首先,在运算过程中,我们在MQ中会多使用一位来作为辅助位,以决定我们当前这一步到底进行加法还是减法运算,也因为MQ多了一位,所以其他寄存器也要跟着多添加一位

运算法则如上图,其实翻译过来就是,算上辅助位,

当在MQ寄存器中最后两位是01时就进行加x的补码,再进行右移位

当是10时就进行减x的补码的操作,也就是加

[

x

]

[-x]_补

[−x]补​的操作,再进行右移位

其余的时候只要直接进行右移位就行了

WHY?

这里我不确保我能讲的明白,其实理解上就是一种乘法分配律,如果看不懂的可以看这篇博客

对于任意一个数,我们在小学的时候经常会学习使用一种办法化繁为简,比如计算

9

99

9*99

9∗99时,我们会将其拆分成

9

(

100

1

)

9*(100-1)

9∗(100−1)

这里我们其实用的是一个道理,比如对于010111110,我们可以拆分成(100000000-01000000+001000000-000000010)

这样我们就可以使用更少的加法来简化运算了,可以观察到,本来我们要使用6次加法运算,现在我们只需要使用4次加法运算即可(计算机中减法也是通过加法完成的)

这里其实在数学上也是存在证明的,对于一个数A来说,我们可以写成下面的形式:

A

=

x

n

1

2

n

1

+

x

n

2

2

n

2

+

.

.

.

+

x

0

2

0

=

x

n

1

2

n

1

+

x

n

2

(

2

n

1

2

n

2

)

+

.

.

.

+

x

0

(

2

1

2

0

)

=

2

n

1

(

x

n

2

x

n

1

)

+

2

n

2

(

x

n

3

x

n

2

)

+

2

1

(

x

0

x

1

)

+

2

0

(

0

x

0

)

x

1

=

0

,

便

=

i

=

1

n

2

i

1

(

x

i

2

x

i

1

)

\begin{aligned} A&=-x_{n-1}*2^{n-1}+x_{n-2}*2^{n-2}+...+x_0*2^0\\ &=-x_{n-1}*2^{n-1}+x_{n-2}*(2^{n-1}-2^{n-2})+...+x_0*(2^1-2^0)\\ &=2^{n-1}*(x_{n-2}-x_{n-1})+2^{n-2}*(x_{n-3}-x_{n-2})+2^1(x_0-x_1)+2^0(0-x_0)\\ 这&里我们不妨虚构出一个x_{-1}=0,以便得到通用结论\\ \therefore原式&=\sum_{i=1}^n2^{i-1}*(x_{i-2}-x_{i-1}) \end{aligned}

A这∴原式​=−xn−1​∗2n−1+xn−2​∗2n−2+...+x0​∗20=−xn−1​∗2n−1+xn−2​∗(2n−1−2n−2)+...+x0​∗(21−20)=2n−1∗(xn−2​−xn−1​)+2n−2∗(xn−3​−xn−2​)+21(x0​−x1​)+20(0−x0​)里我们不妨虚构出一个x−1​=0,以便得到通用结论=i=1∑n​2i−1∗(xi−2​−xi−1​)​ 由此我们得证上面式子的正确性

于是我们便可以直接使用上面的结论进行Booth算法的计算,这里我直接饮用了王道的ppt,大家可以试着自己算一下

如果说实在想不起来Booth算法的规则,我们也可以使用化繁为简的方法