一个有关C语言浮点数保留2位小数的操蛋问题

本文探讨了在C语言中处理浮点数时遇到的精度问题,特别是12.105这类数字在保留两位小数时出现误差的情况。通过递归计算10的指数和调整四舍五入方法,提出了一种解决方案,但指出该方法可能因编译器差异导致不同结果。核心思想是利用乘以100消除部分误差,然后通过加0.5和取整来实现保留小数位。
摘要由CSDN通过智能技术生成

问题描述:

   12.105这种浮点数,被保存后有误差,导致在使用printf保留两位小数时成了12.10.

未评估解决方案:

 

float Power10(unsigned int i)       //递归计算10的i次幂
{
if(i)
{
  float tRes = Power10(i>>1);
  return tRes * ( (i & 0x1)? tRes * 10.0f : tRes );      //i转化二进制逻辑尺使用
}
else
{
  return 1.0f;       //递归终结,10的0次幂为1
}
}

float ResX(float a, int x)
{
float tPower10 = Power10(x);
if(a < 0)
{
  tPower10 = -tPower10;       //如果是负数,添个负号
}
a = (a * tPower10) + 0.5f;  //负数会先被正过来
return (int)a / tPower10;  //最后再负回去
}

调用ResX(a, x)四舍五入保留a的x位小数。

这个法子不是很妥,不同的编译环境有可能出现不同的结果,待验。

 

原理上就是把12.1049999……先乘以100,变成1210.5。为什么后面的误差消失了?因为0.5在2进制表示时刚好是无误差的。

然后加上0.5再取整:1211,再除以100就搞定了。


a = (a * tPower10) + 0.5f;

return (int)a / tPower10; 

这里之所以不直接return (int)(a*tPower10 + 0.5f) / tPower10;

是因为大多编译器的浮点寄存器是double甚至更高精度的,不存回到a这个float里,误差就会被保留下来,而不会是一个完美的0.5

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值