浮点数累加的方法

 运行下述代码段:

double value = 99999999.99; 
double sum   = 0.0; 
for(int i=0;i<8192;i++) 
{ 
  sum += value; // 错误的浮点累加方法


printf("%18.2lf", sum); // 819199999918.02  --wrong

运行结果,sum是错误的, 和正确值相差0.06(99999999.99 * 8192 = 819199999918.08),对于报表之类的高精度的项目数据统计,这是不能容忍的,循环越多误差越大。解决方法之一,可以用高精度算法库来代替,比如doubledouble类型,或选择微软的解决方法:本意是,浮点相加硬件实现是减法。把加法改成减法,把误差也计算进去。

上述代码修改后:

double value = 99999999.99; 
double sum   = 0.0; 
double C=0, Y, T;
for(int i=0;i<8192;i++) 
{ 
  Y = value - C;
  T = sum + Y;
  C = T - sum - Y; // 正确的浮点累加方法,做减法。
  sum = T;

printf("%18.2lf", sum);// 819199999918.08  --correct

加了误差累计,这样结果就正确了。还有浮点运算法则最重要一点,是不符合实数算法相同的代数规则。 (sum+Y)-sum-Y ,结果是不等于零的。

 

参考:

http://msdn.microsoft.com/en-us/library/aa289157(VS.71).aspx

http://msdn.microsoft.com/en-us/library/aa289157(VS.71).aspx

http://www.cppblog.com/foxriver/archive/2009/02/28/75136.html

http://en.wikipedia.org/wiki/Compensated_summation

http://blog.csdn.net/l1t/article/details/122777

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值