Domanda

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!

È stato utile?

Soluzione

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

Altri suggerimenti

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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top