В C++, как вычислить среднее значение вектора целых чисел, используя векторное представление и среднее значение статистики gsl?

моя программа манипулирует STL векторы целых чисел но, время от времени, мне нужно вычислить несколько статистических данных о них. Поэтому я использую функции GSL. Чтобы избежать копирования вектора STL в вектор GSL, я создаю GSL векторный вид, и дайте его функциям GSL, как в этом фрагменте кода:

#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;
}

после компиляции (GCC-lstdc++- lgsl-lgslcblas test.cpp), этот код выводит следующее:

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

вектор представление правильно создано, но я не понимаю, почему среднее значение неправильно (оно должно быть равно 10/5=2). Есть идеи? Спасибо заранее.

6 ответов


используйте функции целочисленной статистики:

cout << "mean=" << gsl_stats_int_mean( gsl_v.vector.data, 1, stl_v.size() ) << endl;

Примечание gsl_stats_int_mean вместо gsl_stats_mean.


актеры double* - Это очень подозрительно.

всякий раз, когда вы испытываете соблазн использовать гипс, подумайте еще раз. Затем найдите способ сделать это без приведения (возможно, введя временную переменную, если преобразование неявно). Затем подумайте в третий раз, прежде чем бросать.

поскольку область памяти фактически не содержит double значения, код просто интерпретирует битовые шаблоны там, как если бы они представляли двойные, с предсказуемо нежелательными эффектами. Литье Ан int* to double* сильно отличается от приведения каждого элемента массива.


Если вы не делаете много статистики значительно сложнее, чем среднее, я бы проигнорировал gsl и просто использовал стандартные алгоритмы:

double mean = std::accumulate(stl_v.begin(), stl_v.end(), 0.0) / stl_v.size();

когда / если использование статистической библиотеки оправдано, ваш первый выбор, вероятно, должен быть искать что-то другое, что лучше спроектировано (например, аккумуляторы Boost).

Если вы решите по какой-либо причине, что вам действительно нужно использовать gsl, похоже, вам придется скопировать массив ints в массив doubleS сначала, затем используйте gsl на результат. Это очевидно, довольно неэффективно, особенно если вы имеете дело с большим количеством данных-таким образом, предыдущий совет использовать что-то другое.


хотя я не знаком с GSL, выражение (double*) gsl_v.vector.data выглядит крайне подозрительно. Вы уверены, что это правильно reinterpret_cast этот указатель, чтобы получить double данные?


кастинг double* портит ваши данные. Это не преобразование данных в double, но только с помощью int двоичные данные в виде double


согласно http://www.gnu.org/software/gsl/manual/html_node/Mean-and-standard-deviation-and-variance.html the gsl_stats_mean функция принимает массив double. Ты берешь vector int и говорит ему использовать необработанные байты как double не будет работать правильно.

вам нужно настроить временный vector двойной, чтобы пройти в:

// Assumes that there's at least one item in stl_v.
std::vector<double> tempForStats(stl_v.begin(), stl_v.end());
gsl_stats_mean(&tempForStats[0], 1, tempForStats.size());

EDIT: вы также можете использовать стандартные алгоритмы библиотеки для выполнения int mean себя:

// Assumes that there's at least one item in stl_v.
double total = std::accumulate(stl_v.begin(), stl_v.end(), 0);
double mean = total / stl_v.size();