【问题标题】:Fastest way to generate a random boolean生成随机布尔值的最快方法
【发布时间】:2013-10-12 00:46:44
【问题描述】:

所以在 C# 中创建随机布尔值有几种方法:

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

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

【问题讨论】:

  • 这真的是瓶颈吗?
  • 如果不实际运行它(因为任何方法都会非常快),我的猜测是使用 NextBytes 预填充字节数组,使用 BitArray 将其转换为布尔值,并从Queue 中检索这些布尔值,直到它被清空,然后重复该过程。使用这种方法,您只使用一次随机化器,因此它产生的任何开销只会在您重新填充队列时发生。这在处理安全随机数生成器而不是常规的 Random 类时可能很有用。
  • @JoeEnos MS 搞砸了NextBytes 的实现,所以出奇的慢
  • @CodesInChaos 哇,这很有趣——我只是在反汇编程序中查看了它,看看你指的是什么:buffer[i] = (byte)(this.InternalSample() % 256);——我假设这就是你在说的,他们可以已经取了那个随机整数并将其拆分为 3 个字节,用大约 1/3 的工作填充字节数组。我想知道这是有原因的,还是只是开发人员的疏忽。

标签: c# performance random boolean


【解决方案1】:

第一个选项 - 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 验证、乘法和强制转换,第二个选项可能更快

【讨论】:

  • 谢谢,这就是我想知道的全部内容。
  • 我自己的时间说第二个选项比第一个快 5% 左右。
【解决方案2】:

第二个选项的小改进:

根据MSDN

public virtual double NextDouble()

返回

大于等于 0.0 且小于 1.0 的双精度浮点数。

因此,如果您想要一个均匀分布的随机布尔值,您应该使用 &gt;= 0.5

rand.NextDouble() >= 0.5

范围 1:[0.0 ... 0.5[
范围 2:[0.5 ... 1.0[
|范围 1| = |范围 2|

【讨论】:

    【解决方案3】:

    最快。调用方法Random.Next 的开销更少。下面的扩展方法比Random.NextDouble() &gt; 0.5快20%,比Random.Next(2) == 0快35%。

    public static bool NextBoolean(this Random random)
    {
        return random.Next() > (Int32.MaxValue / 2);
        // Next() returns an int in the range [0..Int32.MaxValue]
    }
    

    比最快更快。 使用技巧可以更快地生成具有Random 类的随机布尔值。生成的int 的 31 个有效位可用于 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,因为它们不是一回事!
    【解决方案4】:

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

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

    CPU 类似于整数,因此 Next(2) 方法更快。 3,700 对 7,500 毫秒,这是相当可观的。 另外:我认为随机数可能是一个瓶颈,我在 Unity 中每帧创建大约 50 个,即使有一个小场景明显减慢了我的系统,所以我也希望找到一种方法来创建随机布尔值。 所以我也尝试了

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

    但调用静态函数甚至更慢,需要 9,600 毫秒。值得一试。 最后我跳过了比较,只创建了 100,000 个随机值,以确保 int 与 double 比较不会影响经过的时间,但结果几乎相同。

    【讨论】:

    • DateTime.Now 是出了名的慢。理想情况下,应该使用依赖于硬件的解决方案或至少依赖于操作系统的解决方案来加快速度。
    • 使用DateTime.UtcNow,比DateTime.Now快很多。
    猜你喜欢
    • 2015-12-29
    • 2017-09-05
    • 2015-08-28
    • 2010-10-26
    • 1970-01-01
    • 2016-08-13
    • 2016-05-23
    • 2022-10-04
    相关资源
    最近更新 更多