我有一个作业要读取一个文件并输出平均测试分数。
这很简单,但我不喜欢现有计算平均分的方法。
average = (test1 + test2 + test3 + test4 + test5) / 5.0;
有没有办法让它只除以测试分数的数量?我在书或谷歌上都找不到类似的东西。就像这样:
average = (test + test + test + test) / ntests;
我有一个作业要读取一个文件并输出平均测试分数。
这很简单,但我不喜欢现有计算平均分的方法。
average = (test1 + test2 + test3 + test4 + test5) / 5.0;
有没有办法让它只除以测试分数的数量?我在书或谷歌上都找不到类似的东西。就像这样:
average = (test + test + test + test) / ntests;
如果你的值存储在向量或数组中,只需使用来自<numeric>
的std::accumulate
:
std::vector<double> vec;
// ... fill vec with values (do not use 0; use 0.0)
double average = std::accumulate(vec.begin(), vec.end(), 0.0) / vec.size();
vec.size()
的值足够大或者vec
中存在大量级的值,考虑在累加之前使用std::transform
将每个值除以vec.size()
,作为更稳定的数值解决方案。 - jwm想知道为什么没有人提到boost::accumulators
。它不是已经发布的解决方案中最短的,但可以更容易地扩展到更一般的统计值,如标准差或更高阶矩。
#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <algorithm>
#include <vector>
double mean(const std::vector<double>& values) {
namespace bo = boost::accumulators;
if (values.empty()) return 0.;
bo::accumulator_set<double, bo::stats<bo::tag::mean>> acc;
acc=std::for_each(values.begin(), values.end(), acc);
return bo::mean(acc);
}
int main()
{
std::vector<double> test = { 2.,6.,4.,7. };
std::cout << "Mean: " << mean(test) << std::endl;
std::cout << "Mean: " << mean({}) << std::endl;
return 0;
}
这是我关于如何通过指定一个lambda函数获取每个值并将它们加起来来计算容器元素平均值的概括:
template <typename ForwardIterator, typename F>
double inline averageOf (ForwardIterator first, ForwardIterator last, F function) {
std::vector<typename std::result_of<F(typename ForwardIterator::value_type)>::type> values;
while (first != last) {
values.emplace_back (function(*first));
++first;
}
return static_cast<double>(std::accumulate (values.begin(), values.end(), 0)) / values.size();
}
我测试过的客户端代码如下:
const std::list<CharmedObserver*> devotees =
charmer->getState<CharmerStateBase>(CHARMER)->getDevotees();
const int averageHitPointsOfDevotees = averageOf (devotees.begin(), devotees.end(),
[](const CharmedObserver* x)->int {return x->getCharmedBeing()->getHitPoints();});
C++11提供了很好的解决方案:
constexpr auto countArguments() -> size_t
{
return 0;
}
template<class T1, class ... Ti>
constexpr auto countArguments(T1, Ti ...xi) -> size_t
{
return 1 + countArguments(xi...);
}
template<class T>
constexpr auto sumAruguments(T x) -> double
{
return x;
}
template<class T1, class ... Ti>
constexpr auto sumAruguments(T1 x1, Ti ...xi) -> double // decltype(x1 + sumAruguments(xi...))
{
return x1 + sumAruguments(xi...);
}
template<class...T>
constexpr auto avarage(T...xi) -> double
{
return sumAruguments(xi...) / countArguments(xi...);
}
我无法编写它以使其自动推断返回类型。
当我尝试时,average(-2)
的结果很奇怪。
int
参数列表,平均值也应该是浮点类型,并且在现代硬件上通常应该是 double
。 - jwm您还可以使用可变数量的参数来计算平均值。这个函数的原理是将未知数量的参数存储在堆栈中,然后我们可以取出它们。
double average(int n, ...) // where n - count of argument (number)
{
int *p = &n; // get pointer on list of number in stack
p++; // get first number
double *pp = (double *)p; // transformation of the pointer type
double sum = 0;
for ( int i = 0; i < n; pp++, i++ ) //looking all stack
sum+=(*pp); // summarize
return sum/n; //return average
}
你可以这样使用这个函数:
double av1 = average( 5, 3.0, 1.5, 5.0, 1.0, 2.0 );
double av2 = average( 2, 3.0, 1.5 );
但是参数的数量必须与 n 匹配。