少女祈祷中...

浮点数运算

浮点数加减法

步骤:

  • 检查0:运算双方是否有一方等于0?
  • 对齐有效值:阶码向大阶对齐,也就是需要将阶码小的那个数的阶码增加m位,直到与阶码大的数的阶码相同。每次阶码+1就要把尾数右移1位。
  • 加或减有效值:进行尾数的运算。需要带上原来的隐藏位
  • 规格化结果:最后得出的结果需要转变为规格化数的形式。如果小于1就要左归(尾数左移,阶码减少);大于等于2就要右规(尾数右移,阶码增加)

乘法和除法

计算步骤:

  • 检查0:运算双方是否有0存在?需要针对不同情况进行不同处理
  • 阶码相加减:两个数的乘除就相当于对阶码相加减。注意:使用移码进行阶码的加减时需要额外加减一次偏置常数,如果是乘法,最后需要减去偏置常数127;如果是除法则加上127。
  • 尾数相乘除:把尾数看出整数,执行整数的乘除,结果也用整数表示
  • 规格化结果:和加减法一样,将结果表示为规格化数的形式。

溢出

阶码操作过程中可能会发生溢出:

  • 上溢:超过11111110(127)
  • 下溢:小于00000001(-126)

有效值可能也会发生溢出:

  • 上溢:两个数相加可能导致最高位的进位。一般可以右移重新对其
  • 下溢:最右端数字在对其过程中被移出,此时需要某种形式的四舍五入(右规)操作

IEEE754中的五种异常

  • 无效运算:结果为NaN,一般为负无穷加正无穷、0/0等等
  • 有限值除以0:正负无穷大

加法

减法示例:

首先确定两个阶码的差值,为1,所以需要对-0.4375的尾数右移,变为了0 1110…0,注意前面的隐藏位变为了0.

然后就对阶码进行相加(负负得正,变为了加法),得到最后的结果。省去一个隐藏位,就得到了结果。

示例2:

这里加一个负数。还是先确定阶码的差值,为1,把-0.4375的尾数右移1位。由于它是一个负数,执行尾数相加的时候需要加尾数的相反数(所有的位取反+1).

乘法

阶码相加,尾数相乘。在尾数相乘的时候都要带上隐藏位。然后乘完以后还需要根据乘积的高两位做出不同的处理。如果高两位为01则无需处理;为10或11就右规一位(不处理00是因为IEEE 754标准中,只有右规)

符号位就是两个符号位的异或,尾数高两位判断时01因此不需要操作,直接取高两位之后的23为写入尾数中,舍去乘积最后的23个0

除法

与乘法相似,先判断除数和被除数的特殊值,然后阶码相减,尾数相除,对最后结果的高两位判断,如果为01则左归一位,为10或11则无需处理

示例:

精度考虑

舍入位

为了确保结果的精确度,需要在中间结果的尾数中都使用附加位。

  • 保护位:在尾数右边的位,左归时被移到尾数中
  • 舍入位:在保护位右边的位,作为舍入的依据

舍入:

  • 就近舍入(默认方式):结果被舍入成最近的可表示的数(非中间值:0舍1入;中间值:强制结果为偶数)
  • 朝+∞舍入:结果果朝正无穷大方向向上舍入
  • 朝-∞舍入:结果果朝负无穷大方向向上舍入
  • 朝 0 舍入:结果朝 0 舍入,

数据类型:

  • int:整数,范围为-2147483648到2147483647
  • float:单精度浮点数,1+8+23
  • double:双精度浮点数,1+11+52

其中,int变成float、float变成int都会失去精度,而double可以完整的表示所有的int和float值。

牢记IEEE754不完美

  • 尽量简化运算步骤
  • 低精度和一个高精度在运算时,低精度的数变成了高精度(补0)
  • 运算后注意舍入
  • 运算时,警惕二进制不能精确表示的数
  • 运算时,警惕2k2^k