使用Boost浮点比较来获得bool返回值

时间:2014-02-19 00:13:20

标签: c++ boost floating-point boost-test

在这里阅读了几篇文章并进行搜索之后,有很多很好的解决方案来比较浮点数。

如Boost库: http://www.boost.org/doc/libs/1_34_0/libs/test/doc/components/test_tools/floating_point_comparison.html

我可以使用Boost库,所以我想使用它。 但是,在比较两个浮点数时,我无法通过一个简单的示例向我展示如何获取布尔返回值。

例如,他们展示了这样的例子: http://www.boost.org/doc/libs/1_50_0/libs/test/doc/html/utf/testing-tools/reference.html

但是这不会返回布尔值。

Psuedo代码示例:

double a = 1.0;
double b = 0.5+0.5;
double percentage = 0.00001; //0.001 %
//Now I want to use the boost library to do something like this:
bool isClose = check_is_close(a, b, percentage);

我很难找到如何让布尔回来。

我已经在Java,Python和Matlab工作了几年,所以C ++现在对我来说就像是一门外语。

请帮忙!

3 个答案:

答案 0 :(得分:2)

可以在没有库/头依赖的情况下完成:

inline bool is_close(double a, double b, double tolerance = 1e-5)
{ 
    return (a - b) * (a - b) < tolerance * tolerance;
}

这是我在测试域之外的方式。它重量轻,效率高,易于实施和使用。

答案 1 :(得分:1)

你必须明白你所指出的是升压单元测试辅助工具,所以在测试域之外依赖它可能不是一个好主意。

作为旁注,在许多情况下,简单地将浮点数与绝对距离的epsilon(例如1e-6)进行比较就足够了。否则,当需要更高精度时,相对于比较的大小的相对距离是必要的。

  

但是这不会返回布尔值

是的,它会返回boost::test_tools::predicate_result,但您可以评估并将其转换为布尔值。

尽管有关于增强测试工具的评论,如果你更喜欢按照你提到的方式使用测试库,这里有一个例子:

#include <iostream>
#include <boost/test/floating_point_comparison.hpp>

int main() {
    bool b = boost::test_tools::check_is_close(
        0.01, 0.015, boost::test_tools::percent_tolerance(49.0));
    std::cout << std::boolalpha << b << std::endl; // false

    b = boost::test_tools::check_is_close(
        0.01, 0.015, boost::test_tools::percent_tolerance(51.0));
    std::cout << std::boolalpha << b << std::endl; // true, 51% tolerance is enough to ignore the difference
}

如果您需要实施更简单的比较,您可以按照以下方式自行推广:

#include <cmath>
bool is_close(double a, double b, double epsilon = 1e-5) { 
    return std::fabs(a - b) < epsilon; 
}

答案 2 :(得分:1)

可以改进pol的答案,以便在比较失败时获得有用的诊断:

template <typename Number>
inline boost::test_tools::predicate_result isClose(Number a, Number b, Number tolerance = Number(1e-5))
{
    if ((a-b)*(a-b) < tolerance*tolerance)
    {
        return true;
    }

    boost::test_tools::predicate_result result(false);
    result.message() << a << " != " << b << " within " << tolerance;
    return result;
}