Rastgele bir boole oluşturmanın en hızlı yolu


87

Dolayısıyla, C # 'da rastgele bir bool oluşturmanın birkaç yolu vardır:

  • Random.Next () kullanarak: rand.Next(2) == 0
  • Random.NextDouble () Kullanımı: rand.NextDouble() > 0.5

Gerçekten bir fark var mı? Eğer öyleyse, hangisinin performansı gerçekten daha iyi? Yoksa görmediğim başka bir yol var mı, bu daha hızlı olabilir mi?



7
Bu gerçekten darboğaz mı?
Brian Rasmussen

2
Aslında çalıştırmadan (çünkü herhangi bir yöntem gülünç derecede hızlı olacaktır), benim tahminim NextBytesbir bayt dizisini önceden doldurmak, BitArraybunu bir boole koleksiyonuna dönüştürmek için kullanmak ve bu boole'leri a'dan Queueboşalana kadar almak ve ardından tekrarlamak olacaktır. süreç. Bu yöntemle, rasgele dağıtıcıyı yalnızca bir kez kullanırsınız, bu nedenle oluşturduğu herhangi bir ek yük yalnızca sırayı yeniden doldurduğunuzda gerçekleşir. Bu, normal Randomsınıf yerine güvenli bir rastgele sayı üreteci ile uğraşırken yararlı olabilir .
Joe Enos

2
@JoeEnos MS uygulamasında karışıklık yarattı NextBytes, bu yüzden şaşırtıcı derecede yavaş
CodesInChaos

1
@CodesInChaos Vay canına, bu ilginç - neyi kastettiğinizi görmek için bir parçalayıcıda baktım: buffer[i] = (byte)(this.InternalSample() % 256);- Bahsettiğiniz şeyin bu olduğunu varsayıyorum, bu rastgele tamsayıyı alıp 3 bayta bölebilirler. , bayt dizisi işin yaklaşık 1 / 3'ü ile doldurulur. Bunun bir nedeni olup olmadığını veya sadece geliştiriciler tarafından bir gözetim olup olmadığını merak ediyorum.
Joe Enos

Yanıtlar:


72

İlk seçenek - rand.Next(2)perde Aşağıdaki kod arkasında yürütür:

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

ve ikinci seçenek için - rand.NextDouble():

return this.Sample();

İlk seçenek maxValuedoğrulama, çarpma ve çevrim içerdiğinden , ikinci seçenek muhtemelen daha hızlıdır .


Teşekkür ederim, tüm bilmek istediğim buydu.
2013

5
Kendi zamanlamalarım, ikinci seçeneğin ilkinden yaklaşık% 5 daha hızlı olduğunu söylüyor.
ClickRick

62

İkinci seçenek için küçük geliştirme :

MSDN'ye göre

public virtual double NextDouble()

İadeler

0,0'a eşit veya daha büyük ve 1,0'dan küçük çift duyarlıklı kayan nokta sayısı.

Bu nedenle, eşit olarak dağıtılmış rastgele bir bool istiyorsanız, kullanmalısınız >= 0.5

rand.NextDouble() >= 0.5

Aralık 1: [0,0 ... 0,5 [
Aralık 2: [0,5 ... 1,0 [
| Aralık 1 | = | Aralık 2 |


10

En hızlı. Yöntemi çağırmak Random.Nextdaha az ek yüke sahiptir. Aşağıdaki uzantı yöntemi Random.NextDouble() > 0.5, % 20 daha hızlı ve% 35 daha hızlı çalışır 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]
}

En hızlıdan daha hızlı. RandomHile kullanarak sınıfla daha hızlı rastgele boole'lar oluşturmak mümkündür . Oluşturulan 31 önemli bit, intsonraki 31 boole üretimi için kullanılabilir. Aşağıdaki uygulama, daha önce açıklanan en hızlı olandan% 40 daha hızlıdır.

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;
    }
}

Teşekkürler! Komut dosyaları yazmak için UnityEngine kullananlar için, aynı şey olmadıkları için UnityEngine.Random'u değil System.Random'u kullandığınızdan emin olun!
DonCarleone

6

Kronometre ile testler yaptım. 100.000 yineleme:

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

CPU'lar tam sayıları sever, bu nedenle Next (2) yöntemi daha hızlıydı. 3.700 ms'ye karşılık 7.500 ms, bu oldukça önemli. Ayrıca: Rastgele sayıların bir darboğaz olabileceğini düşünüyorum, Unity'de her karede yaklaşık 50 tane yarattım, küçük bir sahnede bile sistemimi gözle görülür şekilde yavaşlattım, bu yüzden rastgele bir bool oluşturmak için bir yöntem bulmayı umuyordum. Ben de denedim

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

ancak statik bir işlevi çağırmak 9.600 ms ile daha da yavaştı. Denemeye değer. Sonunda karşılaştırmayı atladım ve int-double karşılaştırmasının geçen süreyi etkilemediğinden emin olmak için sadece 100.000 rastgele değer oluşturdum, ancak sonuç hemen hemen aynıydı.


1
DateTime.Now herkesin bildiği gibi yavaş. Hızlandırmak için ideal olarak donanıma bağlı çözümler veya en azından işletim sistemine bağımlı çözümler kullanılmalıdır.
Do-do-new

Kullanımdan DateTime.UtcNowçok daha hızlıdır DateTime.Now.
Theodor Zoulias
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.