0

There is container with numbers and it needs to find if there is a number in container that is equal to a query value within a given tolerance. Is there a way to implement it with similar to find_if method passing for comparison e.g. bool areEqual(double a, double b, double eps)?

3
  • Are the contents of the container sorted? Commented Mar 1, 2013 at 7:26
  • something like ?en.cppreference.com/w/cpp/algorithm/find_first_of Commented Mar 1, 2013 at 7:27
  • no the contents are not sorted Commented Mar 1, 2013 at 7:28

3 Answers 3

4

If you can use C++11:

bool areEqual(double a, double b, double eps) { return abs(a - b) < eps; } int main(int argc, char * argv[]) { std::vector<double> myvector; myvector.push_back(1.0); myvector.push_back(0.0); myvector.push_back(2.0); double eps = std::numeric_limits<double>::epsilon(); double value = 0.0; std::vector<double>::iterator it = std::find_if (myvector.begin(), myvector.end(), [=](double d) -> bool { return areEqual(d, value, eps); }); if (it != myvector.end()) printf("Found value: %f\n", *it); } 
Sign up to request clarification or add additional context in comments.

4 Comments

Uh, I'm inclined to disagree, std::numeric_limits<double>::epsilon() doesn't seem to be a good tolerance for comparing arbitrary doubles.
@us2012 It depends on what values you are trying to compare. In my case it should work. Otherwise, anoter epsilon value should be chosen. I used std::numeric_limits<double>::epsilon() only for demonstration purposes.
is it possible to call areEqual from lambda expression rather than duplicating function contents?
@ChesnokovYuriy Sure, modified the example.
3

you can bind the 2nd and 3rd parameter:

std::find_if( c.begin(), c.end(), boost::bind( &areEqual, _1, number, eps ) ); 

also C++11 std::bind should do the trick

11 Comments

If you don't want to use Boost, you can also use std::tr1::bind which is present and older compilers as well (I know it ships with GCC 4.1.2).
Also, I am not sure if this actually works. Don't you have to adapt the result of bind in order to use it with standard algorithms (because it is missing the required typedefs)? See here.
In C++11, prefer Lambdas over bind, for clarity and readability.
yes, I would not like to use boost. what is the logic for std::bind?
@ChesnokovYuriy then use a lambda that just calls that function: [=](double a){ return areEqual(a, number, eps); } does the same as the bind in the answer.
|
3
struct CompareFuzzy{ CompareFuzzy(double qVal, double tolerance = 0.0f):m_tolerance(tolerance),m_qVal(qVal){} bool operator()(double a) {return std::abs( a-qVal ) < m_tolerance;} private: double m_tolerance , m_qVal; } std::find_if(container.begin(),container.end(),CompareFuzzy(5.0, 0.5)); 

Use an old-school functor, as shown above, or lambda if you use C++11.

6 Comments

I think it needs to pass a reference to container instead of a single qVal. Since we have a container to find a value inside
I understood the logic. value to find is passed to constructor and all values from container are passed in () operator
@ChesnokovYuriy I would term it as each, instead of all, but yes that is it. This i essentially a < C++11 method of doing what the lamda that others have shown does.
you may use class instead of struct and inherit from unary_function<double, bool>
@ChesnokovYuriy you can, maybe unnecessary though, unless you need it.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.