我有一个标准库容器,里面有大量的数字,如果我把它们加在一起,它们可能会导致溢出。让我们假设它是这个容器:
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
?
6条答案
按热度按时间r8uurelv1#
你不应该使用integer来存储结果:
传递给函数accumulate的返回类型:
T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );
依赖于第三个参数类型:(T init)所以你必须在这里写:0.0得到结果为double。368yc8dk2#
这可能不会很好地舍入,但即使容器上没有
size()
方法,它也可以工作:这利用了C14的一个新特性,*initialized capture *,在lambda中存储状态。(你可以通过捕获一个额外的局部变量来做同样的事情,但是它的作用域是局部作用域,而不是lambda的生命周期。对于较旧的C版本,您自然可以将
count
放在struct
的成员变量中,并将lambda主体作为其operator()()
实现。为了防止舍入误差的累积(或至少显著地减少它),可以做如下操作:
1bqhqjot3#
你的运行“average”是lambda的第一个参数,所以下面是正确的。
mf98qq944#
您正在使用的三个lambda函数不符合标准。
这里使用的参数a在给定时间点将平均值带到向量的特定索引。例如,当“B”的值为1时,“a”的值为0。0,当'B'在那一刻变成2时,它应该是'0。那么很清楚,在任何情况下,“a”都不需要被v除。size(),每次调用lambda函数。
在上述情况下使用正确的lambda函数
这里我们通过引用捕获,因为我们需要v的值。size(),如果预先知道,则可以预先传递向量的大小值
工作程序为
附注:'iota'用于以递增的方式初始化一个范围,这里它初始化从1到10的向量
nzkunb0c5#
我还没有见过这个解决方案,它不需要传递向量的大小,因为已经用
v.begin()
,v.end()
控制了范围:它可以通过用
std::distance(start,end)
替换v.size()
来进一步改进。zvms9eto6#
显然你不需要去这些长度,但你可以创建一个简单的“统计计算器”
你的lambda怎么样在迭代之前创建StatsCalculator示例。然后
然后迭代:
当然你也可以要求均值和方差的元组。