2016-12-21 9 views
1

std::vectorのすべての要素を、通常の型のC++で実行されているのと同じ方法で定数で掛けて除算する必要があります。入力ベクトルが整数型の場合は整数、そうでない場合は浮動小数点型です。整数型std :: vectorを定数で除算する演算子を提供しようとしています

私はstd::multipliesに基づいて乗算のコードを見つけ、交換std::dividesで修正しました。その結果、コードは正常に動作しますが、希望の順序ではありません。

#include <iostream> 
#include <vector> 
#include <algorithm> 

// std::vector multiplication by constant 
// http://codereview.stackexchange.com/questions/77546 
template <class T, class Q> 
    std::vector <T> operator*(const Q c, const std::vector<T> &A) { 

    std::vector <T> R(A.size()); 
    std::transform(A.begin(), A.end(), R.begin(), 
       std::bind1st(std::multiplies<T>(),c)); 
    return R; 
} 

// My modification for division. There should be integer division 
template <class T, class Q> 
    std::vector <T> operator/(const std::vector<T> &A, const Q c) { 

    std::vector <T> R(A.size()); 
    std::transform(A.begin(), A.end(), R.begin(), 
       std::bind1st(std::divides<T>(),c)); 
    return R; 
} 



int main() { 

    std::vector<size_t> vec; 
    vec.push_back(100); 

    int d = 50; 

    std::vector<size_t> vec2 = d*vec;   
    std::vector<size_t> vec3 = vec/d;   
    std::cout<<vec[0]<<" "<<vec2[0]<<" "<<vec3[0]<<std::endl; 

    // The result is: 
    // 100 5000 0 

    size_t check = vec[0]/50; 
    std::cout<<check<<std::endl; 
    // Here the result is 2 

    // But 

    std::vector<double> vec_d;   
    vec_d.push_back(100.0);   
    vec_d = vec_d/50;   
    std::cout<<vec_d[0]<<std::endl; 

    // And here the result is 0.5 

    return 0; 
} 

私の演算子は正しく書くことができますか?私はstd::bind1stが各要素についてcで除算を呼び出すと考えましたが、それは何とか逆になります。

編集:私は、私はループを書くことができることを理解し、私は大きな数字のための部門の多くをしたいので、私はそれが速くなりたかった...

+1

'std :: transform'は内部的にループを使用しているので、生のループに比べてパフォーマンス上の利点はありません。 (実際には、関数呼び出しとバインドのための追加のオーバーヘッドがあるかもしれません。) – qxz

+0

@qxzありがとう!私は参照してください... – Slowpoke

+1

'std :: bind2nd(...)'または 'std :: bind(std :: divides ()、_1、c)'が必要なようです。 –

答えて

3

C++ 11とstd::transformを使用して、私が代わりにbindを使用してのラムダ(this tutorialを参照)することをお勧めしたい:私の意見では

std::transform(A.begin(), A.end(), R.begin(), [c](T val) { 
    return val/c; 
}); 

を、ラムダはあなたが結合していない場合は特に(あなたのケースのように)、ほとんど常にbind INGよりも読みやすいですすべての関数のパラメータ

パフォーマンスを心配している場合は、生の forループがわずかに速いかもしれません。なぜなら、関数呼び出しとラムダオブジェクトの作成にかかるオーバーヘッドがないからです。ディートマーKühlによると

std::transform()は「魔法」のビットを行うと、実際にループよりも優れて行うことができます。例えば、連続した整数のシーケンスで使用されていることがわかると、実装はループをベクトル化することを選択できます。しかし、ループよりも遅くなる可能性は低いです。他のポストと同様に

1
auto c_inverse= 1/c; 
std::transform(A.begin(), A.end(), R.begin(), [c_inverse](T val) { 
    return val * c_inverse; 
}); 

が、むしろ分裂よりも、あなたが最も可能性の高い逆を乗じてパフォーマンスの向上を確認することが言及されるべきです。

+0

...「val」とは何ですか?なぜあなたは 'c'をキャプチャしていますが、それを使用していませんか? – qxz

1

なぜベクターのためだけにするのですか?ここでの方法は、より汎用的にするために、容器の多くの種類で動作するようです:

template <class container, class Q> 
container operator/(const container& A, const Q c) { 
    container R; 
    std::transform(std::cbegin(A), std::cend(A), std::back_inserter(R), 
     [c](const auto& val) {return val/c; }); 
    return R; 
} 

確かback_inserterはそれとして、動的に割り当てられますので、ベクトルの事前割り当てよりも少し遅くなることが予想されますしかし、まあ、時には一般性のためにスピードを交換するのが適切かもしれない。

+1

ありがとう!私のプログラムの中には、誰かにとって良い点かもしれないベクトルに限られていますが – Slowpoke

関連する問題