C++ float数据精度丢失问题

将float、double转换为字符过程中可能存在精度损失,但是通过%.8lf可以规避
(1)float小数点前后加起来有效数字只有6位当给定的float有效数在6位以内转换为字符不会丢失精度,当有效位数大于6位就会存在精度丢失
    //精度没有丢失
    char buf[100]={'\0'};
    float aa=8000.25;
    sprintf(buf,"%f",aa);   //8000.250000
    //精度没有丢失
    char buf[100]={'\0'};
    floataa=8.00025;
    sprintf(buf,"%f",aa);   buf = 8.000250
    //精度丢失,存在误差
    charbuf[100]={'\0'};
    float aa=8000.251;
    sprintf(buf,"%f",aa);  //8000.250977
    //精度丢失,存在误差此时使用.8lf也无效
    char buf[100]={'\0'};
    float aa=8000.251;
    sprintf(buf,"%.8lf",aa);//8000.25097656
    (2)double小数前后加起来的有效数字只有16位,当给定的double有效数在16位以内转换为字符串不会丢失精度,当有效位数大于16位就会存在精度丢失
    存在误差
    char buf[100]={'\0'};
    double aa=121.437565871234012;
    sprintf(buf,"%.20lf",aa);//121.43756587123401000000
    //没有误差
    char buf[100]={'\0'};
    double aa=8000.256165;
    sprintf(buf,"%.8lf",aa);
    std::cout<<buf<<std::endl; //8000.25616500

3、浮点数比较

用"=="来比较两个double应该相等类型,返回真值完全是不确定的计算机对浮点数的进行计算的原理是只保证必要精度内正确即可。

我们在判断点数相等时,推荐用范围来确定,若x在某一范围内,我们就认为相等,至于范围怎么定义,要看实际情况而已了,float,和double 各有不同
    所以const float EPSINON = 0.00001;
    if((x >= - EPSINON) && (x <= EPSINON) 这样判断是可取的至于为什么取0.00001,可以自己按实际情况定义。

    也可以 abs(x) <= EPSINON

比如要判断点数floatA和B是否相等,我们先令float  x = A –B ;

并设const float EPSINON = 0.00001;  则

if ((x >= - EPSINON)&& (x <= EPSINON);//或者if(abs(x) <= EPSINON)

cout<<”A 与B相等<<endl; else cout<<”不相等”<<endl;

根据上面分析建议在系统开发过程中设计到字符转换建议采用double类型,精度设置为%.8lf即可,在比较点数十建议EPSINON= 0.00000001

 

误差累计的解决办法:

如下所示:

输出为382525,显然误差非常大。

float f = 0.1;
    float sum = 0;
    for( int i=0; i<4000000; i++)
    {
        sum += f;
    }

改进后输出为400001,将40W拆分成2K和2K,避免了大数与小数相加后产生的阶段误差,控制数据的有效数字在6位以内。

float f = 0.1;
    float sum = 0;
    for( int i=0; i<2000; i++)
    {
        float tmp_sum =0;
        for (int j = 0;j<2000;j++){
            tmp_sum+=f;
        }
        sum += tmp_sum;
    }

参考:https://blog.csdn.net/wolf96/article/details/74907234

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值