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++編を作成中です。
この章の概要です。
この章では、STLアルゴリズムの中から、数値演算を行うものを取り上げます。
ただし、実のところ、数値演算だけに特化しているとは限りません。たとえば、accumulate関数は +演算子を使うことによって合計を求めているので、+演算子によって連結を意味する std::string のような型を対象にすれば、数値演算以外の意味で使うことが可能です。
なお、数値演算の STLアルゴリズムは、<algorithm> ではなく、<numeric> という標準ヘッダに含まれています。
accumulate関数は、指定した範囲内の要素の合計を計算します。
namespace std {
template <typename InputIterator, typename T>
(InputIterator first, InputIterator last, T init);
T accumulate
template <typename InputIterator, typename T, typename BinaryOperation>
(InputIterator first, InputIterator last, T init, BinaryOperation binary_op);
T accumulate}
第1、2引数で指定した範囲内の要素の合計を求めます。第3引数は初期値として機能します。戻り値は、結果(合計)を返します。
1つ目の形式では、合計を +演算子を使って計算します。具体的には、各要素(elem) について「init = init + elem」を行います。
#include <numeric>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v
std::cout << std::accumulate(v.begin(), v.end(), 0) << std::endl;
}
実行結果:
10
2つ目の形式では、第4引数に指定した関数や関数オブジェクトを使って計算します。
#include <numeric>
#include <iostream>
#include <vector>
#include <functional>
int main()
{
std::vector<int> v;
.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v
std::cout << std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>()) << std::endl;
}
実行結果:
120
std::multiplies は、標準で用意されている関数オブジェクトです。std::multiplies が呼び出されると、2つの引数に *演算子を適用した結果を返します。
標準の関数オブジェクトについては、第26章で取り上げます。
inner_product関数は、指定した2つの範囲内の要素の内積を計算します。
namespace std {
template <typename InputIterator1, typename InputIterator2, typename T>
(InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, T init);
T inner_product
template <typename InputIterator1, typename InputIterator2, typename T, typename BinaryOperation1, typename BinaryOperation2>
(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);
T inner_product}
第1、2引数で1つ目の範囲を指定し、第3引数でもう1つの範囲の先頭の位置を指定します。第4引数は初期値として機能します。戻り値は、結果(合計)を返します。
1つ目の形式では、*演算子を使って計算します。具体的には、1つ目の範囲の各要素(elem1) と、2つ目の範囲の各要素(elem2) について、「init = init + elem1 * elem2」を行います。つまり、2つの要素の積の合計ということになります。
#include <numeric>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v
std::cout << std::inner_product(v.begin(), v.end(), v.begin(), 0) << std::endl;
}
実行結果:
30
2つ目の形式では、第5引数(op1) と第6引数(op2) に指定した関数や関数オブジェクトを使って、「init = op1(init, op2(elem1, elem2))」という計算を行います。
#include <numeric>
#include <iostream>
#include <vector>
#include <functional>
int main()
{
std::vector<int> v;
.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v
std::cout << std::inner_product(v.begin(), v.end(), v.begin(), 1, std::multiplies<int>(), std::plus<int>()) << std::endl;
}
実行結果:
3840
std::multiplies や std::plus は、標準で用意されている関数オブジェクトです。std::multiplies が呼び出されると、2つの引数に *演算子を適用した結果を返し、std::plus の方は、+演算子を適用した結果を返します。
標準の関数オブジェクトについては、第26章で取り上げます。
partial_sum関数は、指定した範囲内の要素の部分和を計算します。
namespace std {
template <typename InputIterator, typename OutputIterator>
(InputIterator first, InputIterator last, OutputIterator result);
OutputIterator partial_sum
template <typename InputIterator, typename OutputIterator, typename BinaryOperation>
(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);
OutputIterator partial_sum}
第1、2引数で指定した範囲内の要素を先頭から順に調べ、そこまでの和を、第3引数の範囲へ出力します。つまり、1つ目の範囲の要素を elem0、elem1、elem2・・・とすると、2つ目の範囲には、次の値が出力されます。[elem0, elem0 + elem1, elem0 + elem1 + elem2, ・・・」
和の計算には、1つ目の形式では +演算子が使われ、2つ目の形式では第4引数の関数や関数オブジェクトが使われます。
戻り値は、最後に出力された要素を指すイテレータです。
#include <numeric>
#include <iostream>
#include <vector>
#include <algorithm>
namespace {
void Println(int elem)
{
std::cout << elem << std::endl;
}
}
int main()
{
std::vector<int> v;
.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v
std::vector<int> result(v.size());
std::partial_sum(v.begin(), v.end(), result.begin());
std::for_each(result.begin(), result.end(), Println);
}
実行結果:
1
3
6
10
15
adjacent_difference関数は、指定した範囲内の要素の階差を計算します。
namespace std {
template <typename InputIterator, typename OutputIterator>
(InputIterator first, InputIterator last, OutputIterator result);
OutputIterator adjacent_difference
template <typename InputIterator, typename OutputIterator, typename BinaryOperation>
(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);
OutputIterator adjacent_difference}
第1、2引数で指定した範囲内の要素を先頭から順に調べ、手前の要素との差を、第3引数の範囲へ出力します。つまり、1つ目の範囲の要素を elem0、elem1、elem2・・・とすると、2つ目の範囲には、次の値が出力されます。[elem0, elem1 - elem0, elem2 - elem1, ・・・」
差の計算には、1つ目の形式では -演算子が使われ、2つ目の形式では第4引数の関数や関数オブジェクトが使われます。
戻り値は、最後に出力された要素を指すイテレータです。
#include <numeric>
#include <iostream>
#include <vector>
#include <algorithm>
namespace {
void Println(int elem)
{
std::cout << elem << std::endl;
}
}
int main()
{
std::vector<int> v;
.push_back(1);
v.push_back(3);
v.push_back(6);
v.push_back(10);
v.push_back(15);
v
std::vector<int> result(v.size());
std::adjacent_difference(v.begin(), v.end(), result.begin());
std::for_each(result.begin(), result.end(), Println);
}
実行結果:
1
2
3
4
5
問題① accumulate関数を使って、指定範囲内の std::string の連結を行えることを確認してください。
問題② accumulate関数を使って、指定範囲内の std::string の長さの合計を求める処理を作成してください。
コンパイラの対応状況について、対応している場合は明記しない方針にした。
clang 3.7 (Xcode 7.3) を、Xcode 8.3.3 に置き換え。
VisualC++ 2017 に対応。
新規作成。
前の章へ (第23章 ソートされた範囲を扱う STLアルゴリズム)
Programming Place Plus のトップページへ
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
RSS | 管理者情報 | プライバシーポリシー |