В 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, похоже, вам придется скопировать массив int
s в массив double
S сначала, затем используйте 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();