详解 浮点数的规格化表示

《深入理解计算机系统》(兰德尔 E. 布莱恩特)中对浮点数的描述不容易懂,在这里记录一下,以加深理解。

1、IEEE浮点表示

IEEE(读作“eye-triple-ee”)浮点标准754中,用图1的形式来表示一个数:

图1 浮点数表示形式​​​

符号(sign)——s决定这个数是负数(s=1)还是正数(s=0),而对于数值0的符号位解释,作为特殊情况处理;

尾数(significand)——M决定浮点数的精度,它是一个二进制小数;

阶码(exponent)——E的作用是对浮点数加权,这个权重是2的E次幂(可能是负数),它决定浮点数的取值范围。

对于双精度double,组成形式是:1位符号,11位阶码,52位尾数 

对于单精度float,组成形式是:1位符号,8位阶码,23位尾数

2、浮点数值的分类 

根据阶码,浮点数可以分成三种情况:规格化的,非规格化的或特殊值 

 情况1:规格化的值

 当阶码的所有bits,既不全为0,也不全为1时,都属于这种情况。

此时,阶码字段被解释为"以偏置(Bias)形式表示的有符号整数" 。也就是说,阶码所表示的实际数值应是 

{\color{Green} E = e - Bias} 

其中 e 位的阶码所表示的无符号数值,其位表示形式为:" {\color{Green} e_{k-1}e_{k-2}\cdot \cdot \cdot e_{1}e_{0}} "。 

而Bias是一个等于 {\color{Green} 2^{k-1}-1} 的偏置值,例如单精度float的偏置是127。由此产生指数的取值范围,对于单精度float是 -126~127 (针对阶码数值为-127或128时的分析,请参考情况2和情况3)

 

而尾数字段,则被定义为

{\color{Green} M = 1 + f}

其中,位的尾数所表示的小数值,满足 \small {\color{Green} 0\leq f< 1},其二进制表示为:" \small {\color{Green} 0.f_{n-1}f_{n-2}\cdot \cdot \cdot f_{1}f_{0}} ",也就是二进制小数点在最高有效位的左边。

有时,这种方式也叫做隐含的以1开头的表示 ,因为我们可以把尾数 看成是一个二进制表达式为:" \small {\color{Green} 1.f_{n-1}f_{n-2}\cdot \cdot \cdot f_{1}f_{0}} " 的数字。

为什么要用这种表示方式,既然我们总能够调整阶码 E ,使得尾数 M 在范围 \small {\color{Green} 1\leq M< 2} 之中,那么这种表示方法是一种轻松获得一个额外精度位的技巧——既然第一位总是等于1,那我们就不需要显式地表示它。

由此,规格化形式可以表示的数值 的范围是 \small {\color{Green} \infty > \begin{vmatrix} V \end{vmatrix}> 0} 。

 

情况2:非规格化的值

 当阶码的所有bits全为0时,所表示的数是非规格化形式。(针对单精度float,阶码值为-127)

在这种情况下,阶码的数值是 {\color{Green} E = 1 - Bias} 。而尾数的值是 {\color{Green} M = f} ,也就是尾数字段的值,开头没有隐含的1。

——那么,为什么非规格化形式为什么将阶码值定义为 \small {\color{Green} 1 - Bias},而不是 \small {\color{Green} -Bias} ?

——因为只有这样,才能从非规格化值平滑转换到规格化值。对此,本文章最后以数字示例做了详细解释。

 非规格化形式提供了两种数值0的表示以单精度float为例,分别是:

+0:0    0000 0000    000 0000 0000 0000 0000 0000;

-0: 1    0000 0000    000 0000 0000 0000 0000 0000。

由此,非规格化形式可以表示的数值 V 的范围是分段函数 \small {\color{Green} \left\{\begin{matrix} 1> V\geq +0,& s=0\\ -1< V\leq -0,&\; \; s=1 \end{matrix}\right.} ,其中,s 为符号位。

 

情况3:特殊值

 当阶码的所有bits全为1时,所表示的数是特殊值。(针对单精度float,阶码值为128)

(1)无穷

尾数为0时,该值表示无穷。当两个非常大的数相乘时,或除数为0时,无穷能够表示溢出的结果。

+∞ :0    1111 1111    000 0000 0000 0000 0000 0000

-∞  :1    1111 1111    000 0000 0000 0000 0000 0000

(2)NaN

尾数不为0时,结果值被称为“NaN (Not a Number)”,一些运算的结果不为实数或无穷时,就会返回这样的 NaN 值,比如计算 \small {\color{Green} \sqrt{-1}} 或 \small {\color{Green} \infty -\infty } 时。

NaN  :x    1111 1111    xxx xxxx xxxx xxxx xxxx xxxx

Linux中对特殊值的应用

math.h中定义了宏INFINITE,表示“无穷大” 超出浮点数的表示范围(溢出),用%f打印这个宏,输出为inf

执行以下计算时,也会出现inf:1.0 / 0.0 = inf,-1.0 / 0.0 = -inf,0.0 + INFINITY = inf,log(0) = -inf。

而执行以下计算时,会出现nan:0.0 * INFINITYINFINITY / INFINITYINFINITY - INFINITY

// gcc编译时记得加 -lm 编译选项
#include <stdlib.h>
#include <math.h>
#include <float.h>

int main()
{
	printf("%f\n", (1.0 / 0.0));
	printf("%f\n", (-1.0 / 0.0));
	printf("%f\n", (0.0 + INFINITY));
	printf("%f\n", log(0));
	
	printf("%f\n", (0.0 * INFINITY));
	printf("%f\n", (INFINITY / INFINITY));
	printf("%f\n", sqrt(-1));

	return 0;
}

/* 输出:
inf
-inf
inf
-inf
nan
nan
-nan
*/

3、数字示例 

图2展示了假定的8位浮点格式的示例,其中有 k = 4 的阶码位和 n = 3 的小数位。于是可知偏置量 Bias 是 \small {\color{Green} 2^{4-1}-1=7} 。

图2 8位浮点格式的非负值示例

可以观察到,最大非规格化数 {\color{Green} \frac{7}{512}} 和最小规格化数 {\color{Green} \frac{8}{512}} 之间的平滑转变。这种平滑性归功于我们对非规格化数的阶码 E 的数值的定义。通过将非规格化数的阶码 E 定义为 1 - Bias,而不是 -Bias,我们可以补偿非规格化数的尾数没有隐含的1。

本文完。

  • 43
    点赞
  • 173
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值