64位浮点数_浮点数误差

ed6de6d1db02d8db33938394224b9ed5.png
chopper:目录​zhuanlan.zhihu.com

本篇文章通过解析浮点数精度格式,分析为什么浮点数会出现误差,并提供了减少浮点数运算误差要尽量遵循的原则。

在计算机中,小数有两种表示方式:定点数和浮点数。小数点隐含在某一个固定位置上的数据,就称为定点数。为了能正确的表示定点数,我们必需规定数据的位数和小数点的位置,以8位的数据为例,规定低3位是小数位,则一个定点数

。定点表示法较为简单,但它表示的数据非常有限,无法表示数值很大的数据和数值很小的数据。为了表示更大范围的数据,数学上通常采用科学计数法,把数据表示成一个小数乘以一个以10为底的指数,例如,太阳的质量
克。科学计数法改写为
,把有效数字
和以10底的指数
存储在机器中的固定单元内,就可以表示出数值如此大的数据,如果指数是一个负数,例如
,则表示的数据的数值非常小。像这样,把一个数的有效数字和指数部分在计算机中分别予以表示,就是浮点表示法。这种表示法,相当于数的小数点位置随比例因子的不同而在一定范围内自由浮动,改变指数部分的数值相当于改变小数点的位置。

IEEE 754标准[4,5]是由1985年[1]引入的浮点数算术标准,是最广泛使用的浮点数运算标准,在2008年[2]对该标准进行了修改。

a43dacbf446dfe67238e2c1155d47c17.png
图1. 单精度和双精度浮点数的存储格式

IEEE 754标准规定的单精度和双精度浮点数的存储格式如图1.1所示,最高位是符号位

,规定浮点数的正负;偏置指数
,紧跟在符号位之后,占
位;有效数字
在最后,占
位。IEEE 754规定偏置指数
保留,用于表示
。通过与偏置量的差来表示实际的指数值,规定偏置量
,则可以表示的最小的指数值为
,可以表示的最大的指数值为
,有效数字
的二进制表示形式为
。对于单精度和双精度表示中,不同的参数如表1所示:

3ad65b7505df8e91a192ccc78b2df5fd.png
表2. 单精度和双精度浮点数格式的参数表

浮点数的数值可以用三元组

表示,
,不同数据的浮点数表示的数值
分别如下所示:
  1. ,则
    ,称该浮点数为正规数;
  2. ,则
    (无论
    为0或1);
  3. ,则
  4. ,则
    ,称该浮点数为非正规数;
  5. ,则

以单精度浮点数为例,单精度编码和对应的数值如表2所示:

71eef121648c9524f5e5f1f7a8cd19fe.png
表2. 单精度的位模式和对应的数值

例如,将数“-7.5”用单精度浮点数的二进制表示,它的转化过程如下所示:

9058b2a006d30afde5f89d19eb5ecd4a.png

数“-7.5”的二进制浮点数表示为

为了方便理解,设浮点数的底数为

,有3个有效数字,
。存在两个浮点数
,则
太小,无法用一个正规数表示,如果不存在非正规数,那么
将被舍入为0。由于
,但是
,这显然就是错误的,因此IEEE 754标准规定,当
时,浮点数的数值为
,增加了非正规数。如图2所示,非正规数弥补了数轴上区间
内的数,显然,绝对值越小的数,能精确表示的概率越大。

f3ac7626891a124dfbe85459d77559d2.png
图2. 浮点数在数轴上的分布

浮点数表示的数据范围比定点数更广泛,但它并不能精确的表示在最大数和最小数之间的所有实数,例如无理数

,有理数
。IEEE 754定义了四种舍入模式(Rounding Mode):(1)向最接近的可表示的值舍入,当有两个最接近的可表示的值时首选“偶数”值;2)向负无穷大舍入;3)向正无穷大舍入;4)向0截断。以十进制数为例,不同的数采用四种舍入模式得到的结果如表3所示。在最接近舍入模式中,当存在两个最接近的表示的值时,Reiser& Knuth[6,7]解释了为什么首选“偶数”而不是“奇数”。

3635ed22dc54b3678aad82f8a4f52c7a.png
表3. 不同的浮点数采用不同的舍入模式

浮点数不仅在实数的表示上存在误差,在数值运算上也存在误差。为了方便理解,设浮点数的底数为10,有3个有效数字。计算

,则先进行指数对齐,得到:

如果对两个绝对值差别很大的两个数作加减操作,就会出现上述所示的“大数吃小数”的现象。被消除的小数

,就是本次运算的误差值。用尾数最后位(units in the last, ulp)来作为衡量误差的单位,例如,四位有效数的数值,
。两个数值运算的误差表示为
,符号
表示对两个数值进行 (加、减、乘、除)运算得到的估计值,则有
*
*
,IEEE 754标准可以保证
*
[6,8,9]。为了降低浮点数的运算误差,引入保护位(guard bit)、舍入位(round bit)和粘贴位(sticky bit),额外添加的位能有效的降低运算误差[5,6]。

此外,由于浮点数范围的局限,如果两个特别大(小)的数相乘或除以一个特别小(大)的数,就可能造成上(下)溢,这也是误差的一个来源。

在运算过程中,重复利用上一次浮点运算的结果,可能造成误差的累加。例如,计算多项式

,如果先计算
,再计算
,最后计算
,共有3次运算的叠加,叠加的次数越多,可能造成的误差也将越大。

在设计算法的时候,必需在精度和速度做好一定的权衡,可以采用32位的浮点数,具有更快的速度、更少的内存,也可能采用64位的双精度,具有更高的精度,但是需要更多的内存,速度也会有所降低。在涉及浮点数的算法中,尽量遵循下面几个原则,尽可能的减少由于浮点数造成的错误,或者减少误差:

1.避免相近的两数相减

例如a1 = 0.12345,a2 = 0.12346,各有5位有效数字,而 a2 - a1 = 0.00001,只剩下1位有效数字,容易造成相对误差增大,严重影响最终计算精度。

2.避免小分母

例如单精度浮点数,阶码表示的范围是-126~127,分母过小,分母和分子的阶码叠加,可能造成浮点数的溢出

3.避免大数吃小数

在浮点运算中,要对阶操作,否则可能造成小数有效数字溢出,影响结果。举个例子,为了解释的方便,假设计算机采用十进制表示:

存为
,1存为
,做加法时,两加数的指数先向大指数对齐,即对阶操作,再将浮点部分相加。即1的指数部分须变为
,则
,取单精度时就成为
,产生大数吃小数的结果。

4.简化计算步骤

减少运算次数(运算量),避免误差积累。

参考

[1] IEEE. "IEEE Standard for Binary Floating-Point Arithmetic."

[2] Dan Zuras, et al. "IEEE standard for floating-point arithmetic." IEEE Std 754-2008, pp.1-70, 2008.

[3] Christer Ericson. Real-time collision detection. Amsterdam/Boston: Elsevier, 2005.

[4] James M. Van Verth, and Lars M. Bishop. Essential Mathematics for Games and Interactive Applications: A Programmer's Guide. CRC Press, 2008.

[5] David A. Patterson, and John L. Hennessy. Computer organization and design: the hardware/software interface. Newnes, 2013.

[6] David Goldberg. "What every computer scientist should know about floating-point arithmetic." ACM Computing Surveys (CSUR), vol.23, no.1. pp.5-48, 1991.

[7] John F. Reiser, and Donald E. Knuth. "Evading the drift in floating-point addition." Information Processing Letters, vol.3, no.3, pp.84-87, 1975.

[8] Jonathan Richard Shewchuk. "Adaptive precision floating-point arithmetic and fast robust geometric predicates." Discrete & Computational Geometry, vol.18, no.3, pp.305-363, 1997.

[9] Johnathan Richard Shewchuk. "Robust adaptive floating-point geometric predicates." Proceedings of the twelfth annual symposium on Computational geometry, ACM, 1996.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值