小数在内存中究竟是如何存储的(C语言代码详细讲解 4)

小数在内存中是如何存储的,揭秘诺贝尔奖级别的设计

IEEE 754 为什么增加非规格化浮点数

  我们以 float 类型为例来说明。

  对于规格化浮点数,当尾数 mant 的所有位都为 0、指数 exp 的最低位为 1 时,浮点数的绝对值最小(符号 sign 的取值不影响绝对值),为 1.0 × 2-126,也即 2-126。

  对于一般的计算,这个值已经很小了,非常接近 0 值了,但是对于科学计算,它或许还不够小,距离 0 值还不够近,非规格化浮点数就是来弥补这一缺点的:非规格化浮点数可以让最小值更小,更加接近 0 值。

  对于非规格化浮点数,当尾数的最低位为 1 时,浮点数的绝对值最小,为 2-23 × 2-126 = 2-149,这个值比 2-126 小了 23 个数量级,更加即接近 0 值。

让我更加惊讶的是,规格化浮点数能够很平滑地过度到非规格化浮点数,它们之间不存在“断层”,下表能够让读者看得更加直观。
在这里插入图片描述

^ 表示次方,例如 2^10 表示 2 的 10 次方。

  上表演示了正数时的情形,负数与此类似。请读者注意观察最大非规格化数和最小规格化数,它们是连在一起的,是平滑过渡的。

舍入模式

  浮点数的尾数部分 mant 所包含的二进制位有限,不可能表示太长的数字,如果尾数部分过长,在放入内存时就必须将多余的位丢掉,取一个近似值。究竟该如何来取这个近似值,IEEE 754 列出了四种不同的舍入模式。
1) 舍入到最接近的值
  就是将结果舍入为最接近且可以表示的值,这是默认的舍入模式。最近舍入模式和我们平时所见的“四舍五入”非常类似,但有一个细节不同。

  对于最近舍入模式,IEEE 754 规定,当有两个最接近的可表示的值时首选“偶数”值;而对于四舍五入模式,当有两个最接近的可表示的值时要选较大的值。以十进制为例,就是对.5的舍入上采用偶数的方式,请看下面的例子。

最近舍入模式:Round(0.5) = 0、Round(1.5) = 2、Round(2.5) = 2
四舍五入模式:Round(0.5) = 1、Round(1.5) = 2、Round(2.5) = 3
2) 向 +∞ 方向舍入(向上舍入)
  会将结果朝正无穷大的方向舍入。标准库函数 ceil() 使用的就是这种舍入模式,例如,ceil(1.324) = 2,Ceil(-1.324) = -1。
3) 向 -∞ 方向舍入(向下舍入)
会将结果朝负无穷大的方向舍入。标准库函数 floor() 使用的就是这种舍入模式,例如,floor(1.324) = 1,floor(-1.324) = -2。
4) 向 0 舍入(直接截断)
会将结果朝接近 0 的方向舍入,也就是将多余的位数直接丢掉。C语言中的类型转换使用的就是这种舍入模式,例如,(int)1.324 = 1,(int) -1.324 = -1。

总结

  与定点数相比,浮点数在精度方面损失不小,但是在取值范围方面增大很多。牺牲精度,换来取值范围,这就是浮点数的整体思想。

  IEEE 754 标准其实还规定了浮点数的加减乘除运算,不过本文的重点是讲解浮点数的存储,所以对于浮点数的运算不再展开讨论。

猜你喜欢

转载自blog.csdn.net/qq_43515862/article/details/108799206