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


87

因此,有几种在C#中创建随机布尔的方法:

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

真的有区别吗?如果是这样,哪个实际上具有更好的性能?还是有我看不到的另一种方法,甚至可能更快?



7
这真的是瓶颈吗?
Brian Rasmussen

2
在没有实际运行的情况下(因为任何方法都会非常快),我的猜测是用来NextBytes预填充字节数组,用于BitArray将其转换为布尔值的集合,并从a中检索这些布尔值,Queue直到将其清空为止,然后重复过程。使用此方法,您只需使用随机数发生器一次,因此它产生的任何开销仅在重新填充队列时发生。在处理安全随机数生成器而不是常规Random类时,这可能很有用。
Joe Enos

2
@JoeEnos MS弄乱了的实现NextBytes,因此它出奇的慢
CodesInChaos 2013年

1
@CodesInChaos哇,这很有趣-我只是在反汇编程序中查看了一下,然后查看了您所指的内容:buffer[i] = (byte)(this.InternalSample() % 256);-我假设这就是您在说的,因为他们可以将随机整数分割成3个字节,用大约1/3的工作填充字节数组。我想知道是否有原因,或者仅仅是开发人员的疏忽。
Joe Enos 2013年

Answers:


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%。
ClickRick 2014年

60

第二个选项的小改进:

根据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 |


9

最快的。调用该方法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,因为它们不是同一件事!
DonCarleone

6

我用秒表进行了测试。100,000次迭代:

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

CPU喜欢整数,因此Next(2)方法更快。3,700对7,500ms,这是相当可观的。另外:我认为随机数可能是一个瓶颈,即使在一个很小的场景中,我在Unity中每帧创建了大约50个帧,这明显降低了我的系统的速度,所以我也希望找到一种创建随机布尔值的方法。所以我也试过了

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

但是调用静态函数的速度甚至比9600ms还要慢。值得一试。最后,我跳过了比较,仅创建了100,000个随机值,以确保int vs. double比较不会影响经过的时间,但结果几乎相同。


1
DateTime.Now非常慢。理想情况下,应使用依赖于硬件的解决方案或至少依赖于OS的解决方案来使其快速运行。
做新的

使用时DateTime.UtcNow,它比速度快得多DateTime.Now
Theodor Zoulias
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.