浮点数的加减运算

🐶博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍🔥专栏系列:线性代数C初学者入门训练​​​​​​​

🔥座右铭:“不要等到什么都没有了,才下定决心去做”

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀 ​​​​​​​

在学习浮点数存储完后(浮点数数据的存储,如果大家对浮点数据还不太明白,可以点击,链接详细学习一下),我发现我仍然不会浮点数的加减运算,于是查阅多数资料,才完成此篇,其中借鉴大佬文章,然后又文章进行大量的修改整理。这样是大家阅读文章更加轻松

目录

🐰浮点数的加减运算

🌸对阶

🌸尾数运算

🌸结果规格化

🌸舍入处理

🌸溢出判断

          🌸事例

🐰浮点数的加减运算

浮点数的加减运算一般由以下五个步骤完成:对阶尾数运算规格化舍入处理溢出判断

🌸对阶

所谓对阶是指将两个进行运算的浮点数的阶码对齐的操作。对阶的目的是为使两个浮点数的尾数能够进行加减运算。因为,当进行M x·2Ex与My·2Ey加减运算时,只有使两浮点数的指数值部分相同,才能将相同的指数值作为公因数提出来,然后进行尾数的加减运算。对阶的具体方法是:首先求出两浮点数阶码的差,即⊿E=Ex-Ey,将小阶码加上⊿E,使之与大阶码相等,同时将小阶码对应的浮点数的尾数右移相应位数,以保证该浮点数的值不变。几点注意:

(1)对阶的原则是小阶对大阶,之所以这样做是因为若大阶对小阶,则尾数的数值部分的高位需移出,而小阶对大阶移出的是尾数的数值部分的低位,这样损失的精度更小。

(2)若⊿E=0,说明两浮点数的阶码已经相同,无需再做对阶操作了。

(3)采用补码表示的尾数右移时,符号位保持不变。

(4)由于尾数右移时是将最低位移出,会损失一定的精度,为减少误差,可先保留若干移出的位,供以后舍入处理用。

🌸尾数运算

尾数运算就是进行完成对阶后的尾数相加减。这里采用的就是我们前面讲过的纯小数的定点数加减运算。

🌸结果规格化

在机器中,为保证浮点数表示的唯一性,浮点数在机器中都是以规格化形式存储的。对于IEEE754标准的浮点数来说,就是尾数必须是1.M的形式。由于在进行上述两个定点小数的尾数相加减运算后,尾数有可能是非规格化形式,为此必须进行规格化操作。

规格化操作包括左规和右规两种情况。

左规操作:将尾数左移,同时阶码减值,直至尾数成为1.M的形式。例如,浮点数0.0011·25是非规格化的形式,需进行左规操作,将其尾数左移3位,同时阶码减3,就变成1.1100·22规格化形式了。

右规操作:将尾数右移1位,同时阶码增1,便成为规格化的形式了。要注意的是,右规操作只需将尾数右移一位即可,这种情况出现在尾数的最高位(小数点前一位)运算时出现了进位,使尾数成为10.xxxx或11.xxxx的形式。例如,10.0011·25右规一位后便成为1.00011·26的规格化形式了。

🌸舍入处理

浮点运算在对阶或右规时,尾数需要右移,被右移出去的位会被丢掉,从而造成运算结果精度的损失。为了减少这种精度损失,可以将一定位数的移出位先保留起来,称为保护位,在规格化后用于舍入处理。

IEEE754标准列出了四种可选的舍入处理方法:

(1)就近舍入(round to nearest)这是标准列出的默认舍入方式,其含义相当于我们日常所说的“四舍五入”。例如,对于32位单精度浮点数来说,若超出可保存的23位的多余位大于等于100…01,则多余位的值超过了最低可表示位值的一半,这种情况下,舍入的方法是在尾数的最低有效位上加1;若多余位小于等于011…11,则直

接舍去;若多余位为100…00,此时再判断尾数的最低有效位的值,若为0则直接舍去,若为1则再加1。

换而言之

多余数字是1001,它大于0.5,故最低位进1。
多余数字是0111,它小于0.5,则直接舍掉多余数字。
多余数字是1000,正好是等于0.5的特殊情况;那么此时最低位为0则舍掉多余位,最低位为1则进位1。

对于1.001...1001,舍入处理后为1.010(去掉多余位,加0.001)
对于1.001...0111,舍入处理后为1.001(去掉多余位)
对于-1.001...1000,舍入处理后为-1.010(去掉多余位,加0.001,因为此时最低位为1)
对于-1.010...1000,舍入处理后为-1.010(直接去掉多余位,因为此时最低位为0)

(2)朝+∞舍入(round toward +∞)对正数来说,只要多余位不为全0,则向尾数最低有效位进1;对负数来说,则是简单地舍去。

正数多余位不全为0进位1
对于1.001...1001,舍入处理后为1.010(去掉多余位,加0.001)
对于1.001...0111,舍入处理后为1.010(去掉多余位,加0.001)

正数多余位全为0直接截尾
对于1.001_0000,舍入处理后为1.001(直接去掉多余位)

负数直接截尾
对于-1.001...1010,舍入处理后为-1.001(直接去掉多余位)

(3)朝-∞舍入(round toward -∞)与朝+∞舍入方法正好相反,对正数来说,只是简单地舍去;对负数来说,只要多余位不为全0,则向尾数最低有效位进1。

正数直接截尾
对于1.001_1001,舍入处理后为1.001(直接去掉多余位)
对于1.001_0111,舍入处理后为1.001(直接去掉多余位)

负数多余位全为0直接截尾
对于-1.001_0000,舍入处理后为-1.001(直接去掉多余位)

负数多余位不全为0进位1
对于-1.001_1010,舍入处理后为-1.010(去掉多余位,加0.001)

(4)朝0舍入(round toward 0)

即简单地截断舍去,而不管多余位是什么值。这种方法实现简单,但容易形成累积误差,且舍入处理后的值总是向下偏差。​​​​​​​

正数
对于1.001...1001,舍入处理后为1.001(直接去掉多余位)
对于1.001...0111,舍入处理后为1.001(直接去掉多余位)

负数
对于-1.001...1000,舍入处理后为-1.001(直接去掉多余位)
对于-1.010...1000,舍入处理后为-1.010(直接去掉多余位)

🌸溢出判断

与定点数运算不同的是,浮点数的溢出是以其运算结果的阶码的值是否产生溢出来判断的。若阶码的值超过了阶码所能表示的最大正数,则为上溢,进一步,若此时浮点数为正数,则为正上溢,记为+∞,若浮点数为负数,则为负上溢,记为-∞;若阶码的值超过了阶码所能表示的最小负数,则为下溢,进一步,若此时浮点数为正数,则为正下溢,若浮点数为负数,则为负下溢。正下溢和负下溢都作为0处理。

要注意的是,浮点数的表示范围和补码表示的定点数的表示范围是有所不同的,定点数的表示范围是连续的,而浮点数的表示范围可能是不连续的。

🌸事例

float a=0.3;b=1.6;

a=(0.3)十进制=(0 01111101 00110011001100110011010)二进制   
计算机实际存储的:
Sa=0    Ea=01111101    Ma=0011001100110011001101023位)
我们所设计的(通过IEEE754转化得到实际存储):
Sa1=0    Ea1=-2    Ma=1.00110011001100110011010

b=(1.6)十进制=(0 01111111 10011001100110011001101)二进制  
计算机实际存储的:    
Sb=0    Eb=011111111     Mb=1001100110011001100110123位)
我们所设计的(通过IEEE754转化得到实际存储):
Sb1=0   Eb1=0     Mb1=1.10011001100110011001101

a+b=?

第一步:对阶

∵ Ea<Eb   Eb1-Ea1=2

∴ Ma1要调整为 0.01001100110011001100110       10(多余位)

   Ea=01111111

第二步:尾数运算

    0.010011001100110011001101.10011001100110011001101

    1.11100110011001100110011‬

第三步:规格化

1.11100110011001100110011‬已经是个规格化数据了

第四步:舍入处理
多余数字是10补齐就是1000,正好是等于0.5的特殊情况;那么此时最低位为0则舍掉多余位,最低位为1则进位1,这里最低为是1,所以进1
1.11100110011001100110100

第五步:溢出判断
没有溢出,阶码不调整,所以最后的结果为

a+b=(0  01111111  11100110011001100110100)二进制=(3FF33334)16

转为10进制
a+b=1.90000010(因为存在有些10进制小数不能被二进制小数完全表示,所以出现1.90000010,我们可以按找自己的精度需求,去取舍)
b-a=?

第一步:对阶

跟上面加法一样

第二步:尾数运算

   1.10011001100110011001101           

-  0.01001100110011001100110

   1.01001100110011001100111

第三步:规格化

1.01001100110011001100111已经是个规格化数据了

第四步:舍入处理

多余数字是10补齐就是1000,正好是等于0.5的特殊情况;那么此时最低位为0则舍掉多余位,最低位为1则进位1,这里最低为是1,所以进1
1.01001100110011001100110

第五步:溢出判断
没有溢出,阶码不调整,所以最后的结果为

a-b=(0  01111111  01001100110011001100110)二进制=(3FA66666)十六进制

转为10进制

a-b=1.29999995

 🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸  

  • 38
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 59
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值