我如何使用std :: accumulate和lambda来计算平均值?

EMB*_*LEM 19 c++ lambda accumulate

我有一个大数字的标准库容器,如果我将它们加在一起它们可能会导致溢出.让我们假装它是这个容器:

std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Run Code Online (Sandbox Code Playgroud)

我想用std :: accumulate来计算这个容器的平均值,但我不能将所有数字加在一起.我只是计算它v[0]/v.size() + v[1]/v.size() + ....所以我设置:

auto lambda = ...;
std::cout << std::accumulate(v.begin(), v.end(), 0, lambda) << std::endl;
Run Code Online (Sandbox Code Playgroud)

这是我到目前为止所尝试的,其中->表示输出:

lambda = [&](int a, int b){return (a + b)/v.size();};  ->  1
lambda = [&](int a, int b){return a/v.size() + b/v.size();};  ->  1
lambda = [&](int a, int b){return a/v.size() + b;};  ->  10
Run Code Online (Sandbox Code Playgroud)

我怎样才能产生正确的平均值,以便输出5

Ada*_*amF 18

您不应该使用整数来存储结果:

传递给函数accumulate的返回类型:
T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );取决于第三个参数类型:(T init)所以你必须放在那里:0.0将结果作为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;
}
Run Code Online (Sandbox Code Playgroud)


Ben*_*igt 7

这可能不会很好地圆,但即使size()容器上没有方法,它也可以工作:

auto lambda = [count = 0](double a, int b) mutable { return a + (b-a)/++count; };
Run Code Online (Sandbox Code Playgroud)

这利用了新的C++ 14特性,初始化捕获,以在lambda中存储状态.(你可以通过捕获一个额外的局部变量来做同样的事情,但是它的范围是局部范围,而不是lambda的生命周期.)对于较旧的C++版本,你自然可以只放入counta的成员变量struct并放置lambda体作为它的operator()()实现.

为了防止累积误差(或至少大幅减少它),可以做类似的事情:

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;
};
Run Code Online (Sandbox Code Playgroud)