Stream Iterator

しばしば,実験データから何らかの統計値(平均,分散,...)を求めたい場合があります.今回も,RMSE(Root Mean Square Error:平均2乗平方根誤差)を求めなければならない場面に遭遇しました.それで,せっかくなので汎用的に使える関数として残しておこうと思い,以下のような関数を書きました.

template <class Type, class InputIterator, class ValueT>
Type mse(InputIterator first,
    const InputIterator& last, ValueT correct) {
    Type sum = 0;
    Type n = 0;
    while (first != last) {
        Type tmp = static_cast<Type>(*first++)
            - static_cast<Type>(correct);
        sum += std::pow(tmp, 2);
        n++;
    }
    return sum / n;
}

template <class Type, class InputIterator, class ValueT>
Type rmse(InputIterator first,
    const InputIterator& last, ValueT correct) {
    return std::sqrt(mse(first, last, correct));
}

使い方としては,rmse < test.datのようにデータファイルをリダイレクトで渡すような形を考えていました.それで,メインプログラムをどのような形で書こうかな,と.最初に思いついたのは,streambuf_iteratorを使う方法だったのですが,これだと一文字づつ読み込んでしまい(100 200 300の場合,'1', '0', '0', ' ', '2', ...)期待した動きをしてくれませんでした.しばらくWebを彷徨っていたところ,stream_iteratorを利用すればうまくいく模様(100 200 300の場合,"100", "200", "300").そういう訳で,最終的なプログラム.

int main(int argc, char* argv[])
{
    if (argc < 2) exit(-1);
    int correct = std::atoi(argv[1]);
    
    std::istream_iterator<double> input(std::cin);
    std::istream_iterator<double> last;
    
    double val = rmse<double>(input, last, correct);
    std::cout << "RMSE: " << val << std::endl;
    
    return 0;
}
|<