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)
?
Asked
Active
Viewed 272 times
0

Chesnokov Yuriy
- 1,760
- 5
- 21
- 35
-
Are the contents of the container sorted? – jogojapan Mar 01 '13 at 07:26
-
something like ?http://en.cppreference.com/w/cpp/algorithm/find_first_of – billz Mar 01 '13 at 07:27
-
no the contents are not sorted – Chesnokov Yuriy Mar 01 '13 at 07:28
3 Answers
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);
}

Spook
- 25,318
- 18
- 90
- 167
-
2Uh, I'm inclined to disagree, `std::numeric_limits
::epsilon()` doesn't seem to be a good tolerance for comparing arbitrary doubles. – us2012 Mar 01 '13 at 07:30 -
@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
::epsilon()` only for demonstration purposes. – Spook Mar 01 '13 at 07:32 -
is it possible to call areEqual from lambda expression rather than duplicating function contents? – Chesnokov Yuriy Mar 01 '13 at 07:40
-
1
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.

Karthik T
- 31,456
- 5
- 68
- 87
-
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 Mar 01 '13 at 08:02
-
I understood the logic. value to find is passed to constructor and all values from container are passed in () operator – Chesnokov Yuriy Mar 01 '13 at 08:21
-
1@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. – Karthik T Mar 01 '13 at 08:24
-
you may use class instead of struct and inherit from unary_function
– Chesnokov Yuriy Mar 01 '13 at 08:31 -
@ChesnokovYuriy you can, maybe unnecessary though, unless you need it. – Karthik T Mar 01 '13 at 08:37
-
yes, it is not necessary to inherit. however in the literature they suggested to inherit from either unary_function or from binary_function – Chesnokov Yuriy Mar 01 '13 at 08:44
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

StilesCrisis
- 15,972
- 4
- 39
- 62

Maciek B
- 394
- 1
- 7
-
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 Mar 01 '13 at 07:37
-
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](http://www.boost.org/doc/libs/release/libs/bind/bind.html#err_modeling_stl_function_object_concepts). – Björn Pollex Mar 01 '13 at 07:38
-
-
yes, I would not like to use boost. what is the logic for std::bind? – Chesnokov Yuriy Mar 01 '13 at 07:38
-
there is a comparison function already defined. it would be superfluous to move its contents to lambda expression – Chesnokov Yuriy Mar 01 '13 at 07:39
-
@BjörnPollex standard algorithms need no typedefs on the predicat/comparator function objects you pass them. They just copy and call what ever you throw in. – Arne Mertz Mar 01 '13 at 07:40
-
1@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. – Arne Mertz Mar 01 '13 at 07:43
-
@ArneMertz: You are right - the typedefs are only required for composing functors. – Björn Pollex Mar 01 '13 at 07:44
-
@ChesnokovYuriy std::bind is just standardized boost::bind pulled in to c++11 standard. The syntax is almost the same – Maciek B Mar 01 '13 at 07:48
-
A bit more on lambdas vs. bind can be found here: http://stackoverflow.com/questions/1930903/bind-vs-lambda – Arne Mertz Mar 01 '13 at 08:03
-
std::find_if(c.begin(), c.end(), bind(&areEqual,_1,number,eps)); ? – Chesnokov Yuriy Mar 01 '13 at 08:04