CSAPP:第2章 信息的表示和处理 2.4 浮点数

2.4 浮点数(表示与运算)
1.二进制小数
- 定点表示法
二进制小数点向左移动一位相当于这个数被 2 除;类似,二进制小数点向右移动一位相当于将该数乘 2。
我们仅考虑有限长度的编码,那么十进制表示法不能准确地表达像1/3这样的数;类似的,小数的二进制表示法只能表示那些能够被写成x * 2^y的数,其他值只能够被近似的地表示。
2.IEEE浮点表示
- 基本表示方法
IEEE浮点标准用V=(-1)^s M 2^E的形式来表示一个数:符号s,尾数M,阶码E。
将二进制浮点数的位表示划分为三个字段,分别对这些值进行编码:一个单独的符号位 s 直接编码符号s;k 位的阶码字段 exp 编码阶码 E;n 位小数字段 frac 编码尾数 M,但是编码出来的值也依赖于阶码字段的值是否等于0。
- 单精度与双精度
在单精度浮点格式(float)中,s、exp、frac字段分别为1位,8位,23位;在双精度浮点格式(double)中,s、exp、frac字段分别为1位,11位,52位。单精度浮点格式为32位,双精度浮点格式为64位。
- 分类
给定位表示,根据exp的值, 被编码的值可以分成三种不同的情况(最后一种情况有两个变种),下面是单精度格式的情况。

规格化的值
exp的位既不全为0,也不全为1。
偏置值:
Bias。这是一个固定的偏移量,取决于浮点数格式。- 单精度(32位):指数字段占 8位,能表示
0到255共256个数。Bias = 2^(8-1) - 1 = 127。 - 双精度(64位):指数字段占 11位,
Bias = 2^(11-1) - 1 = 1023。
对于规格化数:阶码
e的取值范围是:1 到 254。代入公式E = e - Bias:- 当
e = 1(最小值):E_min = 1 - 127 = -126 - 当
e = 254(最大值):E_max = 254 - 127 = 127
所以,规格化数的真实指数范围是:-126 ≤ E ≤ 127
- 编码(存储时):
e = E + Bias(将真实指数E“偏置”为正数e) - 解码(计算时):
E = e - Bias(将存储的阶码e“去偏置”得到真实指数E)
小数字段 frac 被解释为描述小数值 f, 其中 0<=f<1,二进制小数点在最高有效位左边,尾数定义为 M = 1 + f。(隐含的以1开头的表示)
我们总是能够调整阶码 E,使得尾数 M 在范围 1<=M<2 之中,我们第一位总是等于1,那么我们只需表示它的小数部分。
- 单精度(32位):指数字段占 8位,能表示
非规格化的值
当阶码域全为0时,所表示的数是非规格化形式。
阶码值是E=1-Bias(而不是0-Bias),尾数M=f(而不是1+f)。
两个用意:
- 表示0。若使用规格化数,必须总是使M>=1,无法表示0;使用非规格化数,s=M=f=0时,得到+0.0,s=1且M=f=0时,得到-0.0。
- 表示非常接近于 0.0 的数。它们提供了一种属性,称为逐渐溢出(gradual underflow),其中,可能的数值分布均匀地接近于 0.0。
特殊值
阶码全为1时,表示特殊值。
- 小数域全为0时,表示无穷:s=0表示+∞,s=1表示-∞。当把两个非常大的数相乘或者除以0时,无穷能够表示溢出的结果。
- 小数域为非0时,表示NaN:例如计算根号-1等,或者表示未初始化数据。
3.数字示例

可以观察到,那些可表示的数并不是均匀分布的——越靠近原点处它们越稠密。


4.舍入
- 向零舍入:把正数向下舍入,负数向0舍入,得到|x^|<=|x|。
- 向下舍入:把正数和负数都向下舍入,得到x-<=x。
- 向上舍入:把正数和负数都向上舍入,得到x+>=x。
向偶数舍入:向偶数舍入在大多数现实情况中避免了统一向一个方向舍入带来的统计偏差,在 50% 的时间里,它将向上舍入,而在 50% 的时间里,它将向下舍入。
假设我们有4位精度(1位符号,3位尾数),要舍入:
要存储的二进制数:
1.1011(精确值)
可表示的最近值:1.110和1.101计算距离:
- 到
1.110=1.1011 - 1.101=0.0001 - 到
1.110=1.110 - 1.1011=0.0001 - 距离相等!是平局!
- 到
应用向偶数规则:
1.101的二进制最后一位是1(奇数)1.110的二进制最后一位是0(偶数)- 选择
1.110(因为它的最低位是偶数)
5.浮点运算
当参数中有一个是特殊值(如-0、-∞或 NaN)时, IEEE标准定义了一些使之更合理的规则。例如,定义 1/-0将产生-∞, 而定义 1/+0会产生+∞;+∞-∞=NaN);NaN+x=NaN。
整数(包括无符号和补码)加法形成了阿贝尔群。实数上的加法也形成了阿贝尔群,但是我们必须考虑舍入对这些属性的影响。
浮点加法不具有结合性,这是缺少的最重要的群属性。另外,浮点乘法在加法上不具备分配性。
eg. 单精度浮点情况下,表达式(1e20*1e20)*1e-20求值为+∞,而1e20*(1e20*1e-20)将得出1e20。
6.C语言中的浮点数
因为C语言标准不要求机器使用 IEEE浮点,所以没有标准的方法来改变舍入方式或者得到诸如-0、+∞、-∞或者 NaN之类的特殊值。
强制类型转换:
从 int 转换成 float, 数字不会溢出,但是可能被舍入。
从 double 转换成 float,因为范围要小一些,所以值可能溢出成+∞或-∞。另 外,由于精确度较小,它还可能被舍入。
float 或者 double 转换成 int,值将会向零舍入。例如,1.999将被转换成 1,而 -1.999 将被转换成 -1。进一步来说,值可能会溢出。
整数不确定值:
与 Intel 兼容的微处理器指定位模式
[10…00](字长为 w 时的 TMinw) 为整数不确定(integer indefinite)值。一个从浮点数到整数的转换,如果不能为该浮点数找到一个合理的整数近似值,就会产生这样一个值。因此,表达式 (int)+1e10 会得到-21483648, 即从一个正值变成了一个负值。
2.5 小结(与习题)
- 64 位程序的优势是可以突破 32 位程序具有的 4GB 地址限制。
本文系作者 @xiin 原创发布在To Future$站点。未经许可,禁止转载。
暂无评论数据