浮点数精度问题及使用场合


最近一段时间,对于单精度浮点数float和双精度浮点数double的使用场合突然有了疑问。我们都知道在计算机内部浮点数是采用二进制标示的,可以参见下图:

  • sign:符号位
  • exponent:指数为
  • fraction:有效数字

bg2010060601.png

基于这样一个事实:大部分小数是无法精确表示的,导致精度是偶然的,误差是必然的。比如0.1这个数,根据十进制小数转换为二进制小数的规则。

0.1×2=0.2 整数位是0,表示为0.0
0.2×2=0.4 整数位是0,表示为0.00
0.4×2=0.8 整数位是0,表示为0.000
0.8×2=1.6 整数位是1,表示为0.0001
0.6×2=1.2 整数位是1,表示为0.0 0011 从此出现了类似除法的循环0011
0.2×2=0.4 整数位是0,表示为0.000110
0.4×2=0.8 整数位是0,表示为0.0001100
0.8×2=1.6 整数位是1,表示为0.00011001
0.6×2=1.2 整数位是1,表示为0.00011 0011

也是就用有限位无法表示此数,根据上述运算过程,也同样无法表示0.2,0.4,0.6,0.8,而0.3×2=0.6,0.7×2=1.4,0.9×2=1.8也同样陷入了循环之中,所以在0.1~0.9这九个数中只有0.5是可以完全表示的,其他的只能是近似表示。

得出上述结论后,那么,现代计算机的二进制浮点数表示还有什么意义呢,我们平常在编程过程中,是否还该使用这种方法吗?难道我们就只能避免误差累积吗?


更新: 要表示的数的误差很小,在上面图中的 23 位有效数字中,最大表示误差是 2e-23,所以在简单运算场合还是可用的。现在想知道那些场合是不可用的?


更新: 上面图中,有效数字fraction有23位,实际中比如1.1100101的第一位总是1所以不用存储,因此可以认为有效数字的有效位有24位,如果用此32位浮点数存储一个整数的话,那么这个整数的最大值在十进制的6~7位,当要表示的数字大于6~7位时,剩余的位就表示不下,造成误差较大。因此,如果使用单精度浮点型,最好数字不要太大1W以内比较好,超过这个数量级请用双精度浮点型。

计算机原理 浮点数

苍空翼Nayi 11 years, 11 months ago

要表示的数的误差很小,在上面图中的23位 有效数字 中,最大表示误差是2e-23,所以在简单运算场合还是可用的。现在想知道那些场合是不可用的?

冷泉麻子酱 answered 11 years, 11 months ago

你说的都没错,不是2的幂次的多项式和的数都无法精确表示。
可怎么会没有意义?要不然你想让计算机怎么表示小数?
通常4字节的float或者8字节的double已经在日常生活中够用
更高精度的浮点运算不同的语言一般会有相应的库,但是相应的运算速度会慢很多

永远的清风 answered 11 years, 11 months ago

Mithril answered 11 years, 11 months ago

Your Answer