发布网友 发布时间:2023-05-26 04:13
共1个回答
热心网友 时间:2024-10-21 20:52
IEEE754标准包含一组实数的二进制表示法。它有三部分组成:
三种精度的浮点数各个部分位数如下:
对于将某个实数表示为计算机浮点数,首先要将其正规化,也就是表示为形如:
的样子。其中 b 是 0 或 1 ,而 p 二进制数表示的指数位。这样,假设想表示为单精度(float)的浮点数,那么:
上述中有一个词:移码(exponential bias)。因为指数 p 有正有负,那么在8位的指数位中我们就要拿出第一位来指示符号,这样显然会造成不必要的浪费。给指数加上移码,就能保证结果总是一个非负数,也就可以将8个指数位都利用起来。对于有 M 个指数位的精度,其移码为:
这样就得到上面三种精度的移码:
通过此例可知,3.14的单精度浮点数表示是 0 1000-0000 1001-0001-1110-1011-1000-011 。现在我们来还原,看看它的误差:
利用二进制转十进制,可得它对应的十进制数是:3.1400001049041748046875。显然与3.14是有误差的。
我们再通过另一种方法估算误差。从例子中可知,对于3.14的单精度浮点数,我们舍去了第24位以及之后,它们是:
0.00...(23个0)....00 [10001111.....]×21b 。
为了方便计算,不妨假设此后全是0(即方括号中省略部分),也就是舍去了:
0.10001111b×2-23×21b
约为0.00000013317912817001;由于舍入进位关系,给第23位又加了1,所以加了:2-23×21,故而要减去这一部分。
所以,误差约为2-23×21- 0.10001111b×2-23×21=0.00000010523945093155。所以结果大致为3.14+0.00000010523945093155= 3.14000010523945093155 。
可见和上面计算结果大致相同。
机器ε表示1与大于1的最小浮点数之差。不同精度定义的机器ε不同。以双精度为例,双精度表示的1是:
而比1大的最小双精度浮点数是:
从正规化中可知,无论如何浮点数都满足最左边是1。这就有一个严重问题:0没有办法被表示。为此,可以使用非正规化的表示方法,即让最左边默认为0,这样再另尾数也全部为0,就可以表示0了。
新的问题又来了:根据什么判断是非正规化还是正规化呢?
答案就是通过指数部分来反映。记得前面说过,双精度浮点数中,指数加移码的范围可以从0到2047,然而0和2047是作为他用的。在这里,指数部分为0就代表着非正规化。
所以,当见到指数部分为0是,尾数部分就不再是 1.bbbbb... 而是 0.bbbbb... 了。
再进一步,对于非正规化,可以看成是正规化中,小数点向左边跑了一位:1.bbbb....×2-1023=0.1bbbb....×2×2-1023==0.1bbbb....×2-1022(只是概念上理解,小数第一位也不一定非要是1,如 0.001010×2^-1022 也可)。所以,非正规化下表示为:
现在,0就可以表示了。值得注意的是,此时0可以表示位+0和-0。
因为它的最左边不是1是0,实际上可以表示更小的数。双精度浮点数下,使用非正规化可以表示的最小的正数是0.00......01×2-1022也就是2-52×2-1022=2-1074。
请注意这个最小数和前面提到的机器ε的区别。比机器ε小的数是可以被表示出来的(利用非正规化)。但是当它们与其他浮点数做运算时,因为要转成同一种格式(正规化格式),从而可能会因为溢出位而被舍弃。最终结果就是,这些更小的数尽管能被表示,但是对运算结果没有影响。
上面说到,在双精度浮点数中,指数为0表示非正规化,那么指数为2047(二进制是111 1111 1111b,即11位指数位全为1)就表示无穷大和NaN(Not a Number)。具体表现在,当指数是2047,当尾数,全为0就表示无穷大,当尾数不全为0就表示NaN。
以52位尾数位的双精度浮点数为例,舍入时需要重点参考第53位:
由于存在这种舍入规则,浮点数一般在机器内都不会以原数精确相等的存储,这就会使在某些情况下,使用浮点数做算术运算时出现令人费解的情况,如在JavaScript中(数以双精度存储):
可见机器表示中,9.4-9-0.4不严格等于0,其结果有极小误差。因为按照上面的算法可知,9.4在机器内被表示为:9.4+0.2×2-49,而0.4被表示为0.4+0.1×2-52。这样,当9.4-9时(因为9是整数是可以精确存储的)得0.4+0.2×2-49,再减去0.4+0.1×2-52得3×2-53,约等于"0.00000000000000033307"。