std::valarray と NaN と max(), min(), sum()
標準C++ライブラリの std::valarray は、浮動小数点数型で NaN を含んでいると、メンバ関数 max(), min(), sum() の値が NaN になったりする。これは無論 valarray に限ったことではなく、std::vector だろうと配列だろうと、標準テンプレートライブラリ関数 std::max_element, std::min_element, std::accumulate を使えば同じく NaN になる。なお、C++の規格では NaN は必須ではないのでこの挙動は実装依存だが。しかし、NaN ではない要素の最大値、最小値、総和くらい取りたいではないか! 実は valarray ではそれが簡単にできる。
// NaN 以外の総和。ここで v は std::valarray<double> 型。 std::valarray<double>(v[v == v]).sum(); // NaN を含まない要素数 std::valarray<double>(v[v == v]).size(); // NaN の要素数 std::valarray<double>(v[v != v]).size();
ちなみに、NaN の置き換えもできる。
v[v != v] = 0.0; // NaN を 0 で置き換え。
NaN でなくても、比較演算子次第で任意の数値に対してこのような処理が可能。こういう簡潔さも valarray の魅力のひとつだけど…ただでさえマイナーな valarray の仕様を知らない人には伝わらなそう…なんて不憫な valarray たん…
GCCのSTL実装だと、開始イテレータが指す値がNaNでなければmax、min、std::max_element、std::min_elementは正しい値を返してくれる。