zoukankan      html  css  js  c++  java
  • 浮点数的比较

    转贴一文章,供大家参考

    浮点数的比较 
    在数学运算当中经常会涉及到判断两个数是否相等的情况
    对于整数很好处理 A==B这样的一个语句就可以解决全部的问题
    但是对于浮点数是不同的

    首先,浮点数在计算机当中的二进制表达方式就决定了大多数浮点数都是无法精确的表达的
    现在的计算机大部分都是数字计算机,不是模拟机,数字机的离散化的数据表示方法自然无法精确表达大部分的数据量的。

    其次计算机浮点数的精度在单精度float类型下,只有7位,在进行浮点运算的时候,这个精度往往会导致运算的结果和实际期望的结果之间有误差

    因为前两个原因,我们很难用 A==B来判定两个浮点数是否相同

    很自然,我们可以想到  fabs(A-B) < epsilon 这样的一种判别方法
    但是这种判别方法稳妥吗?
    它也不稳妥。

    首先, epsilon是一个绝对的数据,也就是误差分析当中说说的绝对误差
    使用一个固定的数值,对于float类型可以表达的整个数域来说是不可以的
    比如epsilon取值为0.0001,而a和b的数值大小也是0.0001附近的,那么显然不合适
    另外对于a和b大小是10000这样的数据的时候,它也不合适,因为10000和10001也可以认为是相等的呢
    适合它的情况只是a或者b在1或者0附近的时候

    既然绝对误差不可以,那么自然的我们就会想到了相对误差
    bool IsEqual(float a, float b, float relError ) {
           return ( fabs ( (a-b)/a ) < relError ) ? true : false; 
    }
    这样写还不完善,因为是拿固定的第一个参数做比较的,那么在调用
    IsEqual(a, b, relError ) 和 IsEqual(b, a, relError ) 的时候,可能得到不同的结果
    同时如果第一个参数是0的话,就有可能是除0溢出
    这个可以改造
    把除数选取为a和b当中绝对数值较大的即可 
    bool IsEqual(float a, float b, relError )
    {
          if (fabs(a)<fabs(b)) return  ( fabs((a-b)/a) > relError ) ? true : false;
          return  (fabs( (a-b)/b) > relError ) ? true : false;
    };

    使用相对误差就很完善吗? 
    也不是, 在某些特殊情况下, 相对误差也不能代表全部
    比如在判断空间三点是否共线的时候,使用判断点到另外两个点形成的线段的距离的方法的时候
    只用相对误差是不够的,应为线段距离可能很段,也可能很长,点到线段的距离,以及线段的长度做综合比较的时候,需要相对误差和绝对误差结合的方式才可以
    相对完整的比较算法应该如下:
    bool IsEqual(float a, float b, float absError, float relError )
    {
             if (a==b) return true;
            if (fabs(a-b)<absError ) return true;
            if (fabs(a>b) return  (fabs((a-b)/a>relError ) ? true : false;
           return  (fabs((a-b)/b>relError ) ? true : false;
    }
    这样才相对完整

    四舍五入:如果对小数点后2位 可以用   (int)(a*100+0.5)/100.
  • 相关阅读:
    linux下mysql的root密码忘记解决方法
    基于NIO2的遍历文件夹简单复制
    bootstrap插件bootstrapValidator常用验证规则总结
    《程序员修炼之道》-读书笔记六-工厂模式下的伪DI依赖注入
    cpu 突增问题排查
    一次线上OOM 的定位
    熔断、限流、降级的区别
    Mac 下 idea 在同一个窗口下打开多个项目
    No operations allowed after connection closed
    java 死锁演示
  • 原文地址:https://www.cnblogs.com/CKboss/p/3351130.html
Copyright © 2011-2022 走看看