如何在C++中获得平均值

How to get an average in C++?

本文关键字:平均值 C++      更新时间:2023-10-16

我有一项任务要读取一个文件并输出平均测试成绩。

这很简单,但我不喜欢平均数的计算方式。

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();

步骤1。通过迭代(如果你想完成)或递归(如果你想要勇敢)将所有测试分数放入一个数组(如果你希望简单和快速)或一个链表(如果你需要灵活性但速度慢)

步骤2。遍历数组/列表,直到到达末尾;边走边添加每个单元格/节点的内容。同时,记下你当前所在的单元格/节点。

步骤3。取第一个变量的和,除以第二个变量,这个变量可以记录你在哪里。这将产生平均值。

想知道为什么没有人提到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)的奇怪结果。

https://wandbox.org/permlink/brssPjggn64lBGVq

您还可以使用可变数量的参数来计算平均值。这个函数的原理是将未知数量的参数存储在堆栈中,我们可以接受它们。

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相匹配。