2012-02-17 140 views
21

我有一个任务来读取文件并输出平均测试分数。如何在C++中获得平均值?

这很简单,但我不喜欢如何平均完成。

average = (test1 + test2 + test3 + test4 + test5)/5.0; 

有没有办法让它除以测试分数?我在书中或谷歌找不到这样的东西。像

average = (test + test + test + test)/ntests; 
+0

如果不知道,直到你读取输入的测试次数,你需要一个循环做的* N *数的平均值。 – FrustratedWithFormsDesigner 2012-02-17 19:23:53

+1

步骤0:将其移至堆栈溢出。在这里脱离主题。 – 2012-02-17 19:27:32

+4

优秀的问题和出色的观察。硬编码'5'是a)魔术,b)多余。 – 2012-02-17 19:46:04

回答

43

如果你有一个向量或数组中的值,只需使用std::accumulate<numeric>

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

详细说明@RiaD的说法:当你用C(++)分割整数时,它默认只使用整数运算 - 例如除法结果被截断,小数点后没有数据。如果你的数据集的值足够大,那么这个问题不会太大,但是当处理较小的数字时,你不想失去这个精度,这可能导致0.75变成一个单位0. – 2013-04-26 16:43:41

+0

Shouldn'这是一个'0'。而不是'0'?因为如果您将范围(-0.5,0.5)中的数字相加,没有点将保持为零。 – ikku100 2015-06-29 06:27:09

3

步骤1.通过迭代(如果你想完成)或递归(如果你想成为勇敢)将所有的考试成绩到一个数组(如果你想简单和速度),或一个链接的东西列表(如果你想要灵活性,但速度很慢)

第2步。遍历数组/列表直到达到最终;随时添加每个单元格/节点的内容。继续计数当前所在的细胞/节点。

第3步。取第一个变量的总和除以第二个变量,它跟踪你的位置。这将产生平均值。

+0

链接列表不太可能有用。它可能会使得建立这个列表的效率稍微高一些(但是如果你像大多数'vector's一样过度分配,分摊的复杂性是相同的),但是它会使得总结和找到更复杂的长度,并且1/3是一个漂亮的坏分数。 – delnan 2012-02-17 19:28:31

+2

这完全是我的头。我几乎只知道cin cout和其他一些东西。 – 2012-02-17 19:31:55

+0

@Jordan然后,这将提供一个很好的机会,比你知道的多一点。数组或列表和迭代是所有计算机语言的基础 - 越早学习它们越好。 – Caleb 2012-02-17 19:38:37

1

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

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

+5

请注意此代码。它不保证p按照您的期望工作,因为您依赖于实现细节。至少在64位机器上,有些参数是通过参数传递的,这些代码不起作用。要正确实施,请查看va_start和co。同样在C++ 11中,也有可用的可变模板。 – MJD 2012-02-18 06:43:23

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

想知道,为什么没有人提到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; 
} 
0

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