和と積

C++ の話。配列やコンテナの値の総和を取りたい、けれど std::sum はない。ああ今日も車輪の再発明。

sum

sum は std::accumulate アルゴリズムをつかって実装できる。

template<typename InputIter, typename Type = typename std::iterator_traits<InputIter>::value_type>
inline auto sum(InputIter begin, InputIter end) -> Type {
	return std::accumulate(begin, end, Type(), std::plus<Type>());
}

見た目は恐ろしいけれど、入力イテレーターで半開区間の範囲 [begin, end) を受けとり、初期値 0 (を Type() で構築して)に足しこんでいく素直なつくり。
要素型 Type を std::iterator_traits 経由で取得しているところがポイント。

std::list<int> や std::vector<double> など各種コンテナに加えて配列にも使える。

int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, };
sum(std::begin(array), std::end(array)); // => 45

auto const&& vs = std::vector<double> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, };
sum(std::begin(vs), std::end(vs)); // => 45.0

product

同様にして要素の積も定義できる。(初期値を単位元 Type(1) で指定しているところが sum との違い)

template<typename InputIter, typename Type = typename std::iterator_traits<InputIter>::value_type>
inline auto product(InputIter begin, InputIter end) -> Type {
	return std::accumulate(begin, end, Type(1), std::multiplies<Type>());
}

補遺

C++ に零元と単位元を構築する標準関数があれば、と残念におもう。(とくに product の実装で初期値を 1 で指定するところがイケていない)

パフォーマンスは悪いが sum を bool コンテナに適用した場合は any (あるいは複数要素の or)のように動く。(パフォーマンスが悪いというのは、ふつうは非 false の値が出たところで計算を打ち切るところ、お尻まできっちり和を取る)
同様に product を bool コンテナに適用すると all (もしくは複数要素の and)として働く。(こちらも false が出たところで打ち切らない)

この記事が気に入ったらサポートをしてみませんか?