floating points浮点数详解
浮点数构成与储存
浮点数构成
浮点数又称floating point。为什么称浮点数呢?因为小数点是可以根据位数的不同而浮动的!
在说表达形式之前,请大家回忆一下科学计数法,eg.
1.2
∗
1
0
2
1.2*10^2
1.2∗102.
同样,浮点数的表示就是二进制下的科学计数法表示:
+
1.
x
x
x
.
.
.
x
∗
2
y
y
y
.
.
.
y
+1.xxx...x*2^{yyy...y}
+1.xxx...x∗2yyy...y
浮点数的储存(以单精度为例)
根据以上的浮点数的二进制科学计数法表示,我们可以根据表达式组成结构将表达式分成不同的部分:
符号/s/sign: 表示正负
指数/e/exponent:表示指数位大小
小数位/significand:表示小数部分
在单精度下,
符号s占1bit
指数exponent占8bits
小数位significand占23bits
需要注意一点:
我们前面的二进制科学计数法表示是能包含巨大的范围,但是不能包含0!
所以,我们需要留出空间来表示0,在IEEE754标准下,我们把exponent=0&significand=0的位(0/1 00000000 0000000000000000000000)用来表示0。因为+0和-0相同,所以有两个0(i.e.两个数字表示0)!
同时,考虑到需要表示正负两种位数,在IEEE754中用到了Bias Notation偏置表示:将指数exponent的值-偏置量126,即可表示 ±126的指数了。
可能有小伙伴会问:为什么不减去127呢?因为我们 留了一位用来表示0,所以对剩下的7位bit进行操作即可。
那么恭喜大家,得到了浮点数实际(偏置化后)表达式:
特殊的浮点数:区别Nan\Float\Infinity\denorm(以单精度为例)
以上是浮点数的一般式,那么对于一些特殊的数:我们该如何储存/表达呢?
首先,把答案告诉大家!
下面是一张分别以指数Exponent和小数部分significand分类的数字图表和一张数轴形式的表示。
1.表示0
表示方法
如前文,我们把exponent=0,significand=0的数用来表示0。
2.表示±∞
∞的意义
当我们需要求最大值/最小值时,通常我们会定义一个变量用于比较,不妨令为MAX,那么MAX的初值自然就希望越小越好,这时 -∞就有了用武之地。
表示方法
IEEE754中,自然地令exponent=255, significand=0为 ±∞,正负体现在sign位的0/1:0为+,1为负。
3.表示floating point浮点数
表示方法
0和±∞的表示用掉了exponent=0和255的值,所以剩下的exponent就用来表示floating point,即把exponent=1~254,significand = anything用来表示浮点数floating point。
是不是觉得好像0和±∞的表示有些浪费空间:只限定了exponent=0/255,那其他的
2
23
2^{23}
223个数位(significand)用来干嘛呢?
那么下面有意思的来了!!!
4.表示denorm非规格化数
denorm的含义
normalize是标准化,denorm就是去标准化的意思。
为什么要去标准化呢?因为之前的二进制科学计数法就是一种标准化,标准化后出现了问题!以1开头的标准化能表示的最小数a是:
a
=
1.000...000
∗
2
−
126
a
=
2
−
126
a=1.000...000*2^{-126}\\a=2^{-126}
a=1.000...000∗2−126a=2−126
第二小的数b是:
b
=
1.000...001
∗
2
−
126
b
=
(
1
+
2
−
23
)
∗
2
−
126
=
2
−
126
+
2
−
149
b=1.000...001*2^{-126}\\b=(1+2^{-23})*2^{-126}\\=2^{-126}+2^{-149}
b=1.000...001∗2−126b=(1+2−23)∗2−126=2−126+2−149
这张图就形象地表示了这个问题:在0~a之间有一段距离,floating point 无法表示!
怎么办?记不记得我们还有空余空间啊!那就用这些空间来表示这些用标准化/normalized的floating point无法表示的数,所以我们把这些数称之为denorm!
同时,注意到我们还剩 2 23 2^{23} 223个数没有使用,这些正好可以填满 (-a,0)和(0,a) 之间的空隙。
不仅如此,这些denorm之间的间隔也是 a / 2 23 = 2 − 149 a/2^{23}=2^{-149} a/223=2−149,和exponent=1时floating point的间距相同!
表示方法
把exponent=0,significand = nonzero/非零用来表示浮点数非规格化数denorm。
5.表示NaN(Not a Number)
表示方法
把exponent=255,significand = nonzero/非零用来表示浮点数非规格化数NaN。
NaN的作用
在编程中,可能会出现0/0,sqrt(-9) 这些错误,那我们怎么储存这个错误 对应的信息、错误在程序中出现的位置、错误出现在编译的哪个环节…等信息呢?智慧的floating point设计者Khan就把这些信息储存在NaN中,方便编译器为我们报错、debug。