C++ 在C++;,如何使用向量视图和gsl_stats_mean计算整数向量的平均值?

C++ 在C++;,如何使用向量视图和gsl_stats_mean计算整数向量的平均值?,c++,vector,gsl,C++,Vector,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 m

我的程序处理整数的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;
}

向量视图是正确创建的,但我不明白为什么平均值是错误的(它应该等于10/5=2)。有什么想法吗?提前谢谢。

演双倍*的演员非常可疑

任何时候你想使用石膏,请三思。然后寻找一种不用强制转换的方法(如果转换是隐式的,可以引入一个临时变量)。然后在你投之前再考虑第三次


由于内存区域实际上不包含
double
值,因此代码只是简单地解释那里的位模式,就好像它们表示double一样,具有可预测的不希望的效果。将
int*
强制转换为
double*
与强制转换数组的每个元素非常不同。

虽然我不熟悉GSL,但表达式
(double*)GSL\u v.vector.data
看起来非常可疑。您确定重新解释用于获取数据的指针是正确的吗?

double*
转换会弄乱您的数据。它不是将数据转换为
double
,而是根据
gsl\u stats\u mean
函数使用
double
数组,将
int
二进制数据用作
double

。您正在获取int的
向量
,并告诉它将原始字节用作
double
,这将无法正常工作

您需要设置一个临时的
向量
,设置为double才能传入:

// 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());

除非你做的统计数据比平均值复杂得多,否则我会忽略gsl,只使用标准算法:

double mean = std::accumulate(stl_v.begin(), stl_v.end(), 0.0) / stl_v.size();
当/如果使用统计库是合理的,您的第一选择可能是寻找其他设计更好的工具(例如增压蓄能器)


无论出于何种原因,如果您决定确实需要使用gsl,那么看起来您必须首先将
int
s数组复制到
double
s数组,然后对结果使用gsl。这显然是非常低效的,尤其是在处理大量数据时——因此前面的建议是使用其他方法。

使用整数统计函数:

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

cout+1,这是一个问得很好的第一个问题。好吧,从现在起,我会更加谨慎地使用cast。Mark B还提出了一个带有临时向量的解决方案,但这是否意味着必须临时复制我的初始向量?如果这个向量非常大呢?谢谢,但是通过使用向量视图,我想避免使用临时向量,因为如果初始向量非常大,我会浪费时间将其复制到临时向量中。。。或者“tempForStats(stl_v.begin(),stl_v.end());”非常有效吗?我正在编写一个模拟器,因此我需要一个RNG以及计算均值、var、sd、分位数等的函数。这就是为什么我想继续使用GSL,而不是使用std::accumulate。@wfoolhill:标准库已经提供了PRNG,Boost累加器(以及许多其他)可以计算您提到的所有函数--比GSL甚至希望的要干净得多。我不知道Boost,因此遵循您的建议,我快速查看了Boost.acculator的文档。它看起来确实非常强大,但我不认为我需要它的所有功能。到目前为止,我已经拥有了GSL所需要的一切。@wfoolhill:当然,除了工作之外,你还需要的一切。即使你解决了这个问题,它仍然只是“除了工作正常之外”
double mean = std::accumulate(stl_v.begin(), stl_v.end(), 0.0) / stl_v.size();
cout << "mean=" << gsl_stats_int_mean( gsl_v.vector.data, 1, stl_v.size() ) << endl;