IEEE 754浮点数表示标准
二进制数的科学计数法
C++中使用的浮点数包括采用的是IEEE标准下的浮点数表示方法。我们知道在数学中可以将任何十进制的数写成以10为底的科学计数法的形式,如下

其中
显而易见,因为如果a比10大或者比1小都能够再次写成10的指数的形式,如

然而要想在二进制的世界中将数字写成以10为底的科学计数法的形式,着实有点麻烦,因为你首先需要将二进制的数先化成10进制的表示方法,然后才能写成科学计数法的形式。但是如果我们稍微变通一下科学计数法的标记方法,问题就变得特别的简单了。之所以数学上使用的科学计数法选用10为底,是因为我们通常使用的计数方式是十进制的。在计算机的世界中我们使用的数却是二进制的,所以我们在这个世界中应该改用以2为底的科学计数法而不是10为底的科学计数法。此时我们使用的科学计数法就表示成了如下形式,

对于一个二进制的数来说
是不言而喻的,以
为例

IEEE 754标准下的存储策略
IEEE标准下的浮点数存储包括三个基本的组成:符号位、指数、尾数(the sign, the exponent, the mantissa),尾数是由小数部分和一个隐含的前导数位组成。至于前导数位隐含的原因很简单(下面将会解释)。
下面的表格展示了计算机存储单精度和双精度浮点数的层次结构,包括每一部分的比特位(比特范围用方括号括出,00表示最低位)
| Sign | Exponent | Fraction | |
| Single Precision | 1 [31] | 8 [30-23] | 23 [22-00] |
| Double Precision | 1 [63] | 11 [62-52] | 52 [51-00] |
- 符号位
符号位非常简单,位于存储浮点数的最高比特位,且只占1比特。0表示正数,1表示负数。通过改变该比特位的值可以改变该浮点数的符号。
- 指数位
因为指数位既需要能够表示正指数也需要能够表示负指数,为了能够做到这一点,需要将真实的指数数值加上一个偏移值获得用来存储的指数值。对于IEEE标准下的单精度浮点数,这个偏移值是127。因此当真实的指数为0的时候,我们存储的指数位为127。如果存储的指数值是200,那么真实的指数值就应该是(200-127),即73。后面的原因会指出,指数为-127(指数位全为0)和+128(指数位全为1)会被用来存储特殊的数值。
对于双精度的浮点数,指数位的长度位11比特,偏移量位1023。
- 尾数
尾数也被称为有效数位(significand),决定浮点数的精确度。它由隐含的前导数位(小数点左边的部分)和小数部分(小数点右边的部分)组成,因为我们采用以2为底的科学计数法表示二进制数,那么小数点左边的尾数部分自然是固定值1(
),所以前导数位我们不需要明确的表示出来,我们只需要存储尾数的小数部分就可以了。
浮点数存储示例
下面就以单精度浮点数来浮点数的存储策略。
十进制数0.1562510 写成二进制的形式为0.001012。通过乘以以2为底的指数,将小数点向右移动3位后得到

这个时候我们就能够确定它的尾数的小数部分和指数分别是多少了,尾数的小数部分位.012,指数为-3。具体存储方法见下图,

在IEEE 745标准下,我们用三部分来表示一个浮点数:
- sign = 0, 因为该浮点数为正数(用1表示负数);
- 真实的指数是-3,但是我们用来存储的指数要在真实的指数上加上偏移量。在单精度浮点数中,这个偏移量是127,在双精度浮点数中这个偏移量是1023;所以我们这里用来存储的指数应该为(-3+127),即124。
浮点数的范围
我们先来考虑单精度浮点数的范围问题。注意到我们用来存储双精度浮点数的是一块长为32bits的内存,我们重新解释了一下该快内存中数字的存储规则使得表示数的范围大大增加。但是我们看看这样子带来了什么问题?
对于32bits的无符号整数来说,它可以表示0~232-1范围内的任意整数。但是单精度的浮点数却做不到这一点,因为浮点数的存储策略中用来存储尾数的长度只有24bits,这个时候单精度浮点数就会把将底位的部分截断,例如
// 32-bit integer
= +1.1110000 x 2^31 // Single-Precision Float
= // Corresponding Value
这样的方法可以近似32bits的值,但是并不能得到准确的结果。忽略精确度的问题,浮点数能够表示的范围是2127,而32bits整数的表示范围是232。
特殊值
- 零
按照上面的浮点数表示方法,我们发现并不能表示出数值0的大小。因为我们认为前导数位的值永远为0,这个时候无论尾数的小数部分和指数部分怎么取,浮点数的值都不会是0。为此我们规定,当指数位全部为0且尾数的小数位全为0时,这个时候浮点数的值为0。注意,+0和-0时两个不同的浮点数,即使他们的数值一样,但是浮点数的表示方式不一样。
- 非标准化的值
当指数部分全为0,但时小数位不全为0的时候,这个时候浮点数表示的值就是非标准化的值。这个时候我们认为该浮点数的前导数位为0,因此这个时候的单精度浮点数大小为(−1)s × 0.f × 2−126,双精度浮点数的大小为(−1)s × 0.f × 2−1022,其中s为符号位上的数值,2为底的指数分别是-126和-1022,而不是-127和-1023。具体原因很简单,因为标准化所能表示的最小值是(−1)s × 1 × 2−126和(−1)s × 1× 2−1022。提出非标准化的目的就是为了表示更小的值从而提高精确度。
- 无穷大
当指数位全为1,而尾数的小数部分全为0时表示+∞和−∞,同时通过符号位来区分+∞和−∞。所以采用IEEE 754标准表示浮点数可以很好的处理无穷大的情况。
- 非数字(NaN)
NaN(Not a Number)用来表示非数字的值,当指数位全为1且尾数的小数部分不为0时表示NaN值。一共有两类NaN值,静态非数(QNaN, Quiet NaN)和警告非数(SNaN, Signalling NaN)。
在一个NaN的值中,如果尾数小数部分首位被置位则表示QNaN。QNaN是很重要的一类非数,四则运算经常传递QNaN值,该值通常表示不被数学上定义的运算结果,比如除数为零的时候。
在一个NaN的值中,如果尾数小数部分首位被置0则表示SNaN。它别用来表示操作中的一个异常,可以用来表示一个未被初始化变量的过早使用。
Reference:
[1] http://steve.hollasch.net/cgindex/coding/ieeefloat.html
[2] https://en.wikipedia.org/wiki/IEEE_754-1985
IEEE 754浮点数表示标准的更多相关文章
- IEEE二进制浮点数算术标准(IEEE 754)
整理自IEEE 754 IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用.这个标准定义了表示浮点数的格式(包括负零-0) ...
- IEEE 754 浮点数在计算机中的表示方法
IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用.这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denorma ...
- IEEE 754 浮点数加减运算
电子科技大学 - 计算机组成原理 小数的十进制和二进制转换 移码 定义:[X]移 = X + 2n ( -2n ≤ X < 2n ) X为真值,n为整数的位数 数值位和X的补码相同,符号位与补码 ...
- IEEE 754 浮点数的四种舍入方式
四种舍入方向: 向最接近的可表示的值:当有两个最接近的可表示的值时首选"偶数"值:向负无穷大(向下):向正无穷大(向上)以及向0(截断). 说明:默认模式是最近舍入(Round t ...
- IEEE 754 浮点数机器表示标准
32位字长浮点数: 共32位 1 8 23 符号位 解码 尾数 0 + 1 - 移127码 原码,隐含小数点前的首位1 不同数据类型之间转换时,隐藏着一些不容易被察觉的错误,比如int 和 un ...
- IEEE二进制浮点数算术标准学习
看到有网上有个项目是要求将浮点数用二进制表示出来,需要用IEEE754标准,查了查维基和深入理解计算机系统,重新学习了一遍浮点数在计算机中的表示和内存中的存储, 先简单的做个笔记,后面需要更深入的理解 ...
- IEEE 754二进制浮点数算术标准
可能很多人都遇到过浮点数精度丢失的问题,下面以JavaScript为例. 1 - 0.9 = 0.09999999999999998 纳尼,不应该是0.1么,怎么变成0.099999999999999 ...
- 基于 IEEE 754 标准的 单精度浮点数计算方式 (未完成)
def dec2bin(dec): if dec < 0: s = ' dec = dec * (-1) else: s = ' e = 127 dec = float(dec) r = int ...
- IEEE 754标准--维基百科
IEEE二进制浮点数算术标准(IEEE 754) 是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用.这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denorm ...
随机推荐
- Paxos共识算法
Paxos共识算法 paxos是一族用来解决分布式系统共识的基础算法,共识过程就是在一组节点上达成一个一致的结果.由于节点可能会错误,通讯消息也可能会丢失,所以建立共识是一个比较复杂的过程. paxo ...
- AbstractQueuedSynchronizer 原理分析 - 独占/共享模式(转)
1.简介 AbstractQueuedSynchronizer (抽象队列同步器,以下简称 AQS)出现在 JDK 1.5 中,由大师 Doug Lea 所创作.AQS 是很多同步器的基础框架,比如 ...
- so easy, too happy
一.预估与实际 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 • Estimate • 估计这个任务需要多 ...
- java 实验1
北京电子科技学院(BESTI) 实 验 报 告 课程:Java程序设计 班级:1352 姓名:杨光 学号:20135233 成绩: 指导教师:娄嘉鹏 实验 ...
- Sprint11
进展:基本设置和显示已经完成,然后是可以通过长按事件弹出对话框可以进行停用.修改.取消该事件提醒的实现,通过触发动作跳转到各个部分页面.
- css3学习笔记二
接着是对图形移动.旋转.倾斜.放缩的处理. -moz-transform:translateX(x deg) translateY(x deg);/*图形会沿着XY轴移动*/ -moz-transfo ...
- HDU 4529 郑厂长系列故事——N骑士问题 状压dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4529 郑厂长系列故事--N骑士问题 Time Limit: 6000/3000 MS (Java/O ...
- windows下的C++ socket服务器(4)
void handleAccept(int socket_fd) { ] = { '\0' }; string cmd; string filename; recv(socket_fd, buf, ) ...
- 继《在Windows下编译扩展OpenCV 3.1.0 + opencv_contrib》修订
在之前的<在Windows下编译扩展OpenCV 3.1.0 + opencv_contrib>中有些问题,后来由于时间不是很充足,故现在对其中的问题进行完善,如下所示对红色框框中的相应的 ...
- HDU 1027 打印沙漏
https://pintia.cn/problem-sets/994805260223102976/problems/994805294251491328 本题要求你写个程序把给定的符号打印成沙漏的形 ...