前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >二进制的科学计数法?白话谈谈计算机如何存储与理解小数:IEEE 754

二进制的科学计数法?白话谈谈计算机如何存储与理解小数:IEEE 754

作者头像
Piper蛋窝
发布2020-11-19 10:56:31
4.9K0
发布2020-11-19 10:56:31
举报
文章被收录于专栏:Piper蛋窝

浮点数的计算机表示(IEEE 754),由 UCB 数学教授 William Kahan 主要起草。后者也因其卓越贡献于1989年获得图灵奖。计算机组成原理与汇编语言这两门课均对该内容有所讲解。与课程中直接抛出公式与概念不同,我想首先与各位探讨"科学计数法"这个概念,进而讨论设计二进制的科学计数法需要涉及到哪些元素。接着,我们讨论如何在内存上表达这个方案。最后讨论计算机的具体实现。

科学计数法

我们都了解科学计数法。科学计数法的精妙之处在于,其将"量级"与"数值"两个信息拆分,让使用者对这两个信息更加明确。

12345 = 1.2345 \times 10^4

如上,我们可以将任何有理数拆分成

A=B \times 10^C

的形式。值得注意的是:

B

的取值范围是

B\in [1,10)
C

一定是一个整数

对于任何有理数,我们都可以用两个范围狭小(规则明确)的数字 B 与 C 来表示。

此外,我们知道,十进制只不过是记录数字大小的一种方式而已。历史上出现过的二进制、三进制、二十进制,都可以毫无障碍地表示数字,并且还有其独具的数学特性。

那么,二进制可以用科学计数法表示吗?答案当然是肯定的。

二进制的科学计数法

A_2 = B_2 \times 10_2^C

注意,这里下标2,代表这个数是二进制。 同理,

10_2

对应十进制中的数字

2=2^1 \times 1 + 2^0 \times 0

通过观察十进制的科学计数法形式,对于二进制,我们自然可以做出如下约定:

B

的取值范围是

B \in [1,2)
C

一定是一个整数

这里我们补充说明一下,二进制的小数是什么样的。对于

5.25

这个十进制数,如果要将其转换为二进制:

  • 将其整数部分与小树部分分开;
  • 对于整数部分 5 ,我们使用"不断除以2取余数"的方法,得到 101 ;
  • 对于小数部分 .25 ,我们使用"不断乘以2取整数"的方法,得到 .01

关于进制转换的具体方法与背后的数学原理,我写过一篇文章进行讨论,见这里:十进制转二进制 / 八进制 / 十六进制的手算方法,及其数学原理的通俗解释

这里,我们只需要明确,二进制是存在小数形式的,且可以表示一切十进制可表示的数(的近似)。

计算机如何记录二进制的科学计数法

接着,我们步入正题:只会表示0/1的计算机,如何记录并表达浮点数呢?

给一个32位的空间,如果不做任何约束,我们只能将其理解为一个整数,并且其取值范围为

[0, 2^{32}-1]

这是因为,计算机只能记录 0 和 1 这两个信息,并不能直接记录小数点点在哪里。因此,我们需要设置一定规则,取出一定位,用于表示小数点点在哪里。这必将牺牲一定的精度与取值范围。

因此,我们将这 32 位空间分为三部分:

  • 第一部分,用于表示精度,即这个数字值是多少,对应上面的B;
  • 第二部分,用于表示小数点,即量级,对应上面的C;
  • 第三部分,用于表示正负,只需要使用1位。

在 IEEE 754 中,我们分别将上述一、二、三部分叫做尾数M阶码E符号s

于是我们有了二进制的表达式:

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

为了表示尽可能多的、常用的小数,我们有如下需求

  • 对于符号位 s ,如果该位上是 0 ,则为正数;为 1 ,则为负数。
  • 对于尾数 M ,其取值范围为
[1, 2)

  • 对于阶码 E ,其为一个整数,并且取值范围应该包含负数、0、正数。

可以注意到,对于 M 、 E ,我们并不能直接用二进制表示,还需要设定一定规则。

尾数 M

假设尾数 M 一共有 f 位,则 f 可表示的整数取值范围为

[0, 2^f - 1]

,我们称 f 直接对应的非负整数为 C 。为了将其投影到

[0, 1)

,我们做出如下变换:

M=1+\frac{C}{2^f}

解码 E

假设解码 E 一共有 e 位,则 e 可表示的整数取值范围为

[0, 2^e - 1]

,我们称 e 直接对应的非负整数为 Exp 。我们希望 E 可以取到负数,因此做出如下变换:

E = Exp - (2^{e-1}-1)

这样,我们的 E 取值范围就来到了

[-(2^{e-1}-1), 2^{e-1}]

总结

有了如上设计的规则,我们便知晓了计算机记录浮点数的方式,以及转换流程。以下图为例。

二进制转换到其对应的十进制数0.15625过程

知识点与例题

上面我们讨论了 IEEE 754 的思想,但是并不严谨,比如:

  • 正负无穷该怎么表达?
  • 如此表示会不会造成空间的浪费?
  • ...

因此,我们从数学上严谨地讨论一道例题,考虑一下规格化浮点数。例题源自我的汇编语言笔记。

题目

给定一个浮点格式(IEEE 754),有k位指数和n位小数,对于下列数,写出阶码E、尾数M、小数f和值V的公式。另外,请描述其位表示。

  • 数5.0;
  • 能够被准确描述的最大奇数;
  • 最小的正规格化数。
解决
前置知识一:IEEE 754

IEEE 754约定,计算机中浮点数二进制表示为:

数字形式:

(-1)^s M 2^E
  • 符号:s
  • 尾数:M,是一个位于区间[1.0, 2.0)内的小数
  • 阶码:E

编码形式:

s

exp

frac

exp域:E(注意,E要进行变换,再存储在exp中); frac域:M。

前置知识二:规格化浮点数(Normalized)

这里讨论到规格化浮点数(Normalized):

  • 满足条件:exp不全为0且不全为1。
  • 真实的阶码值需要减去一个偏置(biased)量:
    • 单精度数:127(Exp:1...254,E:-126...127)
    • 双精度数:1023(Exp:1...2046,E:-1022...1023)
    Bias = 2^{e-1} - 1

    ,e = exp的域的位数

    • E = Exp - Bias
    • Exp:exp域所表示的无符号数值
    • Bias的取值:
  • frac的第一位隐含1:M = 1.xxx...x_2
    • 因此第一位的“1”可以省去,xxx...x:bits of frac
    • Minimum when 000...0 (
    M = 1.0

    )

    • Maximum when 111...1 (
    M = 2.0 - \epsilon

    )

前置工作一:整理变量关系
Bias = 2^{e-1} - 1
E = exp - Bias
V = (-1)^s M 2^E

则E为

dec(exp) - (2^{e} - 1)

E最大值为

2^e - 1 - 1 - (2^{e-1} - 1)= 2^{e-1} - 1

。(为什么不是

2^e - 1 - (2^{e-1} - 1)

呢?因为有规定:exp全部取1为“非规格化浮点数”,因此规格化浮点数中exp不能全部取1,顶多为(1)*(0)

E的最小值为

1-(2^{e-1}-1)=2-2^{e-1}

。(为什么不是

0-(2^{e-1}-1)

呢?因为有规定:exp全部取0为“非规格化浮点数”,因此规格化浮点数中exp不能全部取0,顶多为(0)*(1)

前置工作二:总结特性

抛开例题,来看一个例子:

  • 8位浮点数表示:exp域宽度为4 bits,frac域宽度为3 bits。则,其偏置量的值为2^(4-1) - 1 = 7.
  • 其他规则符合IEEE 754规范。

取值范围如下表。

s

exp

frac

E

value

0

0000

000

-6

0

0

0000

001

-6

1/8 * 1/64 = 1/512

0

0000

010

-6

2/8 * 1/64 = 2/512

...

0

0000

110

-6

6/8 * 1/64 = 6/512

0

0000

111

-6

7/8 * 1/64 = 7/512

0

0001

000

-6

8/8 * 1/64 = 8/512

0

0001

001

-6

9/8 * 1/64 = 9/512

...

0

0110

110

-1

14/8 * 1/2 = 14/16

0

0110

111

-1

15/8 * 1/2 = 15/16

0

0111

000

0

8/8 * 1 = 1

0

0111

001

0

9/8 * 1 = 9/8

0

0111

010

0

10/8 * 1 = 10/8

...

0

1110

110

7

14/8 * 128 = 224

0

1110

111

7

15/8 * 128 = 240

0

1111

000

n/a

inf

可以看出,假设frac有f位,则M可视为:

M=\left\{ \begin{aligned} 0+\frac{1}{2^f} \times C &, \; & \text{if all(exp==0)} \\ 1+\frac{1}{2^f} \times C &, \; & \text{if both '0' and '1' in exp} \\ \text{n/a} &, \; & \text{if all(frac==1)} \\ \end{aligned} \right.

其中,C是整数,由frac决定,即

C=dec(\text{frac})

并且C满足

0 \le C \le 2^f - 1

则浮点数V的十进制即为:

V=\left\{ \begin{aligned} (-1)^s\times2^{2-2^{e-1}}\times(0+\frac{1}{2^f} \times C) &, \; & \text{if all(exp==0)} \\ (-1)^s\times2^{[dec(exp) - (2^{e} - 1)]}\times(1+\frac{1}{2^f} \times C) &, \; & \text{if both '0' and '1' in exp} \\ (-1)^s \; \text{inf or n/a} &, \; & \text{if all(frac==1)} \\ \end{aligned} \right.
dec(exp) - (2^{e} - 1)

也可写作

E

V=\left\{ \begin{aligned} (-1)^s\times2^{2-2^{e-1}}\times(0+\frac{1}{2^f} \times C) &, \; & \text{if all(exp==0)} \\ (-1)^s\times2^{E}\times(1+\frac{1}{2^f} \times C) &, \; & \text{if both '0' and '1' in exp} \\ (-1)^s \; \text{inf or n/a} &, \; & \text{if all(frac==1)} \\ \end{aligned} \right.

其中,

e

f

分别为exp、frac位数,为常数。

解决问题一:数0.5

较为简单,直接解决如下。

代码语言:javascript
复制
0.5   // 转换为二进制 ==>
0.1   // 移动小数点,使其在最左边的1之后
M  = 1.0 // 小数点后的数字存储在frac中
E = -1 // 因为是左移
frac= 0* // 共n位
exp = E + Bias
 = -1 + (2^(e-1) - 1)

则,位的描述为:

s

exp

frac

0

bin(-1 + (2^(e-1) - 1))

00....(共n位)

解决问题二:能够被准确描述的最大奇数

根据前置工作二,可以看出,对于规格化浮点数可化简为:

\begin{aligned} V & = & (-1)^s\times2^{E}\times(1+\frac{1}{2^f} \times C) \\ & = & (-1)^s \times (2^{E}+2^{E-f} \times C) \end{aligned}

现在的任务有两个:

  • 是整数,不能有小数(则
E

应大于等于

f

);

  • 是奇数(
2^E

不是奇数,因此使

2^{E-f} \times C

为奇数,则

2^{E-f}

取1,则取

E=f

)。

下面分类讨论:

情况一:E可以取到f时,

2^{e-1} - 1 \ge f

时,

E

f

C

取其能取的最大奇数,对应的二进制为: exp:dec2bin(

f + (2^{e-1} - 1)

),frac:1*(frac全为1)

情况二:E取不到f时,

这种情况不可能,因为E取不到f,则很多整数都不能表示。

解决问题三:最小的正规格化数

观察:

\begin{aligned} V & = & (-1)^s\times2^{E}\times(1+\frac{1}{2^f} \times C) \\ & = & (-1)^s \times (2^{E}+2^{E-f} \times C) \end{aligned}

s

0

E

C

分别取最小。

由前置工作一,

E

2-2^{e-1}

C

0

,对应的二进制为: exp:0*1,frac:0*

后记:我第一学习浮点数是在2019年年末,当时对于浮点数的笔记和理解是有问题的。在此感谢一位湖南大学的朋友(公众号 / CSDN:梓酥),给我发邮件,指出我的问题~

感谢你读到最后!我是小拍,一名计算机技术爱好者!觉得文章不错的话,可以点击“在看”支持我一下!有任何批评建议或者合作事宜,可以给我发邮件 piperliu@qq.com ,或者关注公众Piper蛋窝,回复「微信」来加我微信联系~
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Piper蛋窝 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 科学计数法
  • 二进制的科学计数法
  • 计算机如何记录二进制的科学计数法
  • 尾数 M
  • 解码 E
  • 总结
  • 知识点与例题
    • 题目
      • 解决
        • 前置知识一:IEEE 754
        • 前置知识二:规格化浮点数(Normalized)
        • 前置工作一:整理变量关系
        • 前置工作二:总结特性
        • 解决问题一:数0.5
        • 解决问题二:能够被准确描述的最大奇数
        • 解决问题三:最小的正规格化数
        • 感谢你读到最后!我是小拍,一名计算机技术爱好者!觉得文章不错的话,可以点击“在看”支持我一下!有任何批评建议或者合作事宜,可以给我发邮件 piperliu@qq.com ,或者关注公众Piper蛋窝,回复「微信」来加我微信联系~
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档