生成随机布尔值的最快方法

因此,有几种方法可以在 C # 中创建一个随机 bool:

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

真的有区别吗?如果是这样,那么哪一个实际上具有更好的性能呢?或者还有其他我没想到的方法,可能会更快?

93617 次浏览

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.

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|

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.

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