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

时间:2011-01-31 15:57:01

标签: 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 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 个答案:

答案 0 :(得分:4)

double*的演员非常怀疑。

每当你想要使用演员时,请再想一想。然后在没有强制转换的情况下寻找一种方法(如果转换是隐式的,可以通过引入临时变量)。然后在你演员之前第三次思考。

由于内存区域实际上并不包含double值,因此代码只是将那里的位模式解释为它们表示双精度,具有可预测的不期望的效果。将int*投射到double*与投射阵列的每个元素非常不同。

答案 1 :(得分:3)

使用整数统计函数:

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

请注意gsl_stats_int_mean而不是gsl_stats_mean

答案 2 :(得分:2)

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

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

如果/如果使用统计库是合理的,那么您的第一选择应该是寻找更好设计的其他东西(例如,Boost Accumulators)。

如果您出于某种原因决定确实需要使用gsl,看起来您必须首先将int的数组复制到double的数组中,然后在结果上使用gsl。这显然是非常低效的,特别是如果你正在处理大量数据 - 因此之前建议使用别的东西。

答案 3 :(得分:1)

虽然我不熟悉GSL,但表达式(double*) gsl_v.vector.data看起来非常可疑。您确定reinterpret_cast指针获取double数据是否正确?

答案 4 :(得分:1)

施放到double*会弄乱您的数据。它不会将数据转换为double,而只是将int二进制数据转换为double

答案 5 :(得分:1)

根据http://www.gnu.org/software/gsl/manual/html_node/Mean-and-standard-deviation-and-variance.htmlgsl_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());

编辑:您也可以使用标准库算法来实现int意思:

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