(See the next iteration.)
I have this template function for computing standard deviation in one pass over the data. The underlying math is here.
coderodde_sd.h:
#ifndef CODERODDE_SD_H
#define CODERODDE_SD_H
#include <cmath>
#include <iterator>
#include <sstream>
#include <stdexcept>
namespace net {
namespace coderodde {
namespace stat {
template<class Iter>
double sd(Iter begin, Iter end)
{
typedef typename std::iterator_traits<Iter>::difference_type
difference_type;
difference_type distance = std::distance(begin, end);
if (distance < 2)
{
std::stringstream ss;
ss << "The standard deviation cannot be computed for "
"less than two elements. The input sequence has "
<< distance
<< " elements.";
throw std::runtime_error(ss.str());
}
typedef typename std::iterator_traits<Iter>::value_type
value_type;
double x = 0.0;
double x_squared = 0.0;
for (Iter it = begin; it != end; ++it)
{
x += *it;
x_squared += (*it) * (*it);
}
return std::sqrt((x_squared - (x * x) / distance) /
(distance - 1)
);
}
} /* net::coderodde::stat */
} /* net::coderodde */
} /* net */
#endif /* CODERODDE_SD_H */
main.cpp:
#include <iostream>
#include <list>
#include "coderodde_sd.h"
using net::coderodde::stat::sd;
using std::cout;
using std::list;
int main(int argc, char** argv) {
double bad_array[]{1.0};
try
{
sd(bad_array, bad_array);
}
catch (std::runtime_error& error)
{
cout << "ERROR: " << error.what() << "\n";
}
try
{
sd(bad_array, bad_array + 1);
}
catch (std::runtime_error& error)
{
cout << "ERROR: " << error.what() << "\n";
}
std::list<int> my_list = { 1, 5, 2, 4, 3 };
cout << "Standard deviation: "
<< sd(my_list.begin(), my_list.end())
<< "\n";
return 0;
}
I tried hard to write idiomatic C++; please tell me where I failed to reach that ideal + any other critique.
auto
and you'll no longer need to care aboutdifference_type
. \$\endgroup\$