117

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?

8
  • 21
    ericlippert.com/2012/12/17/performance-rant Commented Oct 4, 2013 at 21:26
  • 12
    Is this really the bottleneck? Commented Oct 4, 2013 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. Commented Oct 4, 2013 at 21:31
  • 2
    @JoeEnos MS messed up the implementation of NextBytes, so it's surprisingly slow Commented Oct 5, 2013 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. Commented Oct 5, 2013 at 14:56

4 Answers 4

88

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|

Sign up to request clarification or add additional context in comments.

Comments

84

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.

2 Comments

Thank you, that's all I wanted to know.
My own timings say that the second option is around 5% faster than the first.
26

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

1 Comment

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!
10

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 Comments

DateTime.Now is notoriously slow. Ideally hardware-dependent solutions or at least OS-dependent should be used to make it quick.
Use DateTime.UtcNow, it is much faster than DateTime.Now.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.