过去有一种很普遍的说法是单精度浮点数的有效数字是6到7位。同时也有一个很普遍的问题就是:“6到7位是什么意思?到底是6位还是7位?”。现在似乎主流认知已经变成了单精度浮点数的有效数字就是7位。事实究竟是怎么样的?
先说结论
单精度浮点数可以保证7位10进制有效数字。如果一个数字用10进制表示时有效数字位数大于等于7位,那么用单精度浮点数记录的话,能确保至少正确记录前7位。
为什么说“至少”?比如,4294967296有10位10进制有效数字,但只有1位2进制有效数字(2进制表示是1后面32个0)。我们可以验证单精度浮点数是可以正确记录所有10位有效数字的。但上面只是特殊情况,对于随便给出的一个数,只有第7位和之前的有效数字是能确信正确的。
凭什么说就是7位,为什么不是6位、8位?
最简单的2进制的情况
首先,我假设我们知道一个单精度浮点数种有24位2进制的有效数字(不知道的同学,请先自行搜索IEEE 754
)。很显然,对于有24位或者以上2进制有效数字的数,单精度浮点数能保证前24位。
再看看16进制
我们知道16进制的1位对应2进制的4位(不知道的同学,……姑且4位2进制数刚好有16种不同的情况)。2进制的24位刚好对应16进制的6位,也就是能保证6位16进制的有效数字。
但是假设我们只有23位2进制有效数字的话,那么我们就只能保证5位了。
接下来我们更具体地看一下。假设有16进制数 8765432 1 ( 16 ) 87654321_{(16)} 87654321(16),我们可以写成 8.765432 1 ( 16 ) × 1 6 7 8.7654321_{(16)} \times 16^7 8.7654321(16)×167。2进制的话,可以写成 1000.011 1 ′ 011 0 ′ 010 1 ′ 010 0 ′ 001 1 ′ 001 0 ′ 000 1 ( 2 ) × 2 28 1000.0111'0110'0101'0100'0011'0010'0001_{(2)} \times 2^{28} 1000.0111′0110′0101′0100′0011′0010′0001(2)×228如果我们只有24位2进制有效数字,则后面一部分有效数字无法记录,就成了 1000.011 1 ′ 011 0 ′ 010 1 ′ 010 0 ′ 001 1 ( 2 ) × 2 28 1000.0111'0110'0101'0100'0011_{(2)} \times 2^{28} 1000.0111′0110′0101′0100′0011(2)×2