Help us understand the problem. What is going on with this article?

std::valarrayの使い方

More than 3 years have passed since last update.

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
vs4sh
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした