2015-09-30 6 views
26

निम्नलिखित परिणामों के मुताबिक, % ऑपरेशन का उपयोग करके दो संख्याओं के बीच वर्दी यादृच्छिक पूर्णांक उत्पन्न करना std::uniform_int_distribution का उपयोग करने से लगभग 3 गुना तेज है: क्या std::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- पर विचार किया गया- हानिकारक –

उत्तर

39

आप मिल जाएगा सांख्यिकीय पूर्वाग्रह आप सापेक्ष (%) का उपयोग करते हैं जैसे की सीमा मैप करने के लिए rand() एक और अंतराल के लिए।

उदा rand()[0, 32767] के लिए समान रूप नक्शे (पूर्वाग्रह के बिना) लगता है और आप [0,4] कर rand() % 5 मैप करना चाहते हैं। फिर मान 0, 1, और 2 औसत पर 32768 बार से 6554 का उत्पादन किया जाएगा, लेकिन मूल्य 3 और 4 केवल 6553 बार (ताकि 3 * 6554 + 2 * 6553 = 32768)।

पूर्वाग्रह छोटा है (0.01%) लेकिन आपके आवेदन के आधार पर घातक साबित हो सकता है। अधिक जानकारी के लिए स्टीफन टी। लववेज की बातचीत "rand() considered harmful" देखें।

+1

निष्पक्ष होने के लिए, एक अनुशासनिक यह है कि यदि मॉड्यूलस दो की निरंतर शक्ति है, तो '%' आरएसपी। 'और 'uniform_int_distribution' से बहुत तेज़ हो सकता है, और सामान्य कार्यान्वयन पर कोई पूर्वाग्रह नहीं पेश किया जाता है। –

+0

@AneneVogel सच है, लेकिन केवल अगर RAND_MAX 2 की शक्ति भी है। यह मान कार्यान्वयन निर्भर है। यह गारंटी है कि यह मान कम से कम 32767 है। पोर्टेबल कोड और सामान्य इंटरफेस के लिए, बस 'uniform_int_distribution' का उपयोग करें। – TemplateRex

+0

@AneneVogel यह एक क्यूओआई मुद्दे की तरह दिखता है, नहीं? लेकिन, यदि आपके पास एंट्रॉपी के एक्स बिट्स के साथ यादृच्छिक संख्या है, तो एंट्रॉपी के साथ वाई बिट्स समान है, यदि आप निचले जेड बिट्स निकालते हैं, तो आप एंट्रॉपी के एक्स * जेड/वाई बिट्स के साथ समाप्त होते हैं। यदि आप अपने परिणाम में सभी वाई बिट्स को एकजुट करते हैं (एक साधारण शिफ्ट-एक्सर सिस्टम), तो आपका आउटपुट अभी भी एन्ट्रॉपी के एक्स बिट्स (एक्स <= Z) मान ले सकता है। – Yakk

संबंधित मुद्दे