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)?
- Are the contents of the container sorted?jogojapan– jogojapan2013-03-01 07:26:16 +00:00Commented Mar 1, 2013 at 7:26
- something like ?en.cppreference.com/w/cpp/algorithm/find_first_ofbillz– billz2013-03-01 07:27:01 +00:00Commented Mar 1, 2013 at 7:27
- no the contents are not sortedChesnokov Yuriy– Chesnokov Yuriy2013-03-01 07:28:27 +00:00Commented Mar 1, 2013 at 7:28
Add a comment |
3 Answers
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); } 4 Comments
us2012
Uh, I'm inclined to disagree,
std::numeric_limits<double>::epsilon() doesn't seem to be a good tolerance for comparing arbitrary doubles.Spook
@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.Chesnokov Yuriy
is it possible to call areEqual from lambda expression rather than duplicating function contents?
Spook
@ChesnokovYuriy Sure, modified the example.
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
Björn Pollex
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).Björn Pollex
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.Arne Mertz
In C++11, prefer Lambdas over bind, for clarity and readability.
Chesnokov Yuriy
yes, I would not like to use boost. what is the logic for std::bind?
Arne Mertz
@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. |
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
Chesnokov Yuriy
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
Chesnokov Yuriy
I understood the logic. value to find is passed to constructor and all values from container are passed in () operator
Karthik T
@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.Chesnokov Yuriy
you may use class instead of struct and inherit from unary_function<double, bool>
Karthik T
@ChesnokovYuriy you can, maybe unnecessary though, unless you need it.
|