浮点数的加减法运算

浮点数的加减法运算

本文内容参考自王达老师的《深入理解计算机网络》一书<中国水利水电出版社>

浮点数与定点数相比较有两个比较明显地特点:1、小数点位置不固定,但是在浮点数加减法运算的时候,小数点必须对齐;2、存储器中存储的不是浮点数的直接值,而存储的是符号,尾数,移码/阶码三种要素,所以不能直接相加减,实际上,针对浮点数的加减法运算,只需要对代表浮点数有效部分的尾数进行加减运算。
所以,浮点数的运算相对整数运算更复杂,有关浮点数的加减法运算包括以下5个基本步骤:对阶,尾数运算、规格化处理、舍入处理、益出处理。
—引自王达老师《深入理解计算机网络》一书

一、浮点数运算(总共包括5个步骤):
  • 1、对阶
    对阶就是比较参与运算的浮点数的阶码大小,然后使他们的阶码(或移码)都一样,其最终目的是使参与运算的数的小数点位置对齐,以便得出正确的结果。
    既然需要使参与运算的浮点数的阶码一样,这时就要以某一个浮点数的阶码为标准了,通常以大阶码为准,即阶码小的数,要向阶码大的数对齐,也就是将小阶码的值调成与大阶码的值一样,这时,为了确保小阶码的数值与原来的保持一致,肯定需要对小阶码的尾数的小数点进行移位,就像十进制数中的1.2345 * 103,如果将指数3变成5,那么尾数1.2345的小数点位置不可能保持不变,要向左移两位,变成0.012345,所以,最终的形式为0.012345 * 105
    因为是以大阶码为准,所以小阶码需要增大,那么尾数需要做相同倍数的减小,才能保持数值不变(即阶码小的尾数需要向右移对应的位数[小数点是向左移]),因为原则是,在尾数最高位前面加对应数量的0,然后原尾数最后的对应尾数直接丢弃,移了多少位就丢弃多少位(直接丢弃是因为存储尾数的存储器空间是固定的)。

    对阶中的尾数移位可以借助十进制的科学计数法来帮助理解,假设十进制数1234.5原来表示成1.2345 * 103,现在需要表示成106的格式,则对应的格式为0.0012345 * 106(在原来的小数点右边最高位前面移了三位,补加了两个0),又假设小数点后面最多只能4位(浮点数中用来保存尾数的存储空间是固定的),这样一来,最终的存储格式是0.0012 * 106,尾数中原来的"345"就被丢弃了,虽然这会在一定程度上导致与原值有区别,但还是在最大限度上保持了不变。

    示例:X = 20010 * 0.11000101,Y = 20100 * 0.10101110。对这两个浮点数进行加减法运算(尾数的符号位是体现在浮点数的符号位上,阶码和尾数均已采用补码形式表示)。
    X的阶码为0010,对应的十进制数位2,Y的阶码为0100,对应的十进制数为4,因此,X的阶码比Y的阶码小,此时应将X的阶码变成与Y的阶码一样,即都调成4,同时需要将X的尾数小数点左移2位(在小数点右边最高位前面加两个0,原来最低的2位被丢弃,这样才能使X的值与原来保持基本不变)。
    X原来的尾数为11000101,向右移两位(仍要保持原来的总位数不变,则要在前面补相应位数的0,原来最右边的对应两位丢弃),则变成了00110001,这样一来,X的阶码也变成了0100,最终X在存储器中的格式是0 0100 00110001(原来为0 0010 11000101)。

  • 2、尾数运算
    通过对阶将尾数的小数点对齐之后,就能将经过移位的尾数进行加减运算,这一步很简单,可以直接参照博文–“无符号二进制运算”。
    继续前面的示例:X = 20010 * 0.11000101,Y = 20100 * 0.10101110,现要求X+Y。
    X对阶后的尾数为00110001,Y的尾数不变,为10101110,两者相加:

       X  00110001
       Y  10101110
    结果  11011111
    
  • 3、规格化处理
    规格化处理主要是针对浮点数的尾数部分,规格化的尾数格式要求如下:
    尾数采用原码表示形式时:正数的规格化格式为:0.1XXX,负数的规格化形式为1.1XXX。
    尾数采用补码表示形式时,正数的规格化格式为:0.1XXX,负数的规格化形式为:1.0XXX。
    以上的最高位均代表符号位(0代表正数,1代表负数),关键是看小数点后面的数的格式。

    对于双符号位(用两位来表示符号)的补码形式尾数,正数的规格化格式为00.1XXX,负数的规格化格式为:11.0XXX,以上最高两位代表符号位(00代表正数,11代表负数),关键是看小数点后面数的格式。
    引入双符号位的设计目的就是为了能快速检测出运算结果是否有溢出,因为双符号位规定了"00代表正数,11代表负数",如果最高两位不是这两种形式,而是"01"或者是"10"就能快速知道有溢出了,符号位为"01"的时候称为"上溢",即最高真值位相加后有进1,为"10"时,称为"下溢",即最高真值位相减后有借1。
    —引自王达老师《深入理解计算机网络》一书

    本文内容仅涉及单符号位,有兴趣了解双符号位的,可以关注后续博文。
    凡不符合以上格式要求的尾数均要进行规格化,对以上规格化格式进行总结可以得出:符号位与尾数最高位不一致才算是规格化,一致为非规格化。如1.0XXX,0.1XXX(最前面的为符号位)之类的尾数都是规格化的数,而1.1XXX,0.0XXX为非规格化的数,另外,如果尾数大余1,也是非规格化数。
    对于非规格化的尾数需要进行相应的处理,处理方式又分为"左规"和"右规",所谓"左规"就是尾数需要向左移位,每移1位阶码值减1,直到为规格化数为止,对应"右规"就是尾数要向右移位,每移1位阶码值减1,直到为规格化数为止。
    采用"左规"还是"右规"的基本原则如下:
    运算结果产生移益出(由于原来两尾数的最高有效位相加有进位或者相减有借位时形成的)时,必须进行"右规",如双符号位的运算结果为10.XXX或01.XXX格式就是不符合规格化要求了,因为双符号位时符号位为"10"和"01"都是不正确的,右规时,最高有效位前补相应数量的0,此时,10.XXX格式右规后的格式为11.0XXX,而01.XXX格式右规后的格式为00.1XXX。
    如果运算结果出现0.1XXX或者1.1XXX(即符号位与尾数最高有效位相同时),必须进行左规,左规时最低有效位后补相应位数的0。
    在上面的例子中,X与Y的尾数之和是11011111,又因为它是正数,所以可以表示成0.11011111,已经是规格化,不用再处理了。
    如果X与Y相减,得出的尾数之差为负数,如1.1101111,这时就要进行规格化处理了,因为符号位1与尾数最高位1相同,这时需要进行左规,即向左移位,11011111要向左移两位才能使尾数的最高位与符号位不一致,移位后的尾数为01111100(最后两个0是补上去的)同时阶码要从原值0100相应减2,得到0010。

  • 4、舍入处理
    在"对阶"和向左,向右规格化处理时,尾数要向左,向右移位,这样结果尾数与原先的尾数就会有一定的误差,因此要进行舍入处理,以尽可能减小这种误差。
    以下提供两种减小误差的方法:
    “0舍1入法”:
    类似十进制中的四舍五入法,即如果左规或右规时丢弃的是0,则舍去不计,反之要将尾数的末尾加1。
    如上面举例的X和Y的尾数之和为:1.11011111(最高位为符号位),需要左规,得到1.01111100,由此可见左移时去掉的是前面的两位1,这种情况下就需要在尾数的最后一位加1,这样进行舍入处理的结果就是:1.01111101。
    ‘‘恒置1法’’:
    只要有数位被左规或者右规丢弃掉,就要在尾数的末尾恒置1,但是这个方法精确度不高,因为从概率上来讲,丢弃0和1的概率各占50%。
    IEEE 754还有许多更复杂的舍入模式,有兴趣可以自行了解。

  • 5、溢出处理

    如果采用双符号位补码形式,出现了"01"或者是"10"的形式就表示有溢出,但是,如果采用的是单符号位就不好判定了。这时需要根据对尾数进行规格化处理后的阶码是否超出了当前阶码所能表示的取值范围来判定了。
    上文已经提到了,右规后阶码需要加上对应的值,尾数每向右移一位就加1,最终可能导致阶码超出了当前类型的阶码所能表示的数值范围,这称为"上溢"。
    如(X+Y)补浮点数经过"对阶"和尾数相加后得到的尾数为10.101110011,显然它需要右规,结果为11.01110011,相当于尾数右移了一位,原来尾数的最高有效位"1"被丢弃了,同时阶码也需要相应加1,假设原先是用4位来保存阶码(算上阶码的符号位,所以,最大能表示的数是+7),原阶码为0111,尾数右移一位后,阶码+1就变为8了,而这个是大于+7的,所以这是就需要进行溢出处理了。
    同时,尾数进行左规的时候,也有溢出的情况,因为左规后可能超出了用于存储阶码的存储位所能表示的最小值(称为"下溢"),如左规后得到的新阶码为-5,假设原先的阶码是用4为来存储的,现在要求尾数再左移3位,这样阶码也要减小3,得到-8,而-8也超出了4位阶码所能表示的最小值-7(阶码的最高位为符号位)。如果发现有溢出,计算机会根据以下原则进行处理:
    如果是上溢,立即停止运算,做中断处理。
    如果是下溢,整个尾数按0处理。

PS:时间有限,有关Java SE的内容会持续更新!今天就先写这么多,如果有疑问或者有兴趣,可以加QQ:2649160693,并注明CSDN,我会就博文中有疑义的问题做出解答。同时希望博文中不正确的地方各位加以指正!

  • 71
    点赞
  • 222
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值