Slightly stylized, with comparison to Boost Accumulator:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
template <typename It, typename E = typename std::iterator_traits<It>::value_type>value_type, typename R = typename std::common_type<double, E>::type>
R std_dev_boost(It begin, It end){
namespace ba = boost::accumulators;
ba::accumulator_set<R, ba::stats<ba::tag::variance> > accu;
std::for_each(begin, end, std::ref(accu));
return std::sqrt(ba::variance(accu));
}
template <typename It,
typename E = typename std::iterator_traits<It>::value_type,
typename R = typename std::common_type<double, E>::type>
R std_dev(It b, It e)
{
ER N = std::distance(b, e);
ER const mean = std::accumulate(b, e, ER{}) / N;
ER variance = std::accumulate(b, e, ER{}, [mean](ER a, E v)-> ER { return a + (v-mean)*(v-mean); });
return std::sqrt(variance / N);
}
int main(){
std::vector<int> stuff {35, 34, 36, 39, 35, 35, 35, 35, 35};
std::cout << std_dev_boost(stuff.begin(), stuff.end()) << "\n";
std::cout << std_dev (stuff.begin(), stuff.end()) << "\n";
}
Prints
1.34256
1.34256