我的程序操纵整数的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)。任何的想法?提前谢谢。
答案 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.html,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());
编辑:您也可以使用标准库算法来实现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();