[英]In C++, how to compute the mean of a vector of integers using a vector view and gsl_stats_mean?
我的程序操纵整数的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)。 任何的想法? 提前致谢。
演员double*
是非常可疑的。
每当你想要使用演员时,请再想一想。 然后在没有强制转换的情况下寻找一种方法(如果转换是隐式的,可以通过引入临时变量)。 然后在你演员之前第三次思考。
由于存储区实际上不包含double
值,因此代码只是将那里的位模式解释为它们表示双精度,具有可预测的不希望的效果。 将int*
为double*
与转换数组的每个元素非常不同。
使用整数统计函数:
cout << "mean=" << gsl_stats_int_mean( gsl_v.vector.data, 1, stl_v.size() ) << endl;
请注意gsl_stats_int_mean
而不是gsl_stats_mean
。
除非你做了很多比平均值复杂得多的统计数据,否则我会忽略gsl而只使用标准算法:
double mean = std::accumulate(stl_v.begin(), stl_v.end(), 0.0) / stl_v.size();
当/如果使用统计库是合理的,你的第一选择应该是寻找更好设计的其他东西(例如,Boost Accumulators)。
如果由于某种原因决定你真的需要使用gsl,看起来你必须首先将你的int
数组复制到double
的数组中,然后在结果上使用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的gsl_stats_mean
函数采用的阵列double
。 你正在使用int的vector
并告诉它使用原始字节作为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();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.