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

How can I use std::accumulate and a lambda to calculate a mean?

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

std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

我想计算这个容器的平均值,使用 std::accumulate,但我无法将所有数字相加。我会用 v[0]/v.size() + v[1]/v.size() + ... 来计算它。所以我设置:

auto lambda = ...;
std::cout << std::accumulate(v.begin(), v.end(), 0, lambda) << std::endl;

这是我目前尝试过的,其中 -> 表示输出:

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

如何生成正确的均值以使输出为 5

您的 运行 "average" 是 lambda 的第一个参数,因此以下是正确的。

lambda = [&](int a, int b){return a + b/v.size();};

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

传递给函数的return类型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;
}

这可能不太圆润,但即使在容器上没有 size() 方法时它也能工作:

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

这利用了新的 C++14 功能,初始化捕获,在 lambda 中存储状态。 (你可以通过捕获一个额外的局部变量来做同样的事情,但是它的作用域是局部作用域,而不是 lambda 的生命周期。)对于旧的 C++ 版本,你自然可以将 count 放在成员中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;
};

您使用的三个 lambda 函数不合格。

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

这里使用的参数 a 在 time.For 的给定点处携带向量的特定索引的平均值,实例 'a' 的值当 'b' 的值为 1 时0.0,当'b'在那一瞬间变为2时,它应该是'0.1'。 那么很明显,在任何情况下,每次调用 lambda 函数时,'a' 都不需要除以 v.size()。

针对上述情况使用正确的 lambda 函数

lambda = [&](double x,double y){return x+y/v.size();}

这里我们通过引用捕获只是因为我们需要v.size()的值,向量大小的值如果事先知道可以预先传递

工作程序是

    #include<iostream>
    #include<numeric>
    #include<vector>
    using namespace std;

    int main(){
        vector<int> v(10);
        iota(v.begin(),v.end(),1);
        double x=accumulate(v.begin(),v.end(),0.0,[&](double x,double y) {return x+y/v.size();});
        cout << x << endl;
    }

P.S : 'iota'用于以递增的方式初始化一个范围,这里它初始化向量从1到10

我还没有看到这个不需要传递向量大小的解决方案 因为已经用 v.begin()v.end():

控制了范围
double mean = accumulate(v.begin(), v.end(), 0., [](double x, double y) { return x+y; }) / v.size();

v.size() 替换为 std::distance(start,end) 可以进一步改进。