作者:KyrinWoo
链接:https://www.jianshu.com/p/e5d72d764f2f
來源:简书

组成

IEEE754标准包含一组实数的二进制表示法。它有三部分组成:

  • 符号位
  • 指数位
  • 尾数位

三种精度的浮点数各个部分位数如下:

正规化

对于将某个实数表示为计算机浮点数,首先要将其正规化,也就是表示为形如:

的样子。其中b01,而p二进制数表示的指数位。这样,假设想表示为单精度的浮点数,那么第一位符号位用0表示正,用1表示负,在将指数p加上移码表示为8位的二进制数,在接下来的23位填充位数b部分。由于正规化表示时,最左边部分总是1,所以我们只需表示23位的尾数即可。

移码

上述中有一个词:移码(exponential bias)。因为指数p有正有负,那么在8位的指数位中我们就要拿出第一位来指示符号,这样显然会造成不必要的浪费。给指数加上移码,就能保证结果总是一个非负数,也就可以将8个指数位都利用起来。对于有M个指数位的精度,其移码为:

这样就得到上面三种精度的移码:

以双精度的为例。双精度的指数位有11位。这样可以表示的数是从000 0000 0000111 1111 1111,也就是指数加移码所表示的范围从0到2047,那么,减去移码1023,则可以表示的指数是-1023到1024。但是注意,-1023和1024作为他用(后面会说到)。所以实际上能表示数的指数是从-1022到1023。

例子

【例】:求3.14的单精度浮点数表示。
首先将3.14转成二进制。整数部分3的二进制是11b,而小数部分0.14的二进制是:0.0010001111010111000010[10001111.....]b(方括号中表示小数点后第23位及之后)。这样,3.14的二进制代码就是:11.0010001111010111000010[10001111....]×20,那么用正规化表示就是:1.10010001111010111000010[10001111....]×21。 方括号表示的就是小数点后第24位了,由于单精度浮点数尾数只有23位,所以需要舍入(舍入方法见后):由于第24位为1,且之后不全为0,所以需要向第23位进1完成上舍入:1.10010001111010111000011×21。而其指数是1,需要加上移码127,即128,也就是(000 1000 0000)b。它又是正数,所以符号为0。综上所述,3.14的单精度浮点数表示为:
0 000-1000-0000 1001-0001-1110-1011-1000-011
十六进制代码为:0x4048F5C3

通过此例可知,3.14的单精度浮点数表示是0 000-1000-0000 1001-0001-1110-1011-1000-011。现在我们来还原,看看它的误差。

  • 指数是128,那么还原回去,实际指数就是1
  • 尾数还原也就是:10010001111010111000011,所以是:1.10010001111010111000011×21,也就是11.0010001111010111000011。利用二进制转十进制,可得它对应的十进制数是:3.1400001049041748046875。显然与3.14是有误差的。

我们再通过另一种方法估算误差。从例子中可知,对于3.14的单精度浮点数,我们舍去了第24位以及之后,它们是:.......[10001111.....]×21。不妨假设此后全是0,也就是舍去了0.10001111b×2-23×21约为0.00000013317912817001;而后,由于舍入进位关系,给第23位又加了1,所以加了:2-23×21。所以,误差约为2-23×21-0.10001111b×2-23×21=0.00000010523945093155。所以结果大致为3.14+0.00000010523945093155=3.14000010523945093155
可见和上面计算结果大致相同。

机器ε(machine epsilon)

机器ε表示1与大于1的最小浮点数之差。不同精度定义的机器ε不同。以双精度为例,双精度表示的1是:

而比1大的最小双精度浮点数是:

可见,此二者之差为:2-52≈2.220446049250313e-16。所以它就是双精度浮点数的机器ε。
在舍入中,相对舍入误差不能大于机器ε的一半。比如上面的3.14的单精度浮点数,二者误差绝对值是0.0000001049041748046875....,从而相对舍入误差为0.0000001049041748046875....÷3.14≈0.00000003340897286773。而单精度浮点数的机器ε为2-23≈1.1920928955078125e-7,它的一半是0.00000005960464477539。显然,相对舍入误差小于单精度浮点数机器ε的一半。

非正规化:0的表示

从正规化中可知,无论如何浮点数都满足最左边是1。这就有一个严重问题:0没有办法被表示。为此,可以使用非正规化的表示方法,即让最左边默认为0,这样再另尾数也全部为0,就可以表示0了。
新的问题又来了:什么情况下是非正规化,什么情况下又是正规化呢?
答案就是通过指数部分来反映。记得前面说过,双精度浮点数中,指数加移码的范围可以从0到2047,然而0和2047是作为他用的。在这里,指数部分为0就代表着非正规化。
所以,当见到指数部分为0是,尾数部分就不再是1.bbbbb...而是0.bbbbb...了。
在进一步,对于非正规化,可以看成是正规化中,小数点向左边跑了一位:1.bbbb....×2^-1023=0.1bbbb....×2×2^-1023==0.1bbbb....×2^-1022(只是概念上理解,小数第一位也不一定非要是1,如0.001010×2^-1022也可)。所以,非正规化下表示为:

现在,0就可以表示了。值得注意的是,此时0可以表示位+0和-0。
因为它的最左边不是1是0,实际上可以表示更小的数。双精度浮点数下,使用非正规化可以表示的最小的正数是0.00......01×2-1022也就是2-52×2-1022=2-1074
请注意这个最小数和前面提到的机器ε的区别。比机器ε小的数是可以被表示出来的(利用非正规化)。但是当它们与其他浮点数做运算时,因为要转成同一种格式(正规化格式),从而可能会因为溢出位而被舍弃。最终结果就是,这些更小的数尽管能被表示,但是对运算结果没有影响。

浮点数加法
机器加法要先将两个操作数的小数点对齐,相加后再转为浮点数存储。这里最重要的一点是,尽管浮点数有位数限制,但是加法会在精度更高的寄存器中进行,这意味着,寄存器能够运算出比52位还要多的位数,但是在转回浮点数存储时,多余位数会被舍弃,造成两者相加的机器结果不严格等于算术结果。

无穷大与NaN

上面说到,在双精度浮点数中,指数为0表示非正规化,那么指数为2047(二进制是111 1111 1111b,即11位指数位全为1)就表示无穷大和NaN(Not a Number)。具体表现在,当指数是2047,当尾数,全为0就表示无穷大,当尾数不全为0就表示NaN。

舍入规则

以52位尾数位的双精度浮点数为例,舍入时需要重点参考第53位:

  • 若第53位为1,而第53位之后全部为0。此时就要使第52位为0:若第52位本来就是0则不管,若第52位为1,则第53位就要向第52位进一位,这样第52位就可以为0
  • 若不是上面的情况,即第53位1,但是第53位之后不全为0,则第53位就要向第52位进一完成上舍入。
  • 若也不是上面两种情况,那么第53位必为0,此时直接舍去不进位,称为下舍入。

由于存在这种舍入规则,浮点数一般在机器内都不会以原数精确相等的存储,这就会使在某些情况下,使用浮点数做算术运算时出现令人费解的情况,如在JavaScript中(数以双精度存储):

>>9.4-9-0.4===0
<<false
>>(9.4-9-0.4).toFixed(20)
<<"0.00000000000000033307"

可见9.4-9-0.4不严格等于0,其结果有极小误差。因为按照上面的算法可知,9.4在机器内被表示为:9.4+0.2×2-49,而0.4被表示为0.4+0.1×2-52。这样,当9.4-9时(因为9是整数是可以精确存储的)得0.4+0.2×2-49,再减去0.4+0.1×2-52得3×2-53,约等于"0.00000000000000033307"。

循环小数的二进制转回十进制的技巧
某循环小数的二进制码是:0. 0110 0110 0110 0110 0110.....b。可见是0110的循环,令x为其十进制数:x=0.01100110.....b,则24x=110,01100110.....b,两式相减得:(24-1)x=110b,即15x=6,从而x=6/15=0.4

IEEE 754标准相关推荐

  1. c语言变凉存储性,C语言数据的表示和存储(IEEE 754标准)

    C语言的数据类型大体上分为整数和浮点数两种类型.因为char和指针类型实际上都是整数类型. 移码:给每一个数值加上一个偏置常数即可.通常是加上2^(n-1)或者是2^(n-1)-1这里的n通常取编码的 ...

  2. IEEE 754标准--维基百科

    IEEE二进制浮点数算术标准(IEEE 754) 是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用.这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denorm ...

  3. Java入门之7:Java中的float和double类型的浮点数是怎么按照IEEE 754标准存储的?

    前言: 这篇博文,我写了好几天--,里面涉及的基础概念比较多,内容比较多,举例也比较多,想搞清楚明白就难免 我自己都会觉得啰嗦,我整理了目录出来,看完需要一点时间,可以自行根据需要.感兴趣的 选择阅读 ...

  4. 【编程基础】浮点数在计算机中的存储 —— IEEE 754标准

    寻求更好的阅读体验,请移步 :浮点数在计算机中的存储 -[Mculover666的个人博客]. 用于存储小数的数据类型是有单精度浮点型(float)和双精度浮点型(double),那么,浮点数在计算机 ...

  5. 浮点数的二进制表示(IEEE 754标准)

    浮点数是我们在程序里常用的数据类型,它在内存中到底是怎么样的形式存在,是我了解之前是觉得好神奇,以此记录,作为学习笔记.现代计算机中,一般都以IEEE 754标准存储浮点数,这个标准的在内存中存储的形 ...

  6. 2.3.1-4. IEEE 754 标准

    棒棒哒加油哦(•̀ω•́)✧ 好的,上个学期说我们学习了,浮点数的基本构成,还有一个原理,浮点数大致上分为接码,还有尾数这样的两个部分组成,那上个小节的末尾我们提到过,如果说我们不能确定一个统一的规则 ...

  7. IEEE 754二进制浮点数算术标准

    可能很多人都遇到过浮点数精度丢失的问题,下面以JavaScript为例. 1 - 0.9 = 0.09999999999999998 纳尼,不应该是0.1么,怎么变成0.099999999999999 ...

  8. IEEE 754浮点数工业标准

    文章目录 浮点数概述 浮点数的格式 IEEE 754标准规定的浮点数的格式 IEEE 754偏移量与指数范围问题 IEEE 754中浮点数值的三种情况: 1. 规格化的浮点数的值 2. 非规格化的值 ...

  9. IEEE 754浮点数标准详解

    转载于:http://c.biancheng.net/view/314.html 在计算机系统的发展过程中,业界曾经提出过许多种实数的表达方法,比较典型的有相对于浮点数(Floating Point ...

最新文章

  1. 矿大计算机控制技术,潜心科研,匠心育人,来看看矿大这位带领国内顶尖团队的“大拿”的多面人生!...
  2. Yii的Url::toRoute
  3. 自动监控主从MySQL同步的SHELL脚本
  4. SQL实战篇:SQL窗口函数及真题
  5. twitter达人不能不知的缩写
  6. 如何使用Cisdem Video Converter在Mac上将大型 AVI 转换为 MP4
  7. Qt creator5.7 OpenCV249之图片灰度处理(含源码下载)
  8. 分布式ID | 这六种分布式ID生成方法,总有一款适合你
  9. GCC图神经网络预训练概述
  10. 国产CAM究竟水平如何?看完测试我震惊了
  11. 数据通信与计算机网复习题,数据通信与计算机网络 复习题总.doc
  12. 体检导检系统服务器系统,全科智能导检系统
  13. 使用WebSocket实现一个网页版的聊天室(摸鱼更隐蔽)
  14. 11. Zigbee应用程序框架开发指南 - 命令行接口(CLI)
  15. qq三国行脚商脚本思路分享
  16. 医学图像数据集:肝脏和肿瘤分割数据集
  17. 将数字转换成对应的中文 将阿拉伯数字翻译成中文的大写数字
  18. 工作笔记八——vue项目的多语言/国际化插件vue-i18n详解
  19. 论文解读 Receptive Field Block Net for Accurate and Fast Object Detection
  20. Linux进程(二):生命周期

热门文章

  1. VMware Workstation 虚拟机中的 虚拟机使用Windows 连接共享访问 Internet
  2. 【Linux命令】Linux复制时显示进度
  3. (四)进程的生命周期——起源
  4. 航天器/控制器飞行能够实现自主控制么?
  5. 2834: 小凯的书架
  6. nginx快速配置参考
  7. nginx配置和优化详解
  8. Android Dialog
  9. 微信小程序分享功能的实现方法有两种
  10. 转:九月十月百度人搜,阿里巴巴,腾讯华为笔试面试八十题(第331-410题)