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値が含まれていないため、コードはビットパターンを、それらがdoubleを表すかのように単純に解釈し、予想外の望ましくない影響を及ぼします。int*toのキャストは、配列の各要素のキャストとは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を使用する必要があると判断した場合は、最初にsintの配列をsの配列にコピーしてからdouble、結果にgslを使用する必要があるようです。これは、特に大量のデータを処理している場合は、明らかに非常に非効率的です。したがって、代わりに別のものを使用するという以前のアドバイスです。

于 2011-01-31T16:17:48.680 に答える
1

私はGSLに精通していませんが、その表現(double*) gsl_v.vector.dataは非常に疑わしいように見えます。reinterpret_castデータを取得するためにそのポインタが正しいことを確認しdoubleますか?

于 2011-01-31T16:02:42.833 に答える
1

にキャストするdouble*と、データが台無しになります。データをに変換するのではなく、バイナリデータを次のようdoubleに使用するだけです。intdouble

于 2011-01-31T16:03:33.943 に答える
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 に答える