减小float累加运算产生的误差

问题代码

float a = 0.f;
for(int i = 0; i < 10000; ++i){
	a += 0.01f;
}

输出a的值结果为:
输出结果:

可以看到结果存在0.002953的误差,这是因为float的精度问题,在多次运算绝对误差不断累加所导致的。

解决方法

方法一:分段累加

float a=0.f;
for(int i = 0; i < 100; ++i){
	float b = 0.f;
	for(int j = 0; j < 100; j++){
		b += 0.01f;
	}
	a += b;
}

采用这种方法输出a的值结果为99.999985,存在的误差为0.000015,比之前小了很多。减小相加两个浮点数之间的大小差距可以在一定程度上减少相加导致的误差。

方法二:贮存残留值

float a = 0.f;
float r = 0.f; //类积未加上的值
float t;
for(int i = 0; i < 10000; ++i){
   r += 0.01f; 
   t = a; 		//保存本次加法前的a值
   a += r; 		//执行本次加法
   t = a - t;	//本次加法中a实际增加的值
   r  =  r - t;		//理想a应增加的值 - 实际a增加的值 = 本次未加上的值
}

这个技巧初见比较不好理解,所以笔者基本每行代码都加了注释,用这个方法计算得到的a的值正正好为100,误差为0。
这个方法的核心就是用r记录每次加法后残留的没能加上的值,残留值在r中不断积累,最终在某次加法中成功加上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值