7

我的程序处理整数的 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)。任何想法?提前致谢。

4

6 回答 6

4

演员阵容double*非常可疑。

每当您想使用演员表时,请三思。然后寻找一种无需强制转换的方法(如果转换是隐式的,则可能通过引入临时变量)。然后在你施放之前三思而后行。

由于内存区域实际上并不包含double值,因此代码只是解释那里的位模式,就好像它们代表双精度一样,具有可预见的不良影响。转换int*double*与转换数组的每个元素非常不同。

于 2011-01-31T15:59:23.673 回答
3

使用整数统计函数:

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

请注意,gsl_stats_int_mean而不是gsl_stats_mean.

于 2011-01-31T20:13:37.110 回答
2

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

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

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

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

于 2011-01-31T16:17:48.680 回答
1

根据http://www.gnu.org/software/gsl/manual/html_node/Mean-and-standard-deviation-and-variance.html,该gsl_stats_mean函数采用double. 您正在使用vectorint 并告诉它使用double无法正常工作的原始字节。

您需要设置一个临时vector的 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());

编辑:你也可以使用标准库算法来做 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();
于 2011-01-31T16:09:15.967 回答
1

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

于 2011-01-31T16:02:42.833 回答
1

投射到double*会弄乱你的数据。它不是将数据转换为double,而只是使用int二进制数据作为double

于 2011-01-31T16:03:33.943 回答