108

So there is several ways of creating a random bool in C#:

  • Using Random.Next(): rand.Next(2) == 0
  • Using Random.NextDouble(): rand.NextDouble() > 0.5

Is there really a difference? If so, which one actually has the better performance? Or is there another way I did not see, that might be even faster?

Domecraft
  • 1,645
  • 15
  • 26
timedt
  • 1,302
  • 2
  • 9
  • 14
  • 21
    http://ericlippert.com/2012/12/17/performance-rant/ – Austin Salonen Oct 04 '13 at 21:26
  • How many do you intend to create? – Austin Salonen Oct 04 '13 at 21:28
  • 11
    Is this really the bottleneck? – Brian Rasmussen Oct 04 '13 at 21:30
  • 2
    Without actually running it (because any method will be ludicrously fast), my guess would be to use `NextBytes` to pre-populate a byte array, use `BitArray` to turn that into a collection of booleans, and retrieve those booleans from a `Queue` until it's emptied, then repeat the process. With this method, you're only using the randomizer once, so any overhead it creates only happens when you refill the queue. This could be useful when dealing with a secure random number generator rather than the regular `Random` class. – Joe Enos Oct 04 '13 at 21:31
  • I might need to generate up to 2^18 or just 8, depends on the outcome of the one before. – timedt Oct 04 '13 at 21:32
  • 2
    @JoeEnos MS messed up the implementation of `NextBytes`, so it's surprisingly slow – CodesInChaos Oct 05 '13 at 12:37
  • 1
    @CodesInChaos Wow, that's interesting - I just looked it up in a disassembler to see what you were referring to: `buffer[i] = (byte)(this.InternalSample() % 256);` - I'm assuming that's what you're talking about, that they could have taken that random integer and split it into 3 bytes, populating the byte array with about 1/3 the work. I wonder if there was a reason for that or if it was just an oversight by the developers. – Joe Enos Oct 05 '13 at 14:56
  • 1
    @JoeEnos I never saw the code, but the performance is about as bad as calling `Next` for each byte, instead of taking advantage of all 31 bits. But since `System.Random` has bad design and implementation at pretty much every level, this is one of my smaller gripes. – CodesInChaos Oct 05 '13 at 14:59

5 Answers5

82

The first option - rand.Next(2) executes behind the scenes the following code:

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

and for the second option - rand.NextDouble():

return this.Sample();

Since the first option contains maxValue validation, multiplication and casting, the second option is probably faster.

martijnn2008
  • 3,552
  • 5
  • 30
  • 40
Aviran Cohen
  • 5,581
  • 4
  • 48
  • 75
79

Small enhancement for the second option:

According to MSDN

public virtual double NextDouble()

returns

A double-precision floating point number greater than or equal to 0.0, and less than 1.0.

So if you want an evenly spread random bool you should use >= 0.5

rand.NextDouble() >= 0.5

Range 1: [0.0 ... 0.5[
Range 2: [0.5 ... 1.0[
|Range 1| = |Range 2|

DaRich
  • 937
  • 8
  • 13
23

The fastest. Calling the method Random.Next has the less overhead. The extension method below runs 20% faster than Random.NextDouble() > 0.5, and 35% faster than 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]
}

Faster than the fastest. It is possible to generate random booleans with the Random class even faster, by using tricks. The 31 significant bits of a generated int can be used for 31 subsequent boolean productions. The implementation below is 40% faster than the previously declared as the fastest.

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;
    }
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
  • 3
    Thanks! For those using UnityEngine to write scripts, make sure to use System.Random and not UnityEngine.Random, as they are not the same thing! – DonCarleone Nov 06 '20 at 00:24
9

I ran tests with stopwatch. 100,000 iterations:

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

CPUs like integers, so the Next(2) method was faster. 3,700 versus 7,500ms, which is quite substantial. Also: I think random numbers can be a bottleneck, I created around 50 every frame in Unity, even with a tiny scene that noticeably slowed down my system, so I also was hoping to find a method to create a random bool. So I also tried

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

but calling a static function was even slower with 9,600ms. Worth a shot. Finally I skipped the comparison and only created 100,000 random values, to make sure the int vs. double comparison did not influence the elapsed time, but the result was pretty much the same.

  • 2
    DateTime.Now is notoriously slow. Ideally hardware-dependent solutions or at least OS-dependent should be used to make it quick. – Do-do-new May 10 '19 at 14:17
  • Use [`DateTime.UtcNow`](https://learn.microsoft.com/en-us/dotnet/api/system.datetime.utcnow), it is much faster than `DateTime.Now`. – Theodor Zoulias Jun 26 '19 at 13:42
-2

Based on answers here, Below is the code I used to generate random bool value.

  Random rand = new Random();
  bool randomBool = rand.NextDouble() >= 0.5;

References:

Generate a random boolean

https://stackoverflow.com/a/28763727/2218697

Shaiju T
  • 6,201
  • 20
  • 104
  • 196