您的位置:首页 > 理论基础

关于计算机中整数和浮点数运算的一…

2015-01-16 10:44 363 查看
由于浮点数较之整数较复杂,我将先总结整数运算,后总结浮点数运算。

一 整数运算
1加法
这个没什么可讨论的,直接将两个数的补码相加即可得到相应的结果。我们这边重点关注一下整数加法的实现。
保证加法的实现的一个重要基本元件就是全加法器。这个单位元件有3个输入:Xn Yn Cn-1(Xn为第一个数n为上的数
Yn类似 Cn-1是n-1位上传来的进位) 2个输出 Zn 和Cn(Zn为结果 n位上的数,Cn为n位上产生的进位)。
实现加法的结构主要有3种: 1串行加法器 2超前进位加法器 3半超前进位加法器
⒈串行加法器

这个是将多个全加法器串联起来,运算的时候和我们人工计算很类似,实现起来比较简单,但是存在一个严重的问题就是计算每一位都要等到之前一位的进位计算出来才能计算,计算速度特别慢。
⒉超前进位加法器
这个是注意到每一位都可以通过迭代用C1 和本位即本位之前位置上的数表示出来,这样的话这个整个过程的实现只需要计算Xn
Yn的与和或,在把结果和C1传到逻辑运算结构便能一次性得到结果,计算速度特别快。但是这个存在一个问题就是 结构特别复杂。
⒊半超前进位加法器

这种方法是综合了上述2种方法的优点,弱化了他们的缺点。实现方式为,把一个数据化为固定长度的几个部分,对每个部分使用超前进位运算,再把这些部分串联起来。这样话较之串行加法器运算时间大大缩短,较之超前进位加法器线路较为简单。
(鉴于其他运算的实现很复杂,我还不理解,接下来我就不讨论现实结构了)

2减法
这个和加法的实现相差不多,只是将减法符号和第二个数结合,在对两个数做加法。

3乘法
乘法有2种计算方式

⒈普通乘法运算

在乘数前面补个数等于被乘数位数的0,然后开始运算。如果得到的数最后一位是0,那个就直接逻辑右移1位,去掉溢出位,如果最后一位是1,那么在对位数等于被乘数位数的高位加上被乘数,然后右移并去除溢出位。这样做直至乘数的每一位都溢出,最后寄存器里面留下的数就是我们要的结果。(这种方式和我们人工计算类似)
⒉布斯算法

这个是考虑到普通乘法运算存在冗余步骤,在后根据公式推导得到的。这个是在乘数前面加上和被乘数位数相等的0,接着在乘数后方补上一个
0,然后开始运算。将最低位的数前去次低位的数,如果结果为-1,那么高位减去被乘数,然后算数右移一位去除溢出位;如果结果为0,那么直接算数右移一位去除溢出位;如果结果为1,那么高位加上被乘数,然后算数右移一位去除溢出位。这样做直至乘数的最高位被移动到了最低位,或者说右移的次数等于乘数的位数。
最后寄存器里面剩下的就是我们要的结果(最低位是我们补充的不存储在寄存器中)

4除法
除法的运算也存在两种。
1恢复余数的运算

先对被除数进行符号扩展(扩展的位数等于除数的位数)。先左移一位,然后对高位和除数进行操作,操作的规则位:同号则加,异号则减(高位减除数)。然后根据结果判断够不够,判断的标准就是高位的符号是否改变,如果改变了就是不够,我们需要将高位恢复为原来的数,在数据最后补充0;如果符号没改变,那就是够,在数据的最后补充一个1。重复上述步骤直至左移的位数等于被除数的位数。这样还没有结束,我们需要对数据进行处理才能获得我们的结果。我们需要的余数被保存在高位,我们需要的商被保存在低位,但是如果除数和被除数的符号不同,那么我们需要的商等于寄存器低位数的补码。

⒉不恢复余数的运算
这个是鉴于恢复余数预算的过程过于繁琐,开销过大,有关专家想出来简化出发运算的。

实现的方式为:将被除数符号扩展(扩展位数等于除数的位数)。先将高位与乘数进行操作,同加异减,如果得到的结果与除数同号,那么在数据最后补1,否则补0,将数据左移。重复上述操作(最后一次不要左移),直至我们在数据最后补充的位数等于被除数位数加一。最后我们对得到的数据进行处理:如果除数与被除数相同,我们需要的结果被保存在低位和补充出来的一位上(低位的首位不用考虑);如果除数与被除数的符号不同,那么我们需要对先前得到的结果加1。然后对余数进行处理,如果余数符号与被除数符号相同,那么余数正确,如果不同,那么我们对余数和除数进行操作,同加异减。

二浮点数的运算

在讨论浮点数的运算的之前,我们先要了解一下浮点数的表示方法。一般浮点数分32位和64位2种。32位的浮点数,用首位来表示符号位,紧接着的8位来表示指数位(浮点数的实际指数为指数位上的数-127),低23位表示浮点数的小数部分(术语中被称为分数)。我们约定,当指数不为0时,浮点数的整数部分应该为1。

1加法
我们要将2个数中指数较小的数的指数化为和指数较大的数的指数一样大(这样做,而不是将较大指数化为较小指数
是因为将指数较低的数化为指数较高的数
这个过程中这可能会有低位上数的损失,在大多数情况下可以被允许,但是将大指数化为小指数可能会存在高位的损失,只是不能被允许的(虽然即使是这样有时也会导致错误,但我们会有扩展数据类型(或者是增加保护位的方法帮我们减少这种情况的发生)))。这样以后再对我们得到的数进行操作,最后规格化得到结果。

2减法
这个和差不多一样。减去一个数就等价于加上这个数的补码。

(上面方法得到数的符号的讨论(前提,我们都是将两个数化为相同符号的数来做,如果是异号数的加法等于同号数的减法):加法的话就直接加,最后的符号等于被加数的符号,如果是减法,如果存在溢出位,那么去掉溢出位的数就是结果,结果的符号与被减数的符号相同,如果不存在溢出位,那么我们需要的结果为当前结果的补码,结果的符号与被减数相反)

3乘法
结果的符号位为2个数符号位的异或。
结果的指数位(初步确定)为2个数指数位相加减去127

然后我们对两者的分数部分进行普通乘法运算,最后小数点点在次高位的后面(这个把2个分数看作个整数为1。的23位小数就可以很容易理解)最后对得到的结果进行规格化操作就可以得到我们需要的答案。

4除法
结果的符号位为2个数符号位的异或。
结果的指数位(初步确定)为被减数的指数减去除数的指数+127

然后我们对两者的分数部分进行不恢复余数的除法操作(注意,我们这时候的操作元没有符号,我们不能完全按照整数除法的规则,我们要把2个数都看作正数,够减的话
减掉补1,不够减的话 补0,然后在左移(注意我我们这里是先判断够不够,如果再左移,整数除法里面是先左移在判断))。

在浮点数运算的时候还有一个保护位的概念,这个和2种浮点数表示方法的扩展类型就有关系了。扩展数据类型的出现就是保证浮点数中间运算结果不会因为原先数据类型中的精度限制而导致数据上溢或者下溢而造成的数据损失和计算错误,保护位只是在原先数据后面添加几位保存以确保数据右移的时候不会存在精度损失,剩下的和之前运算不存在差异,再次不做赘述。(注意
使用了保护位之后就需要对最后结果进行舍入操作(有就近摄入,有向0摄入,和向正负无穷舍入这几种),保护位的使用不一定会使计算的最后结果正确率更高)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐