In C++, how to compute the mean of a vector of integers using a vector view and gsl_stats_mean?

tflutre picture tflutre · Jan 31, 2011 · Viewed 7.2k times · Source

my program manipulates STL vectors of integers but, from time to time, I need to calculate a few statistics on them. Therefore I use the GSL functions. To avoid copying the STL vector into a GSL vector, I create a GSL vector view, and give it to the GSL functions, as in this piece of code:

#include <iostream>
#include <vector>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_statistics.h>
using namespace std;

int main( int argc, char* argv[] )
{
  vector<int> stl_v;
  for( int i=0; i<5; ++i )
    stl_v.push_back( i );

  gsl_vector_int_const_view gsl_v = gsl_vector_int_const_view_array( &stl_v[0], stl_v.size() );

  for( int i=0; i<stl_v.size(); ++i )
    cout << "gsl_v_" << i << "=" << gsl_vector_int_get( &gsl_v.vector, i ) << endl;

  cout << "mean=" << gsl_stats_mean( (double*) gsl_v.vector.data, 1, stl_v.size() ) << endl;
}

Once compiled (gcc -lstdc++ -lgsl -lgslcblas test.cpp), this code outputs this:

gsl_v_0=0
gsl_v_1=1
gsl_v_2=2
gsl_v_3=3
gsl_v_4=4
mean=5.73266e-310

The vector view is properly created but I don't understand why the mean is wrong (it should be equal to 10/5=2). Any idea? Thanks in advance.

Answer

Ben Voigt picture Ben Voigt · Jan 31, 2011

The cast to double* is very suspicious.

Any time you are tempted to use a cast, think again. Then look for a way to do it without a cast (maybe by introducing a temporary variable if the conversion is implicit). Then think a third time before you cast.

Since the memory region does not actually contain double values, the code is simply interpreting the bit patterns there as if they represented doubles, with predictably undesired effects. Casting an int* to double* is VERY different from casting each element of the array.