एक यादृच्छिक बूलियन उत्पन्न करने का सबसे तेज़ तरीका


87

इसलिए C # में एक यादृच्छिक बूल बनाने के कई तरीके हैं:

  • Random.Next () का उपयोग करना: rand.Next(2) == 0
  • Random.NextDouble () का उपयोग करना: rand.NextDouble() > 0.5

क्या वास्तव में अंतर है? यदि हां, तो वास्तव में बेहतर प्रदर्शन किसका है? या क्या कोई और तरीका है जो मैंने नहीं देखा, वह और भी तेज हो सकता है?



7
क्या यह वास्तव में अड़चन है?
ब्रायन रासमुसेन

2
वास्तव में इसे चलाने के बिना (क्योंकि कोई भी विधि बहुत तेज़ी से तेज होगी), मेरा अनुमान NextBytesएक बाइट सरणी को पूर्व-आबाद करने के लिए उपयोग करना होगा , BitArrayजो कि बूलियनों के संग्रह में बदल सकता है, और Queueजब तक वे खाली नहीं हो जाते, तब तक उन बूलियनों को पुनः प्राप्त करें। प्रक्रिया। इस पद्धति के साथ, आप केवल एक बार रैंडमाइज़र का उपयोग कर रहे हैं, इसलिए किसी भी ओवरहेड का निर्माण केवल तभी होता है जब आप कतार को फिर से भरते हैं। यह नियमित Randomवर्ग के बजाय एक सुरक्षित यादृच्छिक संख्या जनरेटर के साथ काम करते समय उपयोगी हो सकता है ।
जो एनोस

2
@JoeEnos MS ने कार्यान्वयन को गड़बड़ कर दिया NextBytes, इसलिए यह आश्चर्यजनक रूप से धीमा है
CodesInChaos

1
@CodesInChaos वाह, यह दिलचस्प है - मैंने इसे एक डिस्सेम्बलर में देखा कि आप क्या देख रहे थे: buffer[i] = (byte)(this.InternalSample() % 256);- मैं मान रहा हूं कि आप किस बारे में बात कर रहे हैं, कि वे उस यादृच्छिक पूर्णांक को ले सकते हैं और इसे 3 से विभाजित कर सकते हैं। , 1/3 काम के साथ बाइट सरणी को आबाद करना। मुझे आश्चर्य है कि अगर वहाँ एक कारण था या अगर यह सिर्फ डेवलपर्स द्वारा एक निरीक्षण था।
जो एनोस

जवाबों:


72

पहला विकल्प - rand.Next(2)परदे के लिए निम्न कोड के पीछे कार्यान्वित:

if (maxValue < 0)
{
    throw new ArgumentOutOfRangeException("maxValue",
        Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", new object[] { "maxValue" }));
}
return (int) (this.Sample() * maxValue);

और दूसरे विकल्प के लिए - rand.NextDouble():

return this.Sample();

चूंकि पहले विकल्प में maxValueसत्यापन, गुणा और कास्टिंग शामिल है, इसलिए दूसरा विकल्प संभवत: तेज है


धन्यवाद, यह सब मैं जानना चाहता था।
timedt

5
मेरा अपना समय कहता है कि दूसरा विकल्प पहले की तुलना में लगभग 5% तेज है।
क्लिक करें

62

दूसरे विकल्प के लिए छोटी वृद्धि :

इसके अनुसार MSDN के

public virtual double NextDouble()

रिटर्न

एक डबल-सटीक फ़्लोटिंग पॉइंट संख्या 0.0 से अधिक या बराबर है, और 1.0 से कम है।

इसलिए यदि आप एक समान रूप से फैला हुआ यादृच्छिक बूल चाहते हैं तो आपको इसका उपयोग करना चाहिए >= 0.5

rand.NextDouble() >= 0.5

रेंज 1: [0.0 ... 0.5 [
रेंज 2: [0.5 ... 1.0]
| रेंज 1 | = | रेंज 2 |


10

सबसे तेज़। कॉलिंग विधि Random.Nextमें कम ओवरहेड है। नीचे विस्तार विधि 20% से अधिक तेजी से चलती है Random.NextDouble() > 0.5, और 35% से अधिक तेज़ी से Random.Next(2) == 0

public static bool NextBoolean(this Random random)
{
    return random.Next() > (Int32.MaxValue / 2);
    // Next() returns an int in the range [0..Int32.MaxValue]
}

सबसे तेज से तेज। Randomचालों का उपयोग करके, कक्षा के साथ यादृच्छिक रूप से और भी तेजी से उत्पन्न करना संभव है । उत्पन्न के 31 महत्वपूर्ण बिट्स का intउपयोग 31 बाद की बूलियन प्रस्तुतियों के लिए किया जा सकता है। नीचे दिया गया कार्यान्वयन पहले की तुलना में सबसे तेज 40% तेज है।

public class RandomEx : Random
{
    private uint _boolBits;

    public RandomEx() : base() { }
    public RandomEx(int seed) : base(seed) { }

    public bool NextBoolean()
    {
        _boolBits >>= 1;
        if (_boolBits <= 1) _boolBits = (uint)~this.Next();
        return (_boolBits & 1) == 0;
    }
}

धन्यवाद! स्क्रिप्ट लिखने के लिए UnityEngine का उपयोग करने वालों के लिए, सुनिश्चित करें कि System.Random का उपयोग करें और UnityEngine.Random का उपयोग न करें, क्योंकि वे एक ही चीज़ नहीं हैं!
डॉनकार्लोन

6

मैंने स्टॉपवॉच के साथ परीक्षण चलाए। 100,000 पुनरावृत्तियों:

System.Random rnd = new System.Random();
if (rnd.Next(2) == 0)
     trues++;

पूर्णांक की तरह सीपीयू, इसलिए अगला (2) विधि तेज थी। 3,700 बनाम 7,500ms, जो काफी पर्याप्त है। इसके अलावा: मुझे लगता है कि यादृच्छिक संख्या एक अड़चन हो सकती है, मैंने एकता में लगभग हर फ्रेम को बनाया, यहां तक ​​कि एक छोटे से दृश्य के साथ, जिसने मेरे सिस्टम को काफी धीमा कर दिया, इसलिए मैं एक यादृच्छिक बूल बनाने के लिए एक विधि खोजने की उम्मीद कर रहा था। इसलिए मैंने भी कोशिश की

if (System.DateTime.Now.Millisecond % 2 == 0)
       trues++;

लेकिन एक स्थिर फ़ंक्शन को कॉल करना 9,600ms के साथ धीमा था। एक कोशिश लायक़। अंत में मैंने तुलना को छोड़ दिया और केवल 100,000 यादृच्छिक मूल्यों का निर्माण किया, यह सुनिश्चित करने के लिए कि इंट बनाम दोहरी तुलना बीते समय को प्रभावित नहीं करती थी, लेकिन परिणाम बहुत अधिक था।


1
DateTime.Now बेहद धीमी गति से है। इसे जल्दी बनाने के लिए आदर्श रूप से हार्डवेयर पर निर्भर समाधान या कम से कम ओएस पर निर्भर होना चाहिए।
Do-do-new

का उपयोग करें DateTime.UtcNow, यह की तुलना में बहुत तेज है DateTime.Now
थियोडोर ज़ूलियास
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.