定点数的运算——定点数的乘法

定点数,顾名思义就是,小数点确定的数,当小数点确定在所有数的最右边,那就是整数运算,当确定在数的最左边,那就是小数运算,浮点数就是确定在尾数的最左边,并省去了整数部分的1。

定点数的乘法和除法都是仿照手写计算过程来实现并依据计算机的特性来改进的,我们今天先来看乘法运算。

手动计算

我们先来看看手动乘法计算过程:

假设二进制定点数X=1011Y=1101,计算他们的乘数可得:

手算计算过程


我们可以看出,手算乘法是这样一个过程:

(1)从Y的第一位开始与X相乘,Y_i为0时得到相应位数的0,否则得到X。

(2)将上述每一位结果依次向左错位排列,可以看作左移。

(3)得到他们的和。

然后我们就得到了这两个数的乘积。

原码乘法

原码是浮点数尾数的表示形式,需要计算机能实现顶点原码小数的乘法运算。

原码乘法分两步:(1)有两个数的符号位异或得到乘积符号位;(2)计算乘积的数值位。乘积的数值部分为两个乘数的数值部分之积。



小数点不用管,计算机内部没有小数点的表示,只是约定了它的位置。因此我们可以将两个定点小数的数值部分之积看成是两个无符号数的乘积


计算机进行无符号数的乘法计算时,采用了类似手算的方法。但为了提高效率,做了相应改进:

(1)每当将乘数Y的一位乘以被乘数得到X\times Y_i后,就将它与前面的结果累加得到P_i,我们把它叫做部分积。

        这个改进没有等到全部计算完毕再进行移位和加和的操作,减少了保存每次的X\times Y_i的开销。

(2)每次求得X\times Y_i后,不是将它左移与前次部分积相加,而是将部分积P_i右移一位,再以相应的高位与其相加。

        (上文提到过,计算机中原码多用于表示浮点数的尾数部分,因此原码乘法中,小数乘法占了大多数。

            计算机中的左移操作,对应于实际计算中的\times 2操作,右移操作对应于\times 2^{-1}的操作,后者于小数计算更有利,而整数多用补码来进行计算,后文将讲到专门的布斯乘法来进行更便利的整数乘法)

(3)对乘数中为1的位进行加法和右移运算,而对乘数中为0的位只进行右移运算


这样做的好处在于,如果按照手算操作,原本需要非常多位的储存与计算加法器,现在经过简化,只需要X\times Y_i的高n位进行相加,低位都不会改变,因此只需要n位的加法器就可以实现两个n位的无符号数的相乘,需要的存储容量也大大降低。




上述思想的数学推导如下:

X\times Y=X \times (0.Y_1 Y_2 \dots Y_n)

                =X \times Y_1 \times 2^{-1}+X \times Y_2 \times 2^{-2}+X \times Y_3 \times 2^{-3}+\dots +X \times Y_n \times 2^{-n}

                =2^{-1}(2^{-1}(2^{-1}\dots 2^{-1}(2^{-1}(0+X\times Y_n)+X\times Y_{n-1})+ \dots +X\times Y_2)+X\times Y_1)

其中有n个2^{-1}

上述推导过程具有明显的递推公式,我们可以观察得出,其递推公式为:

P_{i+1}=2^{-1}(P_i+X\times Y_{n-i})         (i=0,1,2,3,\dots,n-1)

我们可以设P_0=0


我们将上述推导过程的迭代过程归结如下:

(1)取乘数的最低位Y_{n-i}判断;

(2)若Y_{n-i}为1,则将上一步迭代部分积P_i与X相加;若Y_{n-i}为0,则什么也不做。

(3)右移一位,产生本次部分积P_{i+1}



进行无符号数相加时,P_i和X相加可能会产生进位,因而需要有一个专门的进位C

整个迭代过程从P_0和乘数最低位Y_n开始,经过n次“判断—加法—右移”循环,直到求出P_n为止。假定每次循环在一个始终周期内开始,那么完成n位乘法就需要用n个时钟周期来完成。

32位无符号数乘法的逻辑结构图为:


其中,部分积与乘数Y是放在一个64位寄存器中的,Y的最低位判断相乘过后便没用了,右移一位舍弃它,P的右移也能留出空间,节省存储。

乘数寄存器Y一开始放置的是乘数,结束时放置的是64位乘积的低32位‘乘数寄存器P一开始放置的是P_0,结束时放置的是64位乘积的高32位。


每次循环都要对进位位C、乘积寄存器P和乘数寄存器Y实现同步“右移”。

当乘数或被乘数中至少有一个全为0时,结果直接得0,不在进行乘法运算。

补码乘法运算

补码是机器中带符号整数的表现形式,需要计算机能实现补码乘法运算。

我们在计算时,常常将补码转换为原码形式,然后进行相应运算后再将结果转换为补码,但是这样太过繁琐。不骂的乘法也没有加法那样方便的特性,于是我们需要一个新的算法来计算不乏的乘法。

A.D.Booth提出了一种补码相乘算法,可以将符号位与数值位合在一起参与运算。于是称为“布斯算法”。


类似于原码,我们先进行利用补码形式的运算数学推导,观察得出其迭代或递推式:

假设[x]_{补}=X_{n-1}\dots X_1 X_0,[y]_{补}=Y_{n-1}\dots Y_1 Y_0

根据补码的定义,我们可以得到y的真值表达式为:

y=-Y_{n-1} 2^{n-1}+\sum_{i=0}^{n-2}Y_i 2^i


这里对y的第一项做一下解释。

我们都知道最开始的不添加任何符号的二进制数,也就是原码表示的无符号数,本来是只能表示0~2^{n}-1(n是用来表示二进制最大位数)的数,我们为了计算机的运算方便,才对二进制的表示形式做出种种规定。

而补码表示法,将正负数置于mod(2^{n-1})(n依然是最大位数)的系统之下,巧妙地利用了模的特性是计算机的运算变得更加简单快捷。

在模运算系统中,若ABM满足关系:A=B+K\times M(K为整数),则记为:A\equiv B(mod\quad M),即A与B模M后余数相同,称为A与B同余。在一个模系统中,一个数与它除以模后得到的余数是等价的。

利用这个等价关系,计算机的前辈们把负数与其同余的正数等价起来,也就是说负数在模2^{n}的系统下,跟这个数加2^{n}得到的正数是等价的。这样补码就诞生了。

所以在补码中,如果这个数是一个负数,我们计算出它的十进制真值可以先取反加一再取负数,也可以直接把它当做原码表示法,计算出其正数真值,然后再减去2^{n-1},得到其表示为补码时所代表的的真值。

所以我们再回到y的真值表达式中来:

y=-Y_{n-1} 2^{n-1}+\sum_{i=0}^{n-2}Y_i 2^i

后面得到了它原码表示法时的十进制正数真值,当最高位为1时,它是负数,减去2^{n-1};为0时,它是正数,正数的原码表示法跟补码表示法是一样的,此时这一项为0,不影响结果正确。


我们在这个式子基础上进行归纳化简:

y=-Y_{n-1} 2^{n-1}+Y_{n-2} 2^{n-2}+\dots+Y_1 2^1+Y_0 2^0

    =-Y_{n-1} 2^{n-1}+Y_{n-1} 2^{n-1}-Y_{n-2}2^{n-2}+\dots+Y_12^2-Y_1 2^1+Y_0 2^1-Y_0 2^0

    =(Y_{n-2}-Y_{n-1})2^{n-1}+(Y_{n-2}+Y_{n-3}) 2^{n-2}+\dots+(Y_0-Y_1) 2^1 +(0-Y_0)2^0

    =\sum_{i=0}^{n-1}(Y_{i-1}-Y_{i})2^i

(设Y_{-1}=0)

与无符号数乘法算法类似,我们可以得出:

x\times y=x\times \sum_{i=0}^{n-1}(Y_{i-1}-Y_{i}) 2^i

与无符号数算法一样,我们可以不用考虑小数点的位置,只要最终的乘积约定好小数点位置就可以了。因此上述式子可以通过乘以2^{-n}来变换成下列形式:

x\times y=x\times \sum_{i=0}^{n-1}(Y_{i-1}-Y_{i}) 2^{-(n-i)}

展开观察,我们可以得到递推公式为:

P_{i+1}=2^{-1}(P_{i}+(Y_{i-1}-Y_i)x)

由此公式又可以得到:

P_{1}=2^{-1}(P_{0}+(Y_{-1}-Y_{0})\times x)

\dots

P_{n-1}=2^{-1}(P_{n-2}+(Y_{n-3}-Y_{n-2})\times x)

P_{n}=2^{-1}(P_{n-1}+(Y_{n-2}-Y_{n-1})\times x)

对于小数点的问题,比较刚归纳完的式子,我们可以知道x\times y=2^{n}P_{n},但是我们提过计算机中小数点的位置是可以随意约定的,因此我们在计算完毕之后将小数点的位置约定在乘积的最右边。

从上面的递推式,我们可以知道,布斯算法的部分积是由乘数中的连续两位确定的,因此我们可以得到它的规则为:

(1)若Y_{i}Y_{i-1}=01P_{i+1}=2^{-1}(P_i+x)

(2)若Y_{i}Y_{i-1}=10P_{i+1}=2^{-1}(P_i-x)

(3)若Y_{i}Y_{i-1}=11或00P_{i+1}=2^{-1}(P_i+0)

2^{-1}代表右移

那么根据以上的分析,我们可以得出补码乘法运算规则如下:
(1)乘法最低位增加一位辅助位,即Y_{-1}=0

(2)根据Y_{i}Y_{i-1}的值,决定部分积+[x]_{补}还是+[-x]_{补},或者不加减;

(3)每次加减后算术右移一位,得到部分积;

(4)重复第(2)(3)步 n 次,得到结果。



补码乘法运算逻辑结构图

布斯算法经过n次“判断-加减-右移”循环,当遇到,会直接跳过加法运算进行右移运算,因此效率较高。




©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容