为了转换十六进制到十进制,这里用到了IEEE754规则

组成

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

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

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

精度 符号 尾数 总位数
单精度 1 8 23 32
双精度 1 11 52 64
长双精度 1 15 64 80

正规化

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

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

移码

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

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

精度 移码 二进制表示
单精度 8 127 0111 1111
双精度 11 1023 011 1111 1111
长双精度 15 16383 011 1111 1111 1111

以双精度的为例。双精度的指数位有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

作者:KyrinWoo
链接:https://www.jianshu.com/p/e5d72d764f2f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

通过此例可知,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

作者:KyrinWoo
链接:https://www.jianshu.com/p/e5d72d764f2f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

IEEE754转换规则相关推荐

  1. 基本数据类型转换规则

    基本数据类型转换规则 前言 一. byte.short.char运算的规则 二. 多种数据类型混合运算规则 三.总结 前言 在这篇文章中,我对Java的基本类型数据类型的混合运算做了一些总结,希望可以 ...

  2. IEEE-754标准(32位) 十六进制转换十进制浮点数

    因实验需要,读取陀螺仪的数据是16进制的数据,需要将该数据转化为10进制方便自己查看,理解.记录如下: 1.将(32位)16进制IEEE-754标准浮点数就是用十六进制表示浮点,称为单精度浮点数. f ...

  3. Java虚拟机规范阅读(二)IEEE754简介以及Java虚拟机中的浮点算法

    什么是浮点数 在计算机系统的发展过程中,曾经提出过多种方法表达实数.典型的比如相对于浮点数的定点数(Fixed Point Number).在这种表达方式中,小数点固定的位于实数所有数字中间的某个位置 ...

  4. 从IEEE754标准谈C语言浮点数据类型

    先看下面几个问题,如果你能准确地回答,那么此篇文章将不适合你: 计算机中怎样表示浮点数的,与整型的表示方法有什么不同? 32位精度的float类型和64位精度的double类型能表示浮点数最大范围是多 ...

  5. java:不同数据类型的转换规则

    当参数运算的两个变量的数据类型不同,就需要进行隐式的数据类型转换. 转换规则: 优先级满足: byte < short < char < int < long < flo ...

  6. java32位无符号数_用C语言解释32位无符号长单精度IEEE-754浮点数

    我使用的是Microchip的XC32编译器,它基于标准的C编译器 . 我正在从RS485网络上的设备读取32位值并将其存储在unsigned long中,我将其命名为DWORD . 即 typede ...

  7. Java忽略算术溢出,IEEE-754:“最小”溢出条件

    Before I start, just some background information: 我正在使用编译器标准数学库(符合IEEE-754)在Keil uVision3中编译的ARM7微控制 ...

  8. 进制转换Visual Basic—进制转换规则

    进制转换规则 @ Mayuko 转载于:https://www.cnblogs.com/mayuko/p/4567580.html

  9. 前缀、中缀和后缀表达式详解,中缀表达式到后缀表达式的转换规则,以及后缀表达式的计算规则,附计算代码

    1. 中缀.前缀和后缀表达式 1.1 中缀表达式 首先,中缀表达式的这个"缀"指运算符在两个操作数的位置.中缀表达式其实就是我们常用的算术表达式,比如 2 + 9 - (32 * ...

最新文章

  1. go linux 源码编译环境,Linux 源码安装 GO 环境
  2. js 获取图片url的Blob值并预览
  3. POJ2135 来回最短路(简单费用流)
  4. 调试一个C#研究生管理信息系统源码
  5. 一文看透 Redis 分布式锁进化史(解读 + 缺陷分析)
  6. 1 0.99999的悖论_无限小数与芝诺悖论
  7. 电脑键盘下划线怎么打_图文详解笔记本电脑键盘失灵怎么办
  8. android xutil 数据库,Android XUtils3框架的基本使用方法(二)
  9. hibernate悲观锁,乐观锁
  10. js在html中加文字走马灯特效,jQuery简单的文字跑马灯特效
  11. leetcode大纲
  12. 【学习笔记】bootstrap之CSS组件
  13. 电机学第一章(磁路的基本定律)
  14. 单片微型计算机原理及应用考试,单片机原理及应用《微机原理及应用》试卷(A卷)附答案...
  15. 离线强化学习总结!(原理、数据集、算法、复杂性分析、超参数调优等)
  16. Excel如何删除空白行
  17. 【暑期每日一题】洛谷 P5708 【深基2.习2】三角形面积
  18. 重新回来,介绍一下Android Studio 如何继承腾讯云直播 以及 腾讯云通信
  19. Domino管理中的一些小而有大用处的技巧
  20. R语言ggplot2可视化为轴标签添加下标实战:符号下标、百分比下标、带括号的下标

热门文章

  1. Java Swing(二)按钮点击事件处理ActionListener
  2. API是用来干什么的
  3. 逆波兰式的转换与计算(简单)
  4. 2021年2月教育行业网络关注度分析报告
  5. element UI dialog点击dialog区域外会关闭dialog
  6. 记录vant里面notice-bar使用v-show文字消失问题
  7. GL.iNet MT1300 双频千兆无线路由器
  8. [转载]Emit学习之旅(1):Emit概览
  9. Redis集群批量删除key
  10. Java静态方法的注意事项