阅读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都不用加上,因为编译器对不同的终端都做好工作。如果要了解浮点是如何进行运算如何加减乘除的,要了解更多编码知识。
在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都不用加上,因为编译器对不同的终端都做好工作。如果要了解浮点是如何进行运算如何加减乘除的,要了解更多编码知识。
相关文章推荐
- 关于UPnP Device Architecture 2.0的阅读笔记(九)
- 关于DSP中浮点与定点运算的C语言编程方法
- 关于《effectivity Java》阅读笔记 01
- (大卫的阅读笔记)关于对象的construct与destruct
- 关于byte类型的运算问题(适合新手阅读)
- RFC3581-关于rport字段 的阅读笔记
- 关于移动平台GPU浮点运算的文章转载1
- 关于剑指offer的阅读笔记
- 深入理解计算机系统笔记(一)关于位运算求整数平均值
- 笔记---浮点数运算的陷阱
- 关于sampling softmax 中重要性采样的论文阅读笔记
- 【Class 学习笔记】 浮点数的储存,运算
- C++面向对象程序设计(谭浩强)阅读笔记3——关于运算符的重载
- cocos2d-x系列笔记技巧篇—关于CREATE_FUNC宏的用法 分类: cocos2d代码编写 2015-07-29 08:50 7人阅读 评论(0) 收藏
- 关于四则运算表达式生成和答案校验的笔记
- RFC3581-关于rport字段 的阅读笔记(二)
- SIGIR 2017&2016 关于深度学习和推荐的相关文章摘要阅读笔记
- 关于UPnP Device Architecture 2.0的阅读笔记(一)
- 关于UPnP Device Architecture 2.0的阅读笔记(四)
- 关于 AlphaGo 论文的阅读笔记