引言

大家都知道,可以在计算机处理器直接运行的是由0,1构成的机器代码(machine code),本文将介绍浮点数(floating-point number )在机器码中是如何被编码表示的
整数(integer)是如何被编码的呢?小伙伴们应该听过补码,原码,反码吧,这些正是整数被编码的不同规则。

原码:一定字长,在不溢出的情况下,最高位是符号位,跟上该整数二进制表示。符号位中0代表正数,1代表负数。
补码(two's compliment):最高位也是符号位,但是与原码不同的是符号位也参与到求值里。
例如:1001=-2^3+1=-7
而原码中 1001=-1

代表同一数值的原码是可以转换成其补码的。

 很多文章里说补码是无法直接转换成十进制数值,要先换成原码再求,其实这是错误的。理解补码最高位也是参与值的即可。

后续笔者将会撰写一篇文章详细讲解原码,补码,以及反码。

下面开始正题吧!

浮点数(floating-point number)是什么

其实计算机表示小数有两种方式:

  1. 定点数 (fixed-point)
  2. 浮点数(floating-point)
    区别在于,定点数编码小数时小数点位置是确定的,浮点数小数点位置是可以变化的。
    如何用科学计数法来表示二进制小数,即形如:
    V=(−1)s×M×2EV=(-1)^s \times M \times 2^E V=(−1)s×M×2E
    0.25(d)可以写作
    0.01(b)×200.01(b)\times2^00.01(b)×20
    也可以写作
    1.0(b)×2−21.0(b)\times 2^{-2} 1.0(b)×2−2
注:括号中的字母
d表示十进制 decimal
b表示二进制 binary
h表示十六进制 hexadecimal

IEEE floating-point representation

正如上文所述,IEEE是编码小数的一种标准。类比一下十进制的科学计数法,实际上也算一种标准,要写成形如
a×10b(其中∣a∣>=1且<10)a\times10^b (其中|a|>=1且<10) a×10b(其中∣a∣>=1且<10)
而二进制和十进制的区别只是基数不同,二进制也可以写成像科学计数法的形式。
而计算机正是用了这种方式

IEEE表示数V,而V可以写成如下形式:
V=(−1)s×M×2EV=(-1)^s \times M \times 2^E V=(−1)s×M×2E
已知数字特点,那么计算机只需要存取s,M,E即可。

s: sign ***占最高的一位***,可以看出是**符号位**,s=1表示负数(或0),s=0表示正数(或0)
M: significand **尾数**,二进制小数
E: exponent 对该数加权(可能是负数)

计算机常见字长有 32bit 64bit,因此IEEE规定了对应的两种不同位数的编码方式:
32位称为单精度
64位称为双精度

这些数就是想把 s,M,E 存起来
最简单的方法就是直接全部转换成对应的二进制数,放到对应的位置上,显然IEEE不是这样。


如图,图中s编码s,exp编码E,frac编码M。这里的编码规则其实就是IEEE浮点数表示的核心了。

三种情况

设exp位有k位,frac有n位

Case 1(normalized values): exp位不全为0 且 不全为1

规定:
E=exp-Bias
Bias翻译为偏置量 且规定
Bias=2k−1−1Bias=2^{k-1}-1 Bias=2k−1−1
稍后分析Bias这样规定的原因。

根据位数和exp位的限定,我们可以推测出case1可表示的值范围。

由此图得知,E的范围比较对称,有一定负数,让浮点数中较小的值也可以编码。

M=1+ frac
由此可见,case1 无法表示0, 因为M永远大于等于1。

Case 2 (denormalized values):
exp位全部0
规定:
E=1-Bias(Bias=2^(k-1)-1)
M=frac

作用:

  1. 表示0 (+0与-0)。
  2. 表示一些非常接近于0的小数。

Case 3(special values):
exp位全部为1

当frac位不全为0时:
表示NaN(not a number) 比如根号下-1

当frac位全为0时:
如:k=3,n=2时
111100 011100 分别表示-∞与+∞

case 正负 E M
case 1: exp位不全为0或1 s=0为正,s=1为负 E=exp-Bias M=1+frac
case 2:exp位全部是0 s=0为正,s=1为负 E=1-Bias M=frac
case 3:exp位全部是1 frac=0,s=0表示正无穷,s=1为负无穷;frac!=0,均表示NaN NA NA

特点

可以看出一定位数能表示的二进制浮点数是有限的。

k=2,n=2时,让我们列出该情况下可以编码的所有数。
易知,bias=2^1-1=1

为了直观,V都化成了以4为分母的分数。

no. bit e E f M V
1 0 00 00 0 0 0 0 0
2 0 00 01 0 0 1/4 1/4 1/4
3 0 00 10 0 0 1/2 1/2 2/4
4 0 00 11 0 0 3/4 3/4 3/4
5 0 01 00 1 0 0 1.0 4/4
6 0 01 01 1 0 1/4 4/5 5/4
7 0 01 10 1 0 1/2 3/2 6/4
8 0 01 11 1 0 3/4 7/4 7/4
9 0 10 00 2 1 0 1 8/4
10 0 10 01 2 1 1/4 5/4 10/4
11 0 10 10 2 1 1/2 3/2 12/4
12 0 10 11 2 1 3/4 7/4 14/4
13 0 11 00 - - - - +∞
14 0 11 01 - - - - NaN
16 0 11 10 - - - - NaN
17 0 11 11 - - - - NaN

其中
大家也可以自己列一下这个表,加深理解。

同时我们发现了从case 1到case 2的变化是非常均匀 的,V的变化量为1/16,这正是case2中 规定E=1-bias 的用意!!!
但是注意后面V值变化并不均匀!!!

我们来讲两个例子。

  1. 0 00 10
    可以其判断属于case 2(exp位都是0)
    exp: 00(binary)=0(decimal)
    E=1-bias=1-3=-2
    frac: 0.10(b)=1/4(d)
    M=f= 1/4(d)
    V=2^(0)✖️1/4✖️2 ^(-2)=1/16

  2. 0 10 11
    可以其判断属于case 1(exp位不都是1或者0)
    exp: 10(b)=2(d)
    E=exp-bias=2-3=-1
    frac: 0.11(binary)=3/4(decimal)
    M=1+f=7/4(d)
    V=2^(0)✖️7/4✖️2 ^(-1)=14/16

V与IEEE表示的相互转换

IEEE位格式(bit representation)到V

上文在讲例子时,已经介绍了从位格式求V值。
步骤:

  1. 根据exp位判断属于哪个case
  2. 写出s,exp,frac 根据不同规则求出E,M
  3. 代入公式

V=(−1)s×M×2EV=(-1)^s \times M \times 2^E V=(−1)s×M×2E

V转换成IEEE位格式

步骤:

  1. 明确单精度还是双精度。顺势求出bias值
    单精度: s 1位, exp 8位, frac 13位,bias=127
    双精度: s 1位, exp 11位,frac 52位,bias=1023
  2. 判断是case 1 还是case 2(case3 的情况只有+∞和NaN)
    Bit representation很好看出 exp。
    这种情况也不难,判断一个范围即可,求出case 1能表示的最大值(正数为例)。

单精度:
1 00000000 1111111111111
exp=0
E=1-bias-1-127=-126
frac=0.1111111111111(b)=0.9998779296875
M=0.9998779296875
V=2^(-126)✖️0.999877929687
约等于
1.17535×10−381.17535\times 10^{-38} 1.17535×10−38
若V比此值小,则是case 1。否则是case 2。

双精度
该值约等于
2.22507×10−3082.22507\times 10^{-308} 2.22507×10−308

  1. 将V值转换成二进制(只考虑能确切转换成二进制的情况),并化成标准型
    形如
    V=(−1)s×M×2EV=(-1)^s \times M \times 2^E V=(−1)s×M×2E
    注意:
    case 1, 用E来加权,调整M到位数1.xxxxxxx
    case 2, 用E来加权,调整M到位数0.xxxxxxx

举例:
单精度下,V=12345.0(d)
解:显然属于case 1
12345.0(d)=11000000111001
化标准型
V=20×1.1000000111001×213V=2^{0}\times1.1000000111001\times 2^{13} V=20×1.1000000111001×213
则 s=0
frac=10000001110010000000000 【13位,少了还得在后面补0,凑成23位】
E=13
exp=E+bias=13+127=140=10001100(b)【恰好8位,少了在前面补0
则位表达为
010001100100000011100100000000000 1000110010000001110010000000000 01000110010000001110010000000000

舍入问题 (Rounding)

“Floating-point arithmetic can only approximate real arithmetic, since the representation has limited range and precision. Thus, for a value x, we generally want a systematic method of finding the ‘closest’ value.”

“The IEEE floating-point format defines four different rounding modes. The default method finds a closest match, while the other three can be used for computing upper and lower bounds”

其中说的默认方法是round-to-even,它和传统的四舍五入的唯一区别就是对中值的处理。
四舍五入,顾名思义,五永远是要进位的。
而round-to-even,五的话要round到最近的偶数值。

比如:1.5 四舍五入后 2
1.5 round-to-even 2
2.5 四舍五入后 3
2.5 round-to- even 2

优势:
在统计时,若采用四舍五入,那么数据值总是偏大一些,而round-to-even方法在中值处舍和入的概率都是0.5,数据值较为准确。

mode 1.4 1.6 1.5 2.5 -1.5
四舍五入 1 2 2 3 -2
round-to-even 1 2 2 2 -2
round-toward-zero 1 1 1 2 -1
round-down 1 1 1 2 -2
round-up 2 2 2 3 -1

round-toward-zero 模式就是在向0舍入。
round- down就是向数轴负方向舍。
round-up就是向数轴正方向入。

补充:

  1. round-to- even在保留一定位小数时也可以用到。
    比如:1.2350和1.2450保留2位小数。用round-to-even mode后都是1.24
  2. 二进制也可以用round-to-even
    0为even(偶数),1为odd(奇数)
    比如:保留2位小数。
    10.00011 (b)应该为 10.00(b) 而 10.00110(b)应该为10.01(b)。这两个数都不是中值。
    举两个中值(请体会这里中值的含义,是对于保留2位小数而言的)的例子吧!
    10.001(b)应该舍为 10.00(b)
    10.111(b)应该进入为11.00(b)
    注意:都是让小数舍入后最低位为even,即0

二进制小数舍入(Round-to-even)例题:

保留一位小数

before 与中值的关系 after
10.011 大于中值,要入 10.1
10.010 等于中值,要round-to-even(0) 10.0
10.110 等于中值,要round-to-even(0) 11.0
11.001 小于中值,要舍 11.0

关于中值:
10.0xx保留一位小数,其中值为10.010,准确的说,10.010是10.0(舍后的值)与10.1(入后的值)的中值。
类比1.5是1(舍后的值)和2(入后的值)的中值。

参考资料:Computer Systems: A Programmer’s Perspective 3rd edition

亲爱的读者们,欢迎指正错误和提问。

如何深刻理解IEEE浮点数的表示(IEEE floating-point representation)相关推荐

  1. IEEE浮点数尾数向偶舍入-四舍六入五成双

    IEEE浮点数舍入默认算法 可以用一句话来概括 四舍六入五成双 例如有效数字超出规定数位的多余数字是1001,它大于超出规定最低位的一半(即0.5),故最低位进1.如果多余数字是0111,它小于最低位 ...

  2. IEEE浮点数表示法

    月初还在上班的时候,就天天盼望着过年放长假,然而终于熬到了过年,却发现自己的12天的长假将在碌碌无为中度过,朋友们又一个接一个的远去,心里真是拔凉拔凉的啊!最近版上的人气有点低落,连违规率(不敢说犯罪 ...

  3. IEEE浮点数 换算方法【超易懂详解】

    IEEE浮点数 换算方法[超易懂详解] 格式概览 转换方法 0. 例子说明 1. 小学乘除:十进制 转 二进制 2. 小学数学:科学计数法 3. 儿童观察力:提取三个元素 4. 幼儿手工:收尾拼接 附 ...

  4. IEEE 浮点数:存储及方式,学习与记录,总结与反思

    摘要:看了看资料,确认过眼神,还是我驾驭不了的浮点数.浮点数的内容似乎十分庞大,我一时还无法完全理解,因此本篇只记录IEEE标准的 float 的二进制表示方式,能够学会手动将浮点数的二进制与十进制相 ...

  5. 【Python基础】为何0.1+0.2≠0.3,使用Python程序深入理解计算浮点数的运算

    [Python基础]为何0.1+0.2≠0.3,使用Python程序深入理解计算机浮点数的运算 用过Python这门编程语言的应该都会发现,当我们输入0.1+0.2时,打印出来的却不是0.3,而是0. ...

  6. 通过配置ssh深刻理解puppet的语法及工作机制

    通过配置ssh深刻理解puppet的语法及工作机制 需求分析 1).要求openssh-server处于被安装状态 2).要求在配置文件/etc/ssh/sshd_config正确的情况下,sshd服 ...

  7. F#学习之路(2) 深刻理解函数(上)

    函数在函数式编程语言中是一等公民,是函数式语言中最重要的基本组成元素,也是其名称的由来. F# 中的函数之如C#中的类,是组织程序结构的最基本单元.是命令式编程语言中函数或OO编程语言中方法的超集.超 ...

  8. 曲线均匀分布_曲线篇:深刻理解B 样条曲线(下)

    前两篇中讲解了贝塞尔曲线和B样条基础. FrancisZhao:曲线篇: 贝塞尔曲线​zhuanlan.zhihu.com FrancisZhao:曲线篇:深刻理解B 样条曲线(上)​zhuanlan ...

  9. 深入理解C++浮点数(float、double)类型数据比较、相等判断

    深入理解C++浮点数(float.double)类型数据比较.相等判断 浮点数在内存中的存储机制和整型数不同,其有舍入误差,在计算机中用近似表示任意某个实数.具体的说,这个实数由一个整数或定点数(即尾 ...

  10. 【JavaScript】JavaScript模拟实现面向对象一张图帮助你深刻理解原型链和原型对象

    文章目录 一.JavaScript模拟面向对象 1.函数是类 2.函数中各种变量的声明 3.关于函数内的this 小结:JavaScript中函数是什么? 4.练习:面向对象思想编写Complex类 ...

最新文章

  1. 中汽创智科技首席人工智能官丁华杰:AI赋能自动驾驶的几点思考
  2. go 公众号 关注 监听_荐号丨推荐五个适合法学院关注公众号
  3. linux 索引代码的函数定义,Linux网络接口操作之if_nameindex
  4. Activit系列之---Activity的生命周期
  5. c语言结构-的优先级,c语言运算符号优先级
  6. Ubuntu系列10.04、11.04、12.04等虚拟机中安装VMware Tools
  7. 前端传值后端接收不到_关于前端传参数,后台接收的问题
  8. php 操作xls,php中使用PHPExcel操作excel(xls)文件
  9. cad---菜单,工具栏,屏幕菜单,增强工具栏
  10. 一文看雷击浪涌的防护解析
  11. RSA加密解密及制作软件license
  12. wxj platte
  13. 解决Linux命令行前出现base
  14. macOS下载【转载】
  15. 明日之后最好看的房子又来啦:情侣专属泰坦尼克号造型登场
  16. 关于Microsoft Edge 浏览器无法使用selenium调用问题
  17. 迪文串口屏(DMG10600C101-03WTC)的使用测试
  18. css图片精灵定位_CSS精灵图片(CSS sprite)使用心得
  19. matlab中如何处理复数,matlab中复数的处理函数
  20. 详细线上问题跟进流程

热门文章

  1. JS中如何删除li节点
  2. MathPage.wll not found
  3. 已解决:Word加载MathType时出现MathPage.wll或MathType.dll文件找不到
  4. windows系统镜像修复计算机,Win7操作系统下系统还原和映像修复方法
  5. 鸿蒙双系统怎么切换,苹果 Mac双系统如何切换?用Option键切换双系统的步骤分享...
  6. python操作word生成目录_Python操作Word批量生成文章
  7. http 阮一峰_JavaScript 标准参考教程(alpha) 阮一峰
  8. 扫地机器人的喋血江湖
  9. 金三银四,作为Java程序员的你为什么面试总拿不到高薪?
  10. 麦德龙的商品供应链管理