std::valarrayの使い方
C++で可変長配列を扱う時によく使うのがstd::vectorだが、intやdoubleなどの数値に限っては数値配列専用のstd::valarrayがある。便利なメンバ関数や演算子が定義されていて、シンプルに書くことが出来る。
また、速度についてもstd::vectorよりも優位という話もある。(参考: .Regenschauer 雑記帳)
以下でstd::valarrayの使い方をstd::vectorと比較しながら示す.
実行環境: Visual C++ 14 (Visual studio 2015)
インクルード
ヘッダーをインクルードするだけで良い.
# include <vector>//std::vector
# include <valarray>//std::valarray
初期化
初期化リストで初期化
std::vector
, std::valarray
ともに初期化リストで初期できる.
//std::vector
std::vector<double> vector = { 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0 };
//std::valarray
std::valarray<double> varray = { 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0 };
要素数と同一の初期値して初期化
要素数と初期値で初期化が可能だが,std::valarray
だけ順序が逆なので注意.
//std::vector
std::vector<double> vector(10, 0.0);
//std::valarray
std::valarray<double> varray(0.0, 10);//初期値,要素数の順.
繰り返し処理
範囲for文
std::vector
, std::valarray
ともに範囲for文(Range-based for loop)を使うことができる.
//std::vector
for (auto& v : vector)
{
//処理...
std::cout << v << std::endl;
}
//std::valarray
for (auto& v : varray)
{
//処理...
std::cout << v << std::endl;
}
for_each,std::transformの使用
std::valarray
でも,std::for_each
, std::transform
を使うことができる.
ただし,std::valarray
ではbegin()
とend()
がメンバ関数ではないので,std::begin()
, std::end()
を使う.
std::for_each(vector.begin(), vector.end(), [](auto x) {std::cout << x << std::endl; });
std::for_each(std::begin(varray), std::end(varray), [](auto x) {std::cout << x << std::endl; });//std::begin(), std::end()を使う.
また,std::valarrayにはapply()というメンバ関数が用意されている.
//std::vector
std::transform(vector.begin(), vector.end(),vector.begin(), [](double v) {return v+1; });
//std::valarray
varray = varray.apply([](double v) {return v+1; });
配列同士の四則演算
例として,2つの配列の足し算を行う.
std::vector
では,std::transfrom
で行う.(参考: 学生時代に頑張ったことが何もない)
一方std::valarray
では,演算子が定義されているので+で書くことが出来る.
//std::vector
std::vector<double> vector1 = { 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0 };
std::vector<double> vector2 = { 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0 };
std::vector<double> vector3(vector1.size(),0.0);
std::transform(vector1.begin(), vector1.end(), vector2.begin(), vector3.begin(), std::plus<double>());
//std::valarray
std::valarray<double> varray1 = { 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0 };
std::valarray<double> varray2 = { 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0 };
std::valarray<double> varray3 = varray1 + varray2;
最大,最小,合計,平均,分散
最大,最小,合計
std::vector
ではstd::max_element
, std::min_element
, std::accumulate
を使って求めるが,
std::valarray
ではこれらがメンバ関数として用意されている.
//std::vector
auto max = *std::max_element(vector.begin(), vector.end());//9
auto min = *std::min_element(vector.begin(), vector.end());//0
auto sum = std::accumulate(vector.begin(), vector.end(), 0.0);//45
//std::valarray
auto max = varray.max();//9
auto min = varray.min();//0
auto sum = varray.sum();//45
平均,分散
要素の和と内積を使って平均と分散を求める.
std::vector
では,std::accumulate
やstd::inner_product
を使う.(参考: My Life as a Mock Quant)
std::varray
の方がメンバ関数や演算子でシンプルに書くことができる.
//std::vector
auto mean = std::accumulate(vector.begin(), vector.end(), 0.0) / vector.size();//4.5
auto var = (std::inner_product(vector.begin(), vector.end(), vector.begin(), 0.0) - mean * mean * vector.size() )/vector.size();//8.25
//std::valarray
auto mean = varray.sum() / varray.size();//4.5
auto var = ((varray*varray).sum() - mean*mean*varray.size()) / varray.size();//8.25