C++編で扱っている C++ は 2003年に登場した C++03
という、とても古いバージョンのものです。C++ はその後、C++11 -> C++14
-> C++17 -> C++20 -> C++23 と更新されています。
なかでも C++11 での更新は非常に大きなものであり、これから C++
の学習を始めるのなら、C++11
よりも古いバージョンを対象にするべきではありません。特に事情がないなら、新しい
C++ を学んでください。 当サイトでは、C++14 をベースにした新C++編を作成中です。
要素が数値の配列やコンテナがあるとき、その要素の値の平均値を求めたいとします。
基本的にはやり方は1つで、合計を求めて、要素数で割るだけです。
合計を求める方法は、「合計を求める」で、要素数を求める方法は「要素数を求める」で説明していますから、それらの組み合わせで実現できます。
#include <iostream>
#include <list>
#include <numeric>
#define SIZE_OF_ARRAY(array) (sizeof(array)/sizeof(array[0]))
int main()
{
// 配列の例
int array[] = {0, 1, 2, 3, 4};
int arraySum = std::accumulate(array, array + SIZE_OF_ARRAY(array), 0);
int arrayAvg = arraySum / SIZE_OF_ARRAY(array);
std::cout << arrayAvg << std::endl;
// std;;list の例
std::list<int> lst(array, array + SIZE_OF_ARRAY(array));
int lstSum = std::accumulate(lst.begin(), lst.end(), 0);
int lstAvg = lstSum / lst.size();
std::cout << lstAvg << std::endl;
}
実行結果:
2
2
実戦的には、ゼロ除算にならないように注意する必要があります。このサンプルプログラムでは、「lst.size()」が 0 を返す可能性を考慮しなければなりません。
なお、整数型の値の平均値を、実数で得たい場合は、double型などで計算を行う必要があります。
double arrayAvg = static_cast<double>(arraySum) / SIZE_OF_ARRAY(array);
次に、関数化することを考えます。配列やコンテナに適用できるように、STLアルゴリズムの形を真似て作ってみます。
#include <cassert>
#include <iostream>
#include <iterator>
#include <list>
#include <numeric>
#define SIZE_OF_ARRAY(array) (sizeof(array)/sizeof(array[0]))
namespace {
template <typename R, typename T>
inline R average(const T begin, const T end, std::size_t n)
{
assert(n >= 0);
return static_cast<R>(std::accumulate(begin, end, 0)) / n;
}
}
int main()
{
// 配列の例
int array[] = {1, 2, 4, 5, 9};
std::cout << average<double>(array, array + SIZE_OF_ARRAY(array), SIZE_OF_ARRAY(array))
<< std::endl;
// std;;list の例
std::list<int> lst(array, array + SIZE_OF_ARRAY(array));
std::cout << average<double>(lst.begin(), lst.end(), lst.size())
<< std::endl;
}
実行結果:
4.2
4.2
2つのイテレータと、要素数を渡す形になっています。また、1つ目のテンプレート仮引数が、戻り値の型を表しており、整数型の値の平均値を、実数で受け取るようなことにも対応できます。
要素数については、std::distance関数を使って算出できますが、イテレータのカテゴリ(【標準ライブラリ】第14章参照)が、ランダムアクセスイテレータでない場合(list の場合など)の効率面を考えると、素直に渡してあげた方が良いと思います。
新規作成。
Programming Place Plus のトップページへ
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
RSS | 管理者情報 | プライバシーポリシー |