2015-09-30 12 views
26

std::uniform_int_distributionを使用するよりもあり、ほぼ3倍の速%操作を使用して、2つの数字の間に一様乱数整数を生成し、その結果を以下による:std::uniform_int_distributionを使用するために何か良い理由がありますか?uniform_int_distributionとモジュラス演算の利点は何ですか?

コード:

#include <iostream> 
#include <functional> 
#include <vector> 
#include <algorithm> 
#include <random> 

#include <cstdio> 
#include <cstdlib> 

using namespace std; 

#define N 100000000 

int main() 
{ 

clock_t tic,toc; 

for(int trials=0; trials<3; trials++) 
{ 
    cout<<"trial: "<<trials<<endl; 

    // uniform_int_distribution 
    { 
     int res = 0; 
     mt19937 gen(1); 
     uniform_int_distribution<int> dist(0,999); 

     tic = clock(); 
     for(int i=0; i<N; i++) 
     { 
      int r = dist(gen); 
      res += r; 
      res %= 1000; 
     } 
     toc = clock(); 
     cout << "uniform_int_distribution: "<<(float)(toc-tic)/CLOCKS_PER_SEC << endl; 
     cout<<res<<" "<<endl; 

    } 

    // simple modulus operation 
    { 
     int res = 0; 
     mt19937 gen(1); 

     tic = clock(); 
     for(int i=0; i<N; i++) 
     { 
      int r = gen()%1000; 
      res += r; 
      res %= 1000; 
     } 
     toc = clock(); 
     cout << "simple modulus operation: "<<(float)(toc-tic)/CLOCKS_PER_SEC << endl; 
     cout<<res<<" "<<endl; 

    } 

    cout<<endl; 
} 

} 

出力:

trial: 0 
uniform_int_distribution: 2.90289 
538 
simple modulus operation: 1.0232 
575 

trial: 1 
uniform_int_distribution: 2.86416 
538 
simple modulus operation: 1.01866 
575 

trial: 2 
uniform_int_distribution: 2.94309 
538 
simple modulus operation: 1.01809 
575 
+4

'std :: uniform_int_distribution'は整数間隔の間に一様な分布を生成することができますが、'% 'はできません。 – Lingxi

+19

すぐに行う必要がない場合は、高速なコードを書くのは簡単です。 –

+6

https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful –

答えて

39

あなたは、例えばの範囲をマッピングするためにモジュロ(%)を使用するときは、統計的な偏りを取得します別の間隔へのrand()

例えばは[0, 32767]に(バイアスなし)一律rand()マップを仮定して、あなたはrand() % 5をやって[0,4]にマッピングします。次に、値0,1、および2は平均して32768回のうち6554回生成されますが、値3と4は6553回だけです(したがって3 * 6554 + 2 * 6553 = 32768)。

バイアスは小さく(0.01%)、アプリケーションによっては致命的となる可能性があります。詳細はStephan T. Lavavejのトーク「rand() considered harmful」をご覧ください。

+1

公平であるためには、モジュラスが2の一定累乗であるならば、 '%' rsp。 '&'は 'uniform_int_distribution'よりはるかに高速であり、通常の実装ではバイアスが導入されません。 –

+0

@ArneVogel trueですが、RAND_MAXも2の累乗である場合のみです。この値は実装に依存します。この値は少なくとも32767であることが保証されています。移植性のあるコードと一般的なインターフェースでは、 'uniform_int_distribution'を使用してください。 – TemplateRex

+0

@ArneVogel QOIの問題のように見えますか?しかし、エントロピーのXビットがYビット幅の乱数でエントロピーが一様に分散している場合、下位のZビットを抽出すると、X * Z/Yビットのエントロピーになります。代わりにすべてのYビットを結果(単純なshift-xorシステム)に変換すると、出力にはXビットまでのエントロピー(X <= Zを前提とする)が可能です。 – Yakk

関連する問題