PDA

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