Firstly, make it correct.
N is integral, you could make it E so you don't accidentally do integer arithmetic.
N-1 is wrong.
Rename average to mean.
Don't hardcode E.
You get:
template <typename It, typename E = typename std::iterator_traits<It>::value_type> E std_dev(It begin, It end){ E N = std::distance(begin, end); E const mean = std::accumulate(begin, end, E()) / N; auto sum_term = [mean](E init, E value)-> E { return init + (value - mean)*(value - mean); }; E variance = std::accumulate(begin, end, E(), sum_term); return std::sqrt(variance / N); }
Slightly stylized, with comparison to Boost Accumulator:
Live On Coliru
#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, 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) { R N = std::distance(b, e); R const mean = std::accumulate(b, e, R{}) / N; R variance = std::accumulate(b, e, R{}, [mean](R a, E v)-> R { 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