How can I use std::accumulate and a lambda to calculate a mean?
You shouldn't use integer to store the result:
The return type passed to the function accumulate:
T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );
depends on the third parameter type: (T init) so you have to put there: 0.0 to get result as double.
#include <vector>
#include <algorithm>
#include <iostream>
#include <numeric>
using namespace std;
std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int main()
{
auto lambda = [&](double a, double b){return a + b / v.size(); };
std::cout << std::accumulate(v.begin(), v.end(), 0.0, lambda) << std::endl;
}
This may not round quite as nicely, but it works even when there's no size()
method on the container:
auto lambda = [count = 0](double a, int b) mutable { return a + (b-a)/++count; };
This takes advantage of a new C++14 features, initialized captures, to store state within the lambda. (You can do the same thing via capture of an extra local variable, but then its scope is local scope, rather than lifetime of the lambda.) For older C++ versions, you naturally can just put the count
in the member variable of a struct
and put the lambda body as its operator()()
implementation.
To prevent accumulation of rounding error (or at least dramatically reduce it), one can do something like:
auto lambda = [count = 0, error = 0.0](double a, int b) mutable {
const double desired_change = (b-a-error)/++count;
const double newa = a + (desired_change + error);
const double actual_change = newa - a;
error += desired_change - actual_change;
return newa;
};