小甲鱼 发表于 2015-12-18 17:23:01

浮点数:表示更大范围的小数(#)

浮点数:表示更大范围的小数(#)

使用定点法来保存小数并不是最优秀的方案,不比整数,保存小数需要考虑到两个维度:精度和范围。

提高精度只能通过不断地扩充位数来实现;而定点数可以表示的取值范围十分有限(见上一节最后的栗子)。

浮点数的发明,正是为了解决取值范围的这个问题。


大家应该都知道科学计数法吧(百科:科学计数法),IEEE 浮点数表示方式跟科学计数法有些相似,但更为复杂。

IEEE 浮点标准用的形式来表示一个数。

组成部分依次是“符号 * 尾数 *阶码”:


[*]符号(sign)决定这个数是正数(s = 0)还是负数(s = 1);
[*]尾数(significand)决定这个数的精度,这里是用定点法表示;
[*]阶码(exponent)决定这个数的范围,它是一个加权值,权重自然是 2 的 E 次幂。

下边小甲鱼给大家列举出 C 语言中对 float 和 double 的封装格式:





可见,float 的三个字段分别是分配 1 位,8 位和 23 位;而 double 则是分配 1 位,11 位和 52 位。

当然,这里并不是直接用二进制表示各个字段的值,要不小甲鱼就不用写这篇文章了……

{:9_237:}

根据阶码(exponent)的值,上述编码还需要被解释成 4 种不同的情况(下边以 float 举例):

1. 规格化的值



2. 非规格化的值



3. 无穷大



4. NaN(Not a Number,不是一个数)




OK,下边小甲鱼给大家逐一介绍:

1:规格化的值

这是最普遍的情况,当 exp 字段不全为 0,也不全为 1 的时候,属于这种情况。

在这种情况下,阶码字段被解释为以偏置(biased)形式表示的有符号整数。

{:9_229:}

呃……说人话就是你只需要记住公式:E = e - Bias

其中,e 是一个无符号数,其值为 exp 字段表示的值;Bias 是一个等于 (k 即阶码字段的位数)的偏置值。

由此不难推导出指数 E 的取值范围是 -126 ~ 127(float)和 -1022 ~ 1023(double)。

对于 frac 字段则被解释为描述小数的值,如果我们把该值称之为 f,则 0 <= f < 1,而尾数被定义为 M = 1 + f

因此,在这种情况下,尾数的第一位总是 1。


2:非规格化的值

当 exp 字段全为 0 的时候,所表示的数就是非规格化形式。

在这种情况下,阶码的值是 E = 1 - Bias

而尾数被定义为 M = f

因此,在这种情况下,尾数即小数的值(第一位不是 1)。

非规格化数用于表示那些非常接近 0.0 的数。


3. 无穷大

当 exp 字段全为 1,且 frac 字段全为 0 的情况下,该浮点数表示无穷。

即 s = 0,结果为正无穷;s = 1,结果为负无穷。

当我们把两个非常大的数相乘,或者除以 0 的时候,无穷能够表示溢出的结果。


4. NaN

在第 3 种情况的基础上,frac 即小数域为非 0 时,我们把结果称之为 NaN,即 Not a Number(不是一个数)。

一些运算的结果不能是实数或无穷来表示,就会返回这样的 NaN 值。


小甲鱼知道大家现在肯定云里雾里的,下边举几个栗子吧!

{:9_227:}

某天,小甲鱼在内存中捡到一个 float 变量,存储如下:



分析:

1. 符号位为 0,说明这丫是一个正数;

2. exp 字段不全为 0 或 1,表示这是一个规格化的值。根据公式 E = e - Bias,求得 E = 124 - 127 = -3;

3. frac 字段的值为 3/4(这里是定点数表示法,忘了的鱼油请回顾上一篇),则 M = 1 + 3/4 = 7/4

4. 根据浮点数公式,求得:



其实也是很简单的,对吧?!

{:9_223:}

回复“朕想知道”,给你看一篇文章 —— 浮点溢出的高昂代价
**** Hidden Message *****
本文参考:《深入理解计算机系统》P70 ~ 72

小甲鱼的二师兄 发表于 2015-12-21 20:16:05

看看

小甲鱼的二师兄 发表于 2015-12-21 20:16:36

朕知道了

hb8689 发表于 2015-12-21 21:37:35

顶起来~~~~~~~~~~~~~

燃烧的水 发表于 2015-12-22 08:56:58

11

燃烧的水 发表于 2015-12-22 09:07:51

float的三个字段位分别是是1位,8位和23位?

counting_stars 发表于 2015-12-22 13:33:36

已经晕了

wmh. 发表于 2015-12-22 15:34:49

联想知道

miaomaio 发表于 2015-12-22 21:09:24

郑想知道

斯塔德 发表于 2015-12-22 21:31:33

刚好在看这本书。正看的发晕呢

人造人 发表于 2015-12-23 17:29:23

想知道

桃花飞舞 发表于 2015-12-24 08:41:45

:call:

tenqaz 发表于 2015-12-24 13:31:42

郑想知道,
好难啊!!
1{:9_238:}

zwy12138 发表于 2015-12-25 21:33:37

朕想知道

lawry 发表于 2015-12-27 13:53:20

学习一下浮点数

唐尸诵词 发表于 2015-12-27 20:40:01

真想知道

zxcmaqi 发表于 2015-12-28 19:41:13

朕想知道

lonelybingo 发表于 2015-12-29 09:24:08

:dizzy:

cn12580 发表于 2016-1-4 16:01:31

朕想知道

DOUBLEC 发表于 2016-1-4 21:07:41

上面“1位,8位,23位”编辑错了{:5_91:}
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 浮点数:表示更大范围的小数(#)