深入浅出IEEE浮点数表示法
使用二进制定点表示浮点数十分麻烦,且由于有些浮点数的二进制不能精确表示,只能添加小数位数不断近似,使得位数开销极大。20世纪70年代已经有一些计算机厂家推出了自己的浮点数表示标准,但并不统一,于是在1985年IEEE 742标准被提出,作为目前国际浮点数的表示标准。
IEEE 742标准规定了一个浮点数表示公式:V = (-1)^s * M * 2^E
怎么理解这个公式?
其实这里有一个知识点:浮点数是用科学计数法来表示的。
比如十进制数25.125
25.125_{(D)} = 11001.001_{B} = 1.1001001 * 2^4
你也可以把它表示成0.11001001 * 2^5,11.001001 * 2^3, 110.01001 * 2^2,11100100.1 * 2^{-3}等等,实际上浮点数的得名也是源自于它的点位漂浮不定的情况,在实际应用中我们采用IEEE 标准,用科学计数法统一表示这些浮点数。
回头看公式,其中V(Value)表示浮点数的十进制值;
S(Sign)符号位表示浮点数的正符号,取1为负,0为正;上例显然是正数, S = 0。
注意,面对这个符号位要摆脱之前整数补码取反加1求负的思想,实际上求浮点数的负值只要偏转一个符号位就行了。
M(Mantissa)表示尾数,表示 二进制浮点数 科学计数法表示形式 下的小数部分; 上例中M = 1.1001001
E (Exponent) 表示阶码,是一个有符号数,表示 二进制浮点数 科学计数法表示形式 的2次幂的值,上例中 E = 4
怎么把数装进计算机的二进制位?
IEEE 提供了浮点数的32位和64位表示形式:
![]()
这里除了符号位外又看到两个变量exp 和 frac 。
这两个参数的作用是什么?这里又要开始讲IEEE标准,制定IEEE标准的这帮人根据exp的值分了三类情况:规格化,非规格化,特殊值情况,我们先主讲规格化的情况。
规格化
即exp的位模式既不全为0也不全为1的情况,该情况下IEEE二进制数对应到科学计数法表示要通过如下公式:
E = exp - bias
M = 1 + frac
exp是exponent,即指数,注意别和阶码E混淆,exp是一个无符号整数,而E是有符号整数;
frac是fraction, 即M去掉整数部分后的小数字段, 注意规格化表示下尾数的第一位一定是1,正如科学计数法下非0数表示的第一位一定非0的情况。
其中bias 是一个偏置值,和之前2.3用于保证整数向0舍入的bias不一样,这个bias是用于浮点数计算时能对齐两数的阶码使用的。这一部分我并不是了解的很清楚,目前要记住E是一个移码,参考:
bias 的取值是 bias = 2^{n-1} - 1 ,其中 n 是exp的数据位数,单精度下bias 值为
127(n = 8), 双精度下为1023(n = 11)。单精度情况下,阶码E的有符号表示范围为
-127 ~ +128,但是-127 和 128 在规格化里是没被用来表示的,原因是在IEEE标准中这两个数分别被用来规定了非规格化和特殊值的情况,也即单精度的规格化阶码exp范围是 00000001(-126)-11111110(127) , 之后讨论。注意,看exp不能按正常的二进制转十进制的思维转成十进制,需要减去偏差。
单精度情况exp和E对照:
exp(B) exp(D) E 0000 0000 (非规格化) 0 -126(非规格化情况E = 1 - bias) 0000 0001 1 -126 … 1111 1110 254 127 1111 1111 (特殊值) 255 -- 规格化情况的公式变为:
V = \begin{cases} (-1)^s * (1 + frac)*2^{exp - 127},float\\\ (-1)^s * (1 + frac)*2^{exp - 1023},double\end{cases}
按照规格表示,我们得到了25.125D(即1.1001001 * 2^4)的单精度表示方法:
1_{(s,1位)} 10000011_{(exp,8位)} 10010010000000000000000_{(fra,23位)}
注意,在实际的位表示中开头1被省略掉了(即implied leading 1, 隐含的1开头表示),用以获得一个额外的尾数位以提高精度。
非规格化
阶码域全为0时,表示的值就是非规格化的,非规格数可以用来表示0及其他一些非常小的数,注意+0.0和-0.0在浮点数中是同时存在的,仅有符号位的不同。非规格化中M和E的公式定义为:
M = frac
E = 1- bias
非规格化的尾数是0开头的,故M代表的就是小数部分,至于E 为什么等于 1-bias会比较费解,其实这里的1是对非规格化数没有隐含的1的补偿,其有益于最大非规格化数到最小规格化数的平滑转变。
另外,值比较小的规格化的数在更低位数的机器中可能成为非规格化数。我们知道,增大尾数位有益于提高浮点数的表示精度从而得到更大的规格化值,而增大指数为有益于提高浮点数的表示范围得到更小更精确的规格化值,我们可以试想下列情况:
设阶码位为k, 尾数位为n,偏置量bias
32位环境下的某小数0.001953的二进制表示形式为:
0_{(s,1位)}01110101_{(exp,8位)} 11111111111101111001110_{(fra,32位)}
其计数表示为1.1111111111110111100111 * 2^{-10}
放到k = 4,n = 3,bias = 7的机器环境中表示为:
0_{(s,1位)}0000_{(exp,4位)} 001_{(fra,3位)}
E = 1 - 7 = -6, M = 0.001 ,故0.001953在该环境下表示为0.001* 2^{-6}
(0.000000001_{B},显然是1/512的近似结果,具体看CSAPP图2-35参考),
若要让小数点到达1前,阶码值需要到-9,即规格化表示是1.0 * 2^{-9},可是该环境下的阶码E范围为 -6 ~ 7,显然超出了取值范围,E取最小值也无法满足开头是1的规格化条件,只能表示成非规格形式。
另外可见,如果表示的浮点数的计数表示超过了E的最大范围,就会导致溢出,值变为+\infty。比如上述环境中256.0的计数表示为 1.0* 2^8, 用4个指数位已经不够表示了(E = 14(1110) - 7 = 7 < 8(1111)),于是全1溢出。
特殊值
特殊值包括正无穷,负无穷和NaN(即不是一个数,Not a Number), 在阶码全为1的时候出现,其中当小数位全为0时,s=1表示负无穷,s=0表示正无穷,如果小数位不全为数就是NaN, 它们的用处是用于表示未初始化的数据,比较少见,这里不再详谈。
参考:
http://kaito-kidd.com/2018/08/08/computer-system-float-point/
南京大学 计算机系统基础(一)主讲:袁春风老师
深入浅出IEEE浮点数表示法的更多相关文章
- IEEE浮点数表示法之出小数
纯小数的表示方法------------------------------------------------- 下面再来讲如何将纯小数转化为十六进制.对于纯小数,比如0.0456,我们需要把 ...
- IEEE Floating Point Standard (IEEE754浮点数表示法标准)
浮点数与定点数表示法是我们在计算机中常用的表示方法 所以必须要弄懂原理,特别是在FPGA里面,由于FPGA不能像在MCU一样直接用乘除法. 定点数 首先说一下简单的定点数,定点数是克服整数表示法不能表 ...
- IEEE浮点数标准
IEEE浮点数标准 阅读笔记:Computer System : A Programmmer's Perspective 基本概念 IEEE浮点数标准采用 \[V=(-1)^s\times M\tim ...
- IEEE754浮点数表示法
IEEE二进制浮点数算术标准(ANSI/IEEE Std 754-1985)是一套规定如何用二进制表示浮点数的标准.就像"补码规则"建立了二进制位和正负数的一一对应关系一样,IEE ...
- IEEE浮点数float、double的存储结构
众所周知,C的float.VB的Single都是32位浮点数变量类型(也叫单精度浮点数),C的double和VB的Double则都是64位的浮点数变量类型(也叫双精度浮点数).有些编译器还支持更屌的l ...
- 浮点数在计算机中的表示(IEEE浮点数标准)
转载自:https://wdxtub.com/2016/04/16/thin-csapp-1/
- IEEE浮点数向偶数舍
CSAPP 向偶数舍入初看上去好像是个相当随意的目标--有什么理由偏向取偶数呢?为什么不始终把位于两个可表示的值中间的值都向上舍入呢?使用这种方法的一个问题就是很容易假想到这样的情景:这种方法舍入 ...
- C语言中float,double类型,在内存中的结构(存储方式)
C语言中float,double类型,在内存中的结构(存储方式)从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float是32位的,double是64位的,所以doubl ...
- PostgreSQL的基础数据类型分析记录-转
src:http://www.codeweblog.com/postgresql%E7%9A%84%E5%9F%BA%E7%A1%80%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E ...
- IEEE二进制浮点数算术标准(IEEE 754)
整理自IEEE 754 IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用.这个标准定义了表示浮点数的格式(包括负零-0) ...
随机推荐
- 古老的BAT文件在windows下的编辑
直接上代码 rem echo choice /t 20 /d y /n >nul rem start/d "E:\service\exe" 8091.exe 8091 sta ...
- C#多线程编程(二)线程池与TPL
一.直接使用线程的问题 每次都要创建Thread对象,并向操作系统申请创建一个线程,这是需要耗费CPU时间和内存资源的. 无法直接获取线程函数返回值 无法直接捕捉线程函数内发生的异常 使用线程池可以解 ...
- SearXNG私有化部署与Dify集成
一.概述 SearXNG 是一个免费的互联网元搜索引擎,它聚合了来自各种搜索服务和数据库的结果,但摆脱了隐私追踪 -- 用户行为既不会被引擎跟踪也不会被分析. 功能特性 自托管,可以私有化部署 没有用 ...
- 使用MCP C# SDK开发MCP Server + Client
大家好,我是Edison. 近日被MCP刷屏了,刚好看到张队发了一篇文章提到MCP的官方C# SDK发布了预览版,于是手痒痒尝了一下鲜,写了一个DEMO分享给大家. MCP是什么鬼? MCP,全称是& ...
- 团队项目:杰杰Bond团队成员介绍
项目 内容 这个作业属于哪个课程 2025年春季软件工程(罗杰.任健) 这个作业的要求在哪里 [T.1] 团队项目:团队成员介绍 我在这个课程的目标是 学习软件工程相关知识,培养编程和团队协作能力,做 ...
- 线性探测法的查找函数 作者 DS课程组 单位 浙江大学
虽然但是,我真的讨厌c语言这样一大坨typedef命名来命名去的,很多时候其实我们会写,但是看不懂这个存储结构 函数的接口定义 Position Find( HashTable H, ElementT ...
- 为什么不推荐在 MySQL 中直接存储图片、音频、视频等大容量内容?
在MySQL中直接存储图片.音频.视频等大容量内容(通常称为BLOB数据)通常不被推荐,主要原因包括以下几点: 1. 性能问题 存储效率:存储大容量文件(如图片.音频.视频等)会大幅增加数据库的存储负 ...
- 宽带带宽和网速的关系,为什么1m等于128kb
带宽单位是:b(比特/位) 网速单位/文件下载上传单位:B(字节) 所以,1Mbps = 1/8Mbps = 128kb/s
- layui动态渲染select表单、初始化默认值、change事件监听等
layui动态渲染,初始化默认值 var html = ''; html += '<select name="" lay-search lay-verify="re ...
- <HarmonyOS第一课01>HarmonyOS介绍
视频链接: https://developer.huawei.com/consumer/cn/training/course/slightMooc/C101717496599725471?ha_sou ...
