Table of Contents
CS:APP Page 75~87
背景:二进制的浮点数,分数 Link to 背景:二进制的浮点数,分数
在计算机中,用二进制的浮点数表示实数  即 例如 而
有些小数则不能有有限位数表示,例如 而在计算机中,存储位数是有限的.所以为了提高精度就需要减小整数部分的位数;为了增加整数部分的位数就需要降低精度.
二进制浮点数的科学计数法 Link to 二进制浮点数的科学计数法
- s是符号位(sign),决定了正负
- 尾数(significand)的范围是[1.0,2.0)
- 阶码E(exponent)会以2的E次幂扩大尾数
IEEE浮点数标准 Link to IEEE浮点数标准
精度 Link to 精度
两个IEEE标准:单精度和双精度: 
情况1:规格化的值 Link to 情况1:规格化的值
上图中, 当阶码不全为0也不全为1的时候exp ≠ 000…0 并且exp ≠ 111…1
- 阶码字段exp = E + bias
- 阶码是unsigned类型
- 偏移量bias = 2^{k-1} - 1,k是阶码位的位数:
- 对于单精度是127(exp:1
254,E:-126127) - 对于双精度是1023(exp:1
2046,E:-10221023)
- 对于单精度是127(exp:1
- 尾数的编码隐含了整数部分前导1:M=1.xxxx
- xxxx就是小数字段frac的比特
- M=1.0,小数字段是000…0;M=2-ε,小数字段是111…1
- 这种方法获得了一个额外精度
举例 Link to 举例
以浮点数15213.0为例
float F = 15213.0f;
过程
结果
0 10001100 11011011011010000000000 s exp frac
情况2:非规格化的值 Link to 情况2:非规格化的值
当阶码域exp全为0(exp = 000…0)时,所表示的数是非规格化形式
- 阶码的值E=1-Bias而不是-Bias
- 尾数的编码隐含了整数部分前导0:M=0.xxxx
- xxxx就是小数字段frac的比特
- exp = 000…0,frac = 000…0
- 表示0
- 对于+1和-1的符号位有+0.0和-0.0
- exp = 000…0,frac ≠ 000…0
- 表示非常接近于0的数
- 分布均匀地接近于0.0
情况3:特殊值 Link to 情况3:特殊值
当阶码域exp全为1(exp=111…1)的时候
frac=000…0
- 表示无穷∞(Infinity)
- 能够表示溢出的结果
- 当s=0时是+∞;当s=-1时是-∞
frac≠000…0
- 表示不是一个数(NaN)
- 能够表示运算结果不是实数或无穷,例如sqrt(-1),∞-∞,∞*0
在数轴上的分布 Link to 在数轴上的分布
 规格化的值不是均匀分布的;非规格化的值聚集在0附近,并且是均匀分布的.
数字示例:以8位浮点格式为例 Link to 数字示例:以8位浮点格式为例
s | exp | frac |
---|---|---|
1-bit | 4-bit | 3-bit |
偏移量 Bias = 2^ (4-1) = 7 | ||
 | ||
完整范围: | ||
![]() | ||
在-1.0~1.0附近: | ||
![]() |
浮点运算 Link to 浮点运算
舍入(Round) Link to 舍入(Round)
基本思想 Link to 基本思想
首先计算精确值,然后按需要的精度舍入
舍入方式 Link to 舍入方式
- 向0四舍五入
- 向下(-∞)四舍五入
- 向上(+∞)四舍五入
- 四舍五入偶成双 这是默认方式.即大于中间数(在十进制下是5,在二进制下是1)的向上入,小于中间数的向下舍,等于中间数的向偶数舍入. 对于十进制: 对于二进制也类似:
加法(addtion) Link to 加法(addtion)
假设E1>E2 精确结果为 其中:
- 符号s由对齐后的符号决定.
- 尾数M对齐后相加的结果
- 指数E是E1
调整:
- 如果M>=2,右移M,然后E增加1
- 如果M<1,左移k位,E减小k
- 如果E溢出,溢出为无穷
- 舍入M使得符合frac位精度要求
对齐那样的处理方法导致了一个特性,就是不符合加法结合律: (3.14+1e10)-1e10 = 0, 3.14+(1e10-1e10) = 3.14
符合加法交换律
乘法(multiplication) Link to 乘法(multiplication)
精确结果为 其中:
- 符号位s: s1^ s2
- 尾数M:M1×M2
- 指数E:E1+E2 调整:
- 如果M>=2,右移M,然后E增加1
- 如果E溢出,溢出为无穷
- 舍入M使得符合frac位精度要求 类似于浮点数加法的特性,浮点数乘法可能不符合乘法结合律和乘法分配律
(1e20*1e20)*1e-20 = inf, 1e20*(1e20*1e-20) = 1e20
1e20*(1e20-1e20) = 0.0, 1e20*1e20-1e20*1e20 = NaN
不过,在大多数情况下,只要差距不是这么悬殊,不对inf和NaN实数运算,数学规律都是适用的. 可以保证对于
C语言中的浮点数 Link to C语言中的浮点数
C语言提供了两种不同的浮点数:单精度float和双精度double 在int,float,double类型之间进行强制类型转换时.原则如下: 与signed和unsigned类型相互转换不会改变比特位不同的是,这里比特会发生实质性的改变
double/float -> int
- 直接截去小数部分
- 向0舍入
- 超过int范围或转换NaN时是未定义行为:通常置为TMin
int/float -> double 因为double有更大的范围,也有更大的精度,所以能够保证是精确值
int -> float 数字不会溢出,但是可能被舍入
double ->float
- 因为float范围更小,所以可能溢出为+∞或-∞;因为精度更小,所以可能被舍入
浮点数的范围 Link to 浮点数的范围
补充一下浮点数能够表示的范围
- 单精度浮点数
格式 | 最小值 | 最大值 |
---|---|---|
规格化 | ||
非规格化 |
- 双精度浮点数
格式 | 最小值 | 最大值 |
---|---|---|
规格化 | ||
非规格化 |