2017-06-08 13 views
1

私のコードを複製したくありませんが、1行を除いて同じことをする2つの関数があります。 プライベート関数を呼び出す別の関数が必要です。それはテンプレートであり、私の重複したコードの問題を解決します。C++ 2つの関数は同じ行を除いて同じです

double EuclideanDistance::calculateDistance(const Point &p1, const Point &p2) const 
{ 
    if (p1.getDimension()!=p2.getDimension()) 
     return 0; 
    double sum = 0.0; 
    for(size_t i = 0; i < p1.getDimension(); i++) 
    { 
     sum += pow(p1[i] - p2[i], 2.0); 
    } 
    return sqrt(sum); 
} 

double EuclideanDistance::calculateWeightedDistance(const Point &p1, const Point &p2, const double *weights) const 
{ 
    if (p1.getDimension()!=p2.getDimension()) 
     return 0; 
    double sum = 0.0; 
    for(size_t i = 0; i < p1.getDimension(); i++) 
    { 
     sum += pow(((p1[i] - p2[i])*weights[i]), 2.0);//here is the difference 
    } 
    return sqrt(sum); 
} 

あなたは何をお勧めしますか?

+2

コードは、私には正常に見えます。統合しようとすると、最初のバージョンのパフォーマンスが低下します。 – rustyx

+2

これは[codereview](http://codereview.stackexchange.com/)にもっと属しています。アイデアとして: 'weights'が' 1'であれば関数は同じです。あなたはおそらくそれを実現させる方法を見つけることができます。 – nwp

+0

[コードレビュー](https://codereview.stackexchange.com/) – gsamaras

答えて

5

calculateWeightedDistanceのみを実装します。 およびcalculateDistanceの場合calculateWeightedDistance、重量の場合1.0

+1

欠点は、1.0で満たされた配列を準備する必要があることです。 – ArturFH

2

次はどうなりますか? 3番目のパラメータnullptrで関数を呼び出すと、最初のバージョンの動作が実行されます。

double EuclideanDistance::calculateWeightedDistance(const Point& p1, const Point& p2, const double* weights) const { 
    if (p1.getDimension()!=p2.getDimension()) 
     return 0; 

    double sum = 0.0; 
    for(size_t i = 0; i < p1.getDimension(); i++) 
    { 
     const auto distance_d = (p1[i] - p2[i]) * 
           (weights != nullptr ? weights[i] : 1.0); 
     sum += pow(distance_d, 2.0); 
    } 
    return sqrt(sum); 
} 
+1

OpenCVと思われます。だから私は大量の計算が可能であると考えています。それぞれの反復での分岐は、潜在的な最適化の範囲内のきちんとした考えではありません。 – ArturFH

+0

@ ArturR.Czechowskiブランチのそれは同じ方法なので、ブランチの予測はブランチのコストを隠すでしょう –

+0

非常にコンパイラの実装とアーキテクチャに依存します。私はARM(g ++ -O2フラグ)でそれをチェックしたところ、条件はループの繰り返しごとにチェックされます。少なくともARMでは、条件付き演算があるので、この時点では分岐がありません。したがって、seqenceは 'cmp r3、#0'です。 'ldrne r7、[r3、r4]'; 'moveq r7、#1'です。インテルでは、おそらく後で夜にアセンブラの知識をリフレッシュする必要があります。 – ArturFH

1

あなたはこの方法を因数分解可能性があります

template <typename F, typename Ts...> 
double calculateDistanceImpl(F&& f, const Point &p1, const Point &p2, Ts&&... args) 
{ 
    if (p1.getDimension()!=p2.getDimension()) 
     return 0; 

    double sum = 0.0; 
    for(size_t i = 0; i != p1.getDimension(); i++) 
    { 
     sum += f(p1[i], p2[i], args[i]...); 
    } 
    return sqrt(sum); 
} 


double EuclideanDistance::calculateDistance(const Point &p1, const Point &p2) const 
{ 
    return calculateDistanceImpl(
     [](auto&& p1, auto&& p2){ return pow(p1 - p2, 2.0);}, 
     p1, p2); 
} 

double EuclideanDistance::calculateWeightedDistance(const Point &p1, 
                const Point &p2, 
                const double *weights) const 
{ 
    return calculateDistanceImpl(
     [](auto&& p1, auto&& p2, double weight){ return pow((p1 - p2) * weight, 2);}, 
     p1, p2, weights); 
} 
関連する問題