2010-11-29 2 views
2

私はコンテナ内の数値を繰り返し処理し、いくつかの集計値(この場合はエントロピー)を計算する簡単な関数を書いています。異なる値の型(doublefloat、...)を超えるベストプラクティス:このコードを改善してコンテナ値を合計する方法

私はそれが別のコンテナで動作するように、できるだけ一般的なようにそれを書きたい(vectorset、...)ので、私はこれをやっています:

template<class Iterator> 
typename Iterator::value_type Entropy(Iterator begin, Iterator end) { 
    typedef typename Iterator::value_type Value; 
    Value result = Value(); // assignment needed? 
    for (Iterator it = begin; it != end; ++it) { 
    result -= *it * log(*it); 
    } 
    return result; 
} 

私は、このコードがすべてのベストプラクティスによってどのように見えるかに興味があります。言い換えれば、この小さな関数のSTL実装はまさにどのように見えますか?

+0

「すべてのベスト・プラクティス」のセットがとてもコードが書き込まれていない飽きないでしょう矛盾しています。あなたはどういう意味ですか? –

+0

私は、STLの実装者がこれをどのように書いているのか不思議です。私はSTLコードそのものと同じくらい簡潔で包括的なコードを書く方法を学びたいと思っています... – Frank

答えて

4

のstdに見て::変換とstd ::は蓄積

+0

興味深いことに、なぜ変換のソースコード(http://gcc.gnu.org/onlinedocs/libstdc++/latest -doxygen/a01056_source.html#l00116)は、「Iterator :: value_type」を使用するのではなく、値タイプに追加のテンプレートパラメータを使用します。 – Frank

+0

@user:あなたは '蓄積する'にリンクしています。初期値を選択することができます(例えば、すべての値を乗算すると1が良いでしょう)。結果の型は 'Iter :: value_type'と同じである必要はありません。 – UncleBens

+1

など、別の結果タイプが必要な場合があるためです。整数のリストから平均をcaculatingするとき、あなたはまだ本当の価値のある結果が欲しいです。 –

4
template < typename T1, typename T2 > 
T1 entropy_sum(T1 sum_so_far, T2 number) 
{ 
    return sum_so_far - static_cast<T1>(number) * log(static_cast<T1>(number)); 
} 
double entropy = std::accumulate(set.begin(), set.end(), 0.0, &entropy_sum<double, set_type::value_type>); 

あなたの方法は、Value()は、法的声明ではないかもしれないという事実を除いてOKです。

コメントを反映するように編集されました。

+0

しかし、 'log'は' float'と 'long double'に対しても定義されていますので、これらの型も許可したいと思います。 – Frank

+0

次に、リターンと最初のargもパラメータ化します。この場合、特定の型変換を行う必要があります。そうしないと、整数型のために選択されたログがあなたの望むものと異なる場合があります。 –

2

このためstd::iterator_traitsを使用する方が良いでしょう:

typedef typename std::iterator_traits<Iterator>::value_type Value; 

これはイテレータはポインタにすることができます。

C++ 0xので
4

次のラムダバージョンを使用することができます。

template<class Iterator> 
typename Iterator::value_type Entropy(Iterator begin, Iterator end) { 
    typedef typename Iterator::value_type Value; 
    return accumulate(begin, end, Value(), 
     [] (Value i, Value j)-> Value { return i - j * log(j); }); 
} 
+0

非ローカル変数(begin、end)を使用していない場合[なぜ]ですか? –

+0

あなたは正しいです@フレッド、私はまだこのエリアに私のLプレートを持っていることを告白します。編集、ありがとう。ラムダ構文をよりよく理解するためのプライベートクエストの一部。 –

+0

私たちはすべてこのクエストに参加しています。 –

関連する問題