c++ comparing two floating point values

前端 未结 5 1309
陌清茗
陌清茗 2020-12-30 15:58

I\'m wondering what is the difference for comparing two double between this two manner :

double a1 = ...;
double a2 = ....;
  1. fabs(a1-a
5条回答
  •  抹茶落季
    2020-12-30 16:23

    Epsilon varies according to the value inside the double range. If you want to use your own and fixed epsilon, I recommand to choose an epsilon for 1.

    fabs(a1-a2) < epsilon
    

    This is not perfect. If a1 and a2 are results from operations with small numbers, the epsilon would be small. If a1 and a2 are results from operations with big numbers, the epsilon would be big.

    fabs((a1-a2)/a2) < epsilon
    

    This is a bit better as you would like to scale epsilon by a2. However, there is a division by 0 if a2 equals 0.

    fabs(a1-a2) < fabs(a2)*epsilon
    

    This is a bit better. However, this is incorrect if a2 equals 0. fabs(a2)*epsilon would be equal to 0 and the comparison of two values a1=0.000000001 and a2=0 will always fail.

    fabs(a1-a2) < max(fabs(a1), fabs(a2))*epsilon
    

    This is a bit better. However, this is incorrect because epsilon is not proportional in continuous manner. With IEEE encoding, epsilon is proportional to a value in discrete manner on base 2.

    fabs(a1-a2) < 2^((int)log2(max(fabs(a1), fabs(a2)))*epsilon
    

    This looks correct for me when both a1 and a2 are not equal to 0.

    The implementation of a generic method could be:

    bool nearly_equal(double a1, double a2, double epsilon)
    {
      if (a1 == 0 && a2 == 0)
        return true;
    
      return std::abs(a1 - a2) < epsilon * pow (2.0, static_cast (std::log2(std::max(std::abs(a1), std::abs(a2)))));
    }
    

提交回复
热议问题