2012-02-17 5 views
21

私はファイルを読み、平均テストの得点を出力する課題を持っています。C++で平均を得るには?

かなりシンプルですが、私は平均がどのように行われているのが好きではありません。

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

テストスコアの数で除算する方法はありますか?私は本やGoogleからこのようなものを見つけることができませんでした。反復(あなたが行うことにしたい場合)、または再帰経由

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

テストの数は、あなたが入力を読むまで知られていない場合は、* N *数値の平均を行うためにループを必要とするだろう。 – FrustratedWithFormsDesigner

+1

ステップ0:これをスタックオーバーフローに移動します。ここでは話題にはならない。 –

+4

優れた質問と優れた観察。ハードコーディング '5'はa)魔法、b)冗長です。 –

答えて

43

あなたがベクトルまたは配列内の値を持っている場合は、単に<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(); 
+0

@RiaDが何を言っているかを詳しく述べてみましょう。C(++)で整数を分割すると、デフォルトでは整数の計算だけが使用されます。除算の結果は切り捨てられ、小数点以下のデータは残されません。データセットの値が十分大きい場合、それほど大きな問題ではありませんが、小さい数値を扱う場合は、その精度を失いたくない場合は、0.75がフラット0になります。 –

+0

Shouldn ' tは「0」である。 '0'の代わりに?ドットなしでは、範囲(-0.5、0.5)の数値を加算するとゼロのままになるからです。 – ikku100

3

ステップ1のようなもの(あなたは勇敢になりたい場合は)(あなたはシンプルさとスピードをしたい場合)配列にすべてのテストの点数を配置またはリンクされましたリスト(柔軟性はあるがゆっくりしたい場合)

ステップ2.最後に到達するまでアレイ/リストを繰り返します。それぞれのセル/ノードの内容を追加します。あなたが行っているときにあなたが現在いるセル/ノードの数を数え続けます。

ステップ3.最初の変数から合計を取り出し、それを2番目の変数で除算します。これにより平均値が得られます。

+0

リンクされたリストは有用ではありません。リストを少し効率的なものにすることができます(ただし、ほとんどの 'vector'sのように、余分に割り振ると償却された複雑さは同じですが)、合計を計算して長さを複雑にし、1/3がきれいです悪いスコア。 – delnan

+2

これは私の頭の中にかなりあります。私はちょうどシンドウといくつかのことを知っています。 –

+0

@Jordanこれはあなたが知っている以上のことを学ぶ絶好の機会を提供します。配列やリストと反復は、すべてのコンピュータ言語にとって基本的なものです。より早く学習すればするほどよいでしょう。 – Caleb

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を保証するものではありません。少なくとも64bitマシンでは、いくつかの引数が引数を渡されていましたが、このコードは機能しません。適切に実装するには、va_startとcoを見てください。また、C++ 11では、バリデーションテンプレートも使用できます。 – MJD

0

は、それぞれの値を取得してまで追加するラムダ関数を指定することで、コンテナの要素の平均値を得るための私の一般化である:

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