Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) GetStdDev

 

GetStdDev is a math code snippet to calculate the standard deviation of the values in a container.

 

#include <cassert>
#include <cmath>
#include <functional>
#include <numeric>
#include <vector>

template <class T> struct SquareAccumulator
  : public std::binary_function<T,T,T>
{
  const T operator()(const T& sum, const T& x) const
    { return sum+(x*x); }
};

//From http://www.richelbilderbeek.nl/CppGetStdDev.htm
double GetStdDev(const std::vector<double>& v)
{
  assert(v.size() > 1
    && "Can only calculate standard deviations from "
       "data sets with size 2 or larger");
  const double sum_x
    = std::accumulate(v.begin(),v.end(),0.0);
  const double sum_x_squared
    = std::accumulate(v.begin(),v.end(),
        0.0,SquareAccumulator<double>());
  const double sz = static_cast<double>(v.size());
  return std::sqrt(((sz*sum_x_squared)-(sum_x*sum_x))
    / (sz*(sz-1.0)));
}

 

 

 

 

 

GetStdDev test

 

GetStdDev was tested by a previous version of this code snippet.

 

#include <cassert>
#include <cmath>
#include <functional>
#include <numeric>
#include <vector>

template <class T> struct SquareAccumulator
  : public std::binary_function<T,T,T>
{
  const T operator()(const T& sum, const T& x) const
    { return sum+(x*x); }
};

//From http://www.richelbilderbeek.nl/CppGetStdDev.htm
double GetStdDev(const std::vector<double>& v)
{
  assert(v.size() > 1
    && "Can only calculate standard deviations from "
       "data sets with size 2 or larger");
  const double sum_x
    = std::accumulate(v.begin(),v.end(),0.0);
  const double sum_x_squared
    = std::accumulate(v.begin(),v.end(),
        0.0,SquareAccumulator<double>());
  const double sz = static_cast<double>(v.size());
  return std::sqrt(((sz*sum_x_squared)-(sum_x*sum_x))
    / (sz*(sz-1.0)));
}

//From http://www.richelbilderbeek.nl/CppGetStdDev.htm
double GetStdDevOld(const std::vector<double>& v)
{
  const std::size_t sz = v.size();
  assert(sz>1);

  double sumX = 0.0;
  double sumXsquared = 0.0;
  for (std::size_t i=0; i!=sz; ++i)
  {
    const double x = v[i];
    sumX+=x;
    sumXsquared+=(x*x);
  }
  const double dSize = static_cast<double>(sz);
  return std::sqrt(((dSize*sumXsquared)
    -(sumX*sumX))/(dSize *(dSize-1.0)));
}

#include <cstdlib>

//From htpp://www.richelbilderbeek.nl/CppGetRandomUniform.htm
double GetRandomUniform()
{
  return static_cast<double>(std::rand())
    / static_cast<double>(RAND_MAX);
}

#include <iostream>

//From htpp://www.richelbilderbeek.nl/CppGetStdDev.htm
int main()
{
  std::vector<double> v;
  v.push_back(GetRandomUniform());
  v.push_back(GetRandomUniform());

  int max = 2;
  while (max != 33554432)
  {
    for (int i=0; i!=max; ++i)
    {
      v.push_back(GetRandomUniform());
    }
    std::cout << max << ":\t"
      << GetStdDev(v) << "\t"
      << GetStdDevOld(v) << std::endl;

    max*=2;
  }
}

 

Screen output:

 

Starting /MyFolder/MyProject...
2: 0.207834 0.207834
4: 0.273555 0.273555
8: 0.2501 0.2501
16: 0.295567 0.295567
32: 0.301386 0.301386
64: 0.28569 0.28569
128: 0.290935 0.290935
256: 0.283272 0.283272
512: 0.283464 0.283464
1024: 0.289154 0.289154
2048: 0.288763 0.288763
4096: 0.288992 0.288992
8192: 0.288068 0.288068
16384: 0.288728 0.288728
32768: 0.288723 0.288723
65536: 0.28853 0.28853
131072: 0.288398 0.288398
262144: 0.288527 0.288527
524288: 0.288621 0.288621
1048576: 0.288542 0.288542
2097152: 0.288646 0.288646
4194304: 0.288659 0.288659
8388608: 0.288658 0.288658
16777216: 0.288649 0.288649
/MyFolder/MyProject exited with code 0

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict