计组学习 —— Floating Point
浮点数的表示
0b xx.xxxx
\(2^1\ 2^0\ .2^{-1}\ 2^{-2}\ 2^{-3}\ 2^{-4}\)
这是6位数字分别的含义
可以很容易发现,浮点数的精度是一个很大的问题,对于一个十进制的四位小数,最小的精度是0.0001,而在二进制下这个数为1/16,这中间存在精度误差。
而我们常见的整数往往都是由32位表示的,如何使用有限的有效数字进行表示精度就是一个问题。
同时,小数点的位置永远都不会固定,因为对于同样位数的十进制数,很容易分解出不同位数的二进制数,我们无法预先知道小数点的位置。
根据上述描述,我们需要一种机制来允许二进制点改变位置何跟踪这个位置
所以此时,科学计数法可以满足上述需求
通过科学计数法,我们固定了整数只有一位,这样也就固定了小数的位置。
类似十进制的二进制科学计数法:
\(1.0101_2 \ * 2^1\)
计算机里浮点数的存储
(因此获得了图灵奖)
- 标准格式:
\(\large +1.xx...x_{two}*2^{yy...y_{two}}\)
-
单精度存储方式:
-
为了比较负数与正数,我们在Exponent部分采用偏移的方式<移码>
因为如果采用补码,失去了大小关系,只有移码是保留原本的关系的,我们用0-255来表示-127到128
偏差值(bias)为:-127
如果实际指数为127,那么指数字段设置为254,也就是11111110(七个1一个0)
- 接下来,为了处理正无穷和负无穷问题,我们使用128这个指数表示正无穷(在偏差之后对应的值为255,也就是11111111),使用-127这个指数表示负无穷(在偏差之后对应的值为0,也就是00000000)
-
-
双精度存储方式:
-
0的特殊表示
我们发现,0x00000000为\(1.0*2^{-127}\)不等于0,
- 一切都因为前面默认有一个1
同时还可以发现,0 00000000 00000000000000000000000
和1 00000000 00000000000000000000000
都表示0,一个是+0一个是-0,
但是这样反倒更方便!
无论是极限,还是对于符号的判断,还是用于0作为坟墓的特殊情况,都很方便!
浮点数总结表格
指数 Exponent | 有效数字 Significand | 含义 Meaning |
---|---|---|
0 | 0 | ±0 |
0 | 非0 | Denom Numbers |
1-254 | 所有数 | ±float浮点数 |
255 | 0 | ±∞ |
255 | 非0 | NAN(不符合运算规律) |
Denorm Numbers
Denorm Numbers的产生
-
如何表示最接近0的数呢?
- 我们假设a=1.00....0x2(1-127) = 2-126
-
第二接近的数呢?
- 假设b=1.000...1x2(1-127) = 2-126 + 2-149
-
可以看到0-a之间差了2-126,而a-b之差了2-149,这个差距简直太大了!
所以我们用指数为0,有效数字非0,来表示“不规范的数”,也就是0-a之间的数
Denorm Numbers的定义
-
所有这些数都非常小!
-
实数部分没有前导1!
-
指数部分是-126,不是-127的原因是:当想要移除前导1时,二进制小数点向左移动更多一位。
- 比如,在10进制下 0.0123表示为1.23*10-2,如果我们想要去掉前导1表示为前导0,我们首先要把它表示为0.123*10-1,所以指数的大小减少了1个
-
最小的非规范数: ±0.000...01*2-126 = ±2-149
-
最大的非规范数: ±0.111...1 * 2-126 = ±(2-126-2-149)
-
最小的规范数“: ±2-126
浮点数的限制
- 结果过大?
- x>2128
- 结果过小?
- 0<x<2-149
- 由于分布不均匀,很容易出现精度差
- Small+Big+Small ≠ Small + Small + Big
- 因为它只有23位有效数字!会做近似的取舍,同时在
- 由于分布不均匀,我们无法用浮点数表示出来所有整数
例题
-
BIg = 260 Tiny = 2-15 BigNeg = -Big
-
Big * Tiny * BigNeg == Big * BigNeg * Tiny
如果Big*BigNeg不数据溢出的话,正确,
-
Big+Tiny+BigNeg == BIg+BigNeg +Tiny
错误,因为Big太大了,我们加的时候,我们需要更改二进制后75位有效数字,但是我们的有效位只有23位,所以最后并没有任何内容,所以左侧的表达式会变成0.而0不等于tiny,所以错误。
-