View Full Version : accumulate variant
mickey
23rd August 2008, 01:16
Hello,
could anyone explain me how do this below? I need to return the number of elements summed in way to do the mean. Is there anybody, please?
class Value {
public:
double _value;
bool _missed;
bool getMissed() const { return _missed; }
//other methods....
};
class Other {
vector<Value> _values;
static double sum_values(const double& accum, const Value& right) {
if ( right.getMissed() ) return accum;
return accum + right._value;
}
void computeMean() {
double mean = std::accumulate( _values.begin(), _values.end(), 0.0,
Other::sum_values );
}
};
caduel
23rd August 2008, 09:30
The code is basically correct (assuming that's just part of it).
(If it is supposed to be complete: Other is all private, the constructors are missing etc.)
When I add that missing stuff (hint: do not forget to initialize _missed) the variable mean is assigned a meaningful value (namely the sum of my Values).
What is the problem you're having?
mickey
23rd August 2008, 10:30
I need sum all "valid" values (exactly what it do) BUT I need to compute the "MEAN"; so I need to know how many "values" I've summed; how know how many they?
caduel
23rd August 2008, 10:54
ok... you can do that by either:
* counting those not _missed (and thus iterating twice over your vector)
* or, by using a function object that counts both values and missed
(* or you could use globals, which is very bad imho)
try to replace your function by
class MeanAccumulator
{
int counted_;
double sum_;
public:
MeanAccumulator() : counted_(0), sum_(0) {}
void operator() (const Value &right)
{
if ( right.getMissed() ) return;
++counted_;
sum_ += right._value;
}
double mean() const {return counted_ ? sum_/counted_ : 0; }
};
void computeMean() {
MeanAccumulator res = std::for_each( _values.begin(), _values.end(),
MeanAccumulator());
std::cerr << "sum="<<res.mean()<<std::endl;
}
Note that the function object passed into for_each does NOT get modified.
The resulting function object (with the updated state) is returned by for_each.
(I assumed you do not insist on using accumulate.)
HTH
mickey
23rd August 2008, 16:11
Hello,
I was looking something that permit me to do this with accumulate....I don't know how "algorithms" works, so I was thinking that there was some trick with bind1st or other......your for_each avoid me to write a for( ; ;).......
mickey
23rd August 2008, 23:09
Hello,
See this:
class Value {
public:
double _value;
bool _missed;
...................
};
class Feature {
static std::vector<Value, std::allocator<Value> >&
sum_vec(std::vector<Value, std::allocator<Value> >& v, const Value& right) {
if ( !right.getMissed() ) {
v.push_back(right);
}
return v;
}
......................................
};
//main.cpp
std::vector<Value, std::allocator<Value> > vVal;
vVal = std::accumulate( _values.begin(), _values.end(), vVal, Feature::sum_vec ); //1
_mean = std::accumulate( vVal.begin(), vVal.end() ) / vVal.size(); //2
//1 return vVal that is a new vector that contains only the values that must be summed; (and it is ok)
//2 doesn't compile, because seems vVal.begin() and vVal.end() are not good; Could anyone correct this, please?
However: this isn't the solution that I wanted; I must call 2 accumulate and push_back into a new vector;
I hope this can be a point to reach my aim
Regards,
caduel
24th August 2008, 12:56
Why don't you like the for_each version?
as an alternative (if you for some reason insist on using accumulate...):
you can use a structure (not just a double) to hold both the sum and the number of items counted...
something like the following (untested and uncompiled)
struct mean_helper
{
mean_helper() : count(0), sum(0) {}
int count;
double sum;
};
static mean_helper sum_and_count(mean_helper h, const Value &right)
{
if (! right.getMissed())
{
++h.count;
h.sum += right.value;
}
return h;
}
mean_helper helper = std::accumulate( _values.begin(), _values.end(), mean_helper(), sum_and_count );
_mean = helper.sum / helper.count;
HTH
vBulletin® v3.7.1, Copyright ©2000-2008, Jelsoft Enterprises Ltd.