ランダムなブール値を生成する最速の方法


87

したがって、C#でランダムブール値を作成する方法はいくつかあります。

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

本当に違いはありますか?もしそうなら、どちらが実際に優れたパフォーマンスを持っていますか?それとも私が見なかった別の方法がありますか、それはさらに速いかもしれませんか?



7
これは本当にボトルネックですか?
ブライアンラスムッセン2013年

2
実際に実行せずに(どのメソッドもばかばかしいほど高速になるため)、NextBytesバイト配列を事前入力し、BitArrayそれをブール値のコレクションに変換し、Queue空になるまでそれらのブール値を取得してから繰り返すのが私の推測です。プロセス。この方法では、ランダマイザーを1回しか使用しないため、ランダマイザーが作成するオーバーヘッドは、キューを補充したときにのみ発生します。これは、通常のRandomクラスではなく、安全な乱数ジェネレーターを扱う場合に役立ちます。
ジョー・エノス

2
@JoeEnos MSはの実装を台無しにしたNextBytesので、驚くほど遅い
CodesInChaos 2013年

1
@CodesInChaosうわー、それは興味深いです-逆アセンブラで調べて、あなたが何を参照しているかを確認しました:buffer[i] = (byte)(this.InternalSample() % 256);-それがあなたが話していることだと思います、彼らはそのランダムな整数を取り、それを3バイトに分割できたはずです、バイト配列に約1/3の作業を入力します。それには理由があったのか、それとも開発者の見落としだったのだろうか。
ジョーエノス2013年

回答:


72

最初のオプション-rand.Next(2)舞台裏で実行次のコード:

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

そして2番目のオプションの場合- rand.NextDouble()

return this.Sample();

最初のオプションにはmaxValue検証、乗算、キャストが含まれているため、2番目のオプションの方がおそらく高速です。


ありがとう、それが私が知りたかったすべてです。
timedt 2013年

5
私自身のタイミングによると、2番目のオプションは最初のオプションよりも約5%高速です。
ClickRick 2014年

60

2番目のオプションの小さな拡張:

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を呼び出すと、オーバーヘッドが少なくなります。以下の拡張メソッドはRandom.NextDouble() > 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トリックを使用することで、クラスでランダムなブール値をさらに高速に生成することができます。生成された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を使用してスクリプトを作成する場合は、UnityEngine.RandomではなくSystem.Randomを使用してください。これらは同じものではないためです。
DonCarleone

6

ストップウォッチでテストを実行しました。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,600msとさらに遅くなりました。試してみる価値。最後に、intとdoubleの比較が経過時間に影響を与えないように、比較をスキップして100,000のランダム値のみを作成しましたが、結果はほぼ同じでした。


1
DateTime.Nowは悪名高いほど遅いです。理想的には、ハードウェアに依存するソリューション、または少なくともOSに依存するソリューションを使用して、迅速に処理する必要があります。
Doが-DO-新しい

を使用するとDateTime.UtcNow、よりもはるかに高速ですDateTime.Now
TheodorZoulias19年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.