浮点数float累加误差分析与解决

1.  浮点数IEEE 754表示方法

要搞清楚float累加为什么会产生误差,必须先大致理解float在机器里怎么存储的,具体的表示参考[1] 和 [2], 这里只介绍一下组成

由上图可知(摘在[2]), 浮点数由: 符号位 + 指数位 + 尾数部分, 三部分组成。由于机器中都是由二进制存储的,那么一个10进制的小数如何表示成二进制。例如: 8.25转成二进制为1000.01, 这是因为 1000.01 = 1*2^3 + 0*2^2 + 0*2^1 + 0*2^0 + 0*2^-1 + 2*2^-2 = 1000.01.

(2)float的有效位数是6-7位,这是为什么呢?因为位数部分只有23位,所以最小的精度为1*2^-23 在10^-6和10^-7之间,接近10^-7,
[3]中也有解释

那么为什么float累加会产生误差呢,主要原因在于两个浮点数累加的过程。

2. 两个浮点数相加的过程

两浮点数X,Y进行加减运算时,必须按以下几步执行(可参考 [4] 中插图):

(1)对阶,使两数的小数点位置对齐,小的阶码向大的阶码看齐。

(2)尾数求和,将对阶后的两尾数按定点加减运算规则求和(差)。

(3)规格化,为增加有效数字的位数,提高运算精度,必须将求和(差)后的尾数规格化。

(4)舍入,为提高精度,要考虑尾数右移时丢失的数值位。

(5)判断结果,即判断结果是否溢出。

关键就在与对阶这一步骤,由于float的有效位数只有7位有效数字,如果一个大数和一个小数相加时,会产生很大的误差,因为尾数得截掉好多位。例如:

123 + 0.00023456 = 1.23*10^2 + 0.000002 * 10^2 = 123.0002

那么此时就会产生0.00003456的误差,如果累加多次,则误差就会进一步加大。

那么怎么解决这种误差呢?

3. 误差解决的方法

(1)Kahan summation算法,具体解释和实现参考 [5][6]

(2)使用double类型进行计算,由于double类型的有效数字有15~16位,一般情况下产生误差可以接受。

Reference

[1] IEEE 754: floating point in modern computers

[2] C++中,float double区别

[3] How to Calculate Double + Float Precision

[4] 浮点加减法的运算步骤

[5] Kahan summation algorithm

[6] Kahan Summation

浮点数float累加误差分析与解决,布布扣,bubuko.com

时间: 2024-09-29 09:46:35

浮点数float累加误差分析与解决的相关文章

浮点数float累加误差解决方式总结

首先是float累加产生误差的原因,该部分转自:http://blog.csdn.net/zhrh0096/article/details/38589067 1.  浮点数IEEE 754表示方法 要搞清楚float累加为什么会产生误差,必须先大致理解float在机器里怎么存储的,具体的表示参考[1] 和 [2], 这里只介绍一下组成 由上图可知(摘在[2]), 浮点数由: 符号位 + 指数位 + 尾数部分, 三部分组成.由于机器中都是由二进制存储的,那么一个10进制的小数如何表示成二进制.例如

【javascript】浮点数运算问题分析及解决方法

问题: 在用 js 进行小数四则运算时发现了一个重大问题,比如:0.7 * 0.8 = 0.5599999999999999 分析: 在 js 中只有一种数字类型 Number,而且在 js 中所有的数字都是以 IEEE-754 标准格式表示的.浮点数的精度问题并不是 js 特有的,因为有些小数以二进制表示位数是无穷的,比如 1.1,其程序实际上无法真正的表示 1.1,而只能做到一定程度上的准确(1.09999999999999999),这是无法避免的精度丢失. 通过 chrome 控制台,我们

CSS中右对齐float:right换行的解决办法

问题:同时使用float:left 和right的时候不在同一水平线上 第一种解决办法:把左右对换,比如把日期放在标题的前面,对调下位置就好了. 第二种解决办法:给右边也加上float:right 浮动不正常的(不在同一行,换行了,仅仅因为多了一个 ,从而导致整个排版混乱): 浮动正常的1:(第一种解决办法:去掉 ) 浮动正常的2:(第二种解决办法:从 起再套一层span,并设定float:right;) CSS中右对齐float:right换行的解决办法,布布扣,bubuko.com

Java浮点数float和double精确计算的精度误差问题总结

1.float整数计算误差 案例:会员积分字段采用float类型,导致计算会员积分时,7位整数的数据计算结果出现误差. 原因:超出float精度范围,无法精确计算. float和double的精度是由尾数的位数来决定的.浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响. float:2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字: double:2^5

危险的浮点数float

今天写程序又以为我见鬼了!最后查出来发现原来又是浮点数搞的鬼! 情况大致是这样的,我想要测试向量运算的速度,所以要对一个浮点数向量进行求和运算,代码如下: int vect_size=100000000; vector<float> vect1(vect_size,0.1); float sum=0; for(int i=0;i<vect1.size();++i){ sum+=vect1[i]; } printf("%f\n",sum); 10^8个0.1求和,地球人

Java 浮点数 float或double类型的表示范围和精度

隐约记得,浮点数判断大小好像有陷阱,因为底层的二进制数不能精确表示所有的小数.有时候会产生让人觉得莫名其妙的事情. 如在java中, 0.99999999f==1f //true 0.9f==1f //false 要明白这些,首先要搞清楚float和double在内存结构 1.内存结构 float和double的范围是由指数的位数来决定的. float的指数位有8位,而double的指数位有11位,分布如下: float: 1bit(符号位) 8bits(指数位) 23bits(尾数位) dou

IE6/IE7浏览器中&quot;float: right&quot;自动换行的解决方法

在项目中,调试IE6/IE7,发现一个bug,那就是:在同一个div包裹着,几个块级元素并列为一行的情况下,设置了float:right的块级元素会自动换行: 代码如下: <p> <span>版权所有</span> <span style="float=right;"> <a href="#">申请入驻</a> <a href="#">申请合作</a>

css float塌陷问题的解决

css float 造成的塌陷问题 的解决 <div> <div style="width:300px;height:300px;float:left;'></div> <div style="width:300px;height:300px;float:left;"></div> </div> 这种情况下会出现浮动导致的塌陷问题 如何解决这种问题? 以下介绍三种方法来解决这种问题 first 在父元素最

IEEE浮点数float、double的存储结构

众所周知,C的float.VB的Single都是32位浮点数变量类型(也叫单精度浮点数),C的double和VB的Double则都是64位的浮点数变量类型(也叫双精度浮点数).有些编译器还支持更屌的long double(貌似是80位还是128位的我不清楚,总之存在这种变态玩意儿.)那么这些浮点数从最底层的角度来看,它们是怎么存储的呢?我来举个例子解释下.计算机用的是二进制,如果我用二进制跟大家解释大家可能觉得看不懂,那我就用十进制来跟大家解释.浮点数分三个部分,第一个部分是有效数字,第二个部分