LoginSignup
32
26

More than 5 years have passed since last update.

std::valarrayの使い方

Posted at

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::accumulatestd::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
32
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
26