Question

After having gone through several articles on here and searching, there are many good solutions to comparing floating point numbers.

Such as the Boost library: http://www.boost.org/doc/libs/1_34_0/libs/test/doc/components/test_tools/floating_point_comparison.html

I have the Boost library available to me and so I want to use it. However, I am having trouble getting a simple example to show me how to get a boolean return value when comparing two floating point numbers.

For instance, they show examples like so: http://www.boost.org/doc/libs/1_50_0/libs/test/doc/html/utf/testing-tools/reference.html

But that doesn't return a boolean.

Psuedo code example:

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);

I'm just having trouble finding out how to get a bool back.

I had been working mostly in Java, Python, and Matlab for a few years, so C++ is kind of like a foreign language to me right now.

Please help!

Was it helpful?

Solution

You have to understand that what you have pointed to are boost unit test helper tools, so it may not be a good idea to rely on it outside of the testing domain.

And as a side note, in many cases simply comparing the floating point numbers to be within an epsilon of absolute distance (eg 1e-6) suffices. Otherwise, sure, the relative distance with respect to the magnitude of the comparands is necessary – when more precision is required.

But that doesn't return a boolean

Yes it returns boost::test_tools::predicate_result but you can evaluate and convert it to a boolean.

Notwithstanding the comment on boost test tools, if you do prefer to use the test library in the way you mentioned, here’s an example for you:

#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
}

And if you need to implement the simpler comparison, you can always roll your own, along the lines of:

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

OTHER TIPS

Can be done with no library/header dependency:

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

This is how I do it outside the test domain. It is lightweight and efficient as well as easy to implement and use.

polonium's answer can be improved so that you get a useful diagnostic when the comparison fails:

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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top