您的位置:首页 > 移动开发

阅读IEEE754关于浮点运算笔记

2014-04-03 19:51 627 查看
最近重新看了一篇《深入理解计算机系统》,果然好书读多少次都能得到新的知识。关于浮点运算IEEE754上次读过还只是蜻蜓点水,完全没有深入理解,这次结合P.J.Plauger写的《C标准库》对该标准在计算机中是如何实现的有了更深入的了解。下面我记录下我最近阅读内容及个人的思考理解。

在CSAPP中对IEEE754的描述是:浮点标准用

的形式表示一个数:

符号 s=1这个数为负s=0则为正;

尾数 M是一个二进制小数,它值域是1~2-epsilon(小的数)或是0~1-epsilon;

阶码 E是对浮点数加权;

下面是通常的单精度float和双精度double存储格式,单精度是4个字节,双精度是8个字节



现在对单精度编码进行讲解,理解了单精度,对于双精度只是字段长度的改变而已。

对上图单精度的s,exp和frac字段分别是1位,k=8位和n=23位。

根据exp的值,浮点精可以被编码三种不同的情况,分别是:

1.规格化 exp≠0和≠255 即exp字段不是全为0也不是全为1;

2.非规格化 exp=0 exp字段全为0;

3a.无穷大 exp=255并且frac=0

3b.NaN(不是一个数)exp=255并且frac≠0

对规格化:阶码E=e-Bias,e为exp字段无符号数的值,Bias=2^(k-1)-1=2^(8-1)-1=127,尾数M=1+f,f是frac字段的二进制小数,所以


;

对非规格化:阶码E=1-Bias=-126(这有点违反直觉,正常觉得应该是-Bias,设计者这样设定是为了非规格化平滑过渡到规格化,因为规格化最小值是2^-126),尾数M=f,所以

;

以上就是IEEE754浮点数编码的格式,然而如果你打开一般的C编译器的头文件float.h,会发现实现标准库设计者写的代码跟上面的编码有点出入,但如果你再仔细看其实又没什么问题。

在float.h中会看见很多宏定义例如FLT_*,DBL_*,LDBL_*。这里FLT表示单精度float,DBL表示双精度double,LDBL为long double。

我就对FLT_的宏进行说明。

FLT_ROUNDS 表示浮点加法舍入模式由它的值确定(-1表示不能确定 0表示向0舍入 1表示最近舍入 2表示向正无穷舍入 3表示向负无穷舍入)

FLT_RADIX表示指数表示的基数 其值为2

FLT_MANT_DIG表示FLT_RADIX进制的浮点数有效位数p 这里规格化浮点数它有23个小数位1个整数位一共24位,所以其值为24

FLT_DIG表示10进制的精确位数 log10(2^23)=6 单精度其10进制精确是6~7位6是完全精确的





你可以改变浮点数看输出,其位数精确6~7位。

FLT_MIN_EXP表示二进制最小指数值等于-125 在上的浮点编码我们应该知道阶码应该是-126~127而这里最小值怎么是-125,因为库的设计者是将尾数都化为小数部分,所以阶码相应加了1

FLT_MIN_10_EXP表示10进制最小指数值为-37 log10(2^-125)=-37

FLT_MAX_EXP表示二进制最大指数值等于127+1=128

FLT_MAX_10_EXP表示10进制最大指数值log10((1-2^-24)x2^128)=38

FLT_EPSILON表示1和给定浮点类型比1大的最小值之差=2^-23=1.19209290e-07f

其它一些宏定义就是最大最小之类,通过了理解了编码可以计算下与之对照

对于浮点运算,可能我们在编程的时候连float.h都不用加上,因为编译器对不同的终端都做好工作。如果要了解浮点是如何进行运算如何加减乘除的,要了解更多编码知识。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息