ホセのデイライトダイス
または、真のランダム単位を生成する簡単な方法はありますか?
私は認めます、それはOQではありません。真のものではないランダムな uint を生成するより高速な方法があることが明らかになります。それにもかかわらず、何らかの理由で非フラットなディストリビューションが必要な場合を除いて、それらを生成することにあまり興味を持っている人はいないと思います。C# で簡単かつ迅速に行うための調査から始めましょう。私がコードを書くとき、Easy と Fast はしばしば同義語のように振る舞います。
最初: いくつかの重要なプロパティ
MSDNを参照してください。
Random
コンストラクタ:
Random()
Random
:時間依存のデフォルト シード値を使用して、クラスの新しいインスタンスを初期化します。
Random(int seed)
Random
:指定されたシード値を使用して、クラスの新しいインスタンスを初期化します。
パフォーマンスを向上させるには、新しいオブジェクトをRandom
繰り返し作成して 1 つの乱数を生成するのではなく、1 つのオブジェクトを作成して時間の経過とともに多くの乱数を生成します。Random
private static Random rand = new Random();
Random
メソッド:
rand.Next()
: ゼロ以上で 未満の正の乱数を返しますint.MaxValue
。
rand.Next(int max)
: 0 以上で max 未満の正の乱数を返します。max は 0 以上である必要があります。
rand.Next(int min, int max)
: min 以上で max 未満の正の乱数を返します。max は min 以上である必要があります。
Homework は、rand.Next()
が の約 2 倍速いことを示していrand.Next(int max)
ます。
2 番目: 解決策。
正の int が 2 ビットしかない場合、符号ビットは忘れてください。ゼロであり、rand.Next()
等しい確率で 3 つの異なる値を返します。
00
01
10
真の乱数の場合、最上位ビットと同じように、最下位ビットは 1 と同じ頻度で 0 になります。
最下位ビットで機能させるには、次のようにします。rand.Next(2)
int に 3 ビットがあり、rand.Next()
7 つの異なる値を返すとします。
000
001
010
011
100
101
110
最下位 2 ビットで機能させるには、次のようにします。rand.Next(4)
int にnビットがあるとします。nビット
で機能させるには、次を使用します。rand.Next(1 << n)
最大 30 ビットで動作させるには、次を使用します: rand.Next(1 << 30)
It's the maximum, 1 << 31 is large than int.MaxValue
.
これは、真のランダム単位を生成する方法につながります。
private static uint rnd32()
{
return (uint)(rand.Next(1 << 30)) << 2 | (uint)(rand.Next(1 << 2));
}
簡単なチェック: ゼロを生成する可能性は?
1 << 2 = 4 = 2 2 , 1 << 30 = 2 30
ゼロの可能性は次のとおりです: 1/2 2 * 1/2 30 = 1/2 32
ゼロを含む uint の総数: 2 32
日光と同じくらい澄んでいて、スモッグ アラートはありませんね。
最後に:誤解を招く考え。
を使用してより速く行うことは可能ですかrand.Next()
int.Maxvalue is: (2^31)-1
The largest value rand.Next() returns is: (2^31)-2
uint.MaxValue is: (2^32)-1
をrand.Next()
2 回使用して結果を加算すると、可能な最大値は次のようになります。
2*((2^31)-2) = (2^32)-4
uint.MaxValue との違いは次のとおりです。
(2^32)-1 - ((2^32)-4) = 3
に到達するにuint.MaxValue
は、別の値をrand.Next(4)
追加する必要があるため、次のようになります。
rand.Next() + rand.Next() + rand.Next(4)
ゼロを生み出すチャンスは?
おおよそ: 1/2 31 * 1/2 31 * 1/4 = 1/2 64 、それは 1/2 32であるべきです
ちょっと待ってください。
2 * rand.Next() + rand.Next(4)
繰り返しますが、ゼロを生成するチャンスは何ですか?
おおよそ: 1/2 31 * 1/4 = 1/2 33、小さすぎて真にランダムにはなりません。
別の簡単な例:
rand.Next(2) + rand.Next(2)
、考えられるすべての結果:
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 2
等確率?まさかホセ。
結論: 真の乱数を加算すると乱数が得られますが、真の乱数ではありません。公正なサイコロを2つ投げて……