2011-10-14 9 views
3

ランダムな整数を生成している間、少なくとも私にとって興味深いものはほとんど見つからなかったので、私は自分自身に説明することができないので、ここに投稿すると思った。C#乱数int - 謎を生成する

私のニーズは単純でした:ランダムインテグラル(Int32)IDを生成していて、衝突を最小限に抑えることを目指していました。生成時間は問題ではありませんでした。

私はランダムな整数を生成するため、これらの方法を試してみました:

1)RNDは、方法#3からの種子を持つランダムなタイプのクラスのフィールドである

return rnd.Next(); 

2)RNDが再び方法#3からの種子を持つランダムなタイプのクラスフィールドである

return rnd.Next(Int32.MinValue, Int32.MaxValue); 

3)

var buffer = new byte[sizeof(int)]; 
    using (var rng = new RNGCryptoServiceProvider()) 
    { 
     rng.GetBytes(buffer); 
    }    
    return BitConverter.ToInt32(buffer, 0); 

注:私はまた、RNGCryptoServiceProviderクラスフィールドとしてGCの作業を容易にするcontaingクラスの初期化時に一度初期化することを持ってしようとしたが、私はそう思っ生成するために同じ時間がかかりましたこれは「よりランダム」になります。

4)

return new Random(Method3()).Next(); 

5)

return new Random(Method3()).Next(Int32.MinValue, Int32.MaxValue); 

私はすべての呼び出しに新しいランダム(int型の種子)を作成すると、右、時間がかかり、あまり衝突があることを、知っていますか?

さて、今や謎の部分です。私は、ほとんどの衝突はメソッド#1と#2を持ち、#1はわずかに速く、より衝突が少なく、衝突の少ないメソッド#4と#5を持ち、#4はわずかに速く衝突のないメソッド# 3はある種の妥協であろう。

私は私の題材を証明するためのテストをしました。私は10倍(平均するために)のすべての方法を使用して乱数の百万を生成し、100万の数字を生成するためにかかった衝突の平均数と平均時間を取った。結果(下記)は私にとって少し驚きです。

結果:期間は時間である:分:秒:ミリ秒形式

Method1: AvgCollisions: 235, AvgDuration: 00:00:00.3561967 
Method2: AvgCollisions: 116, AvgDuration: 00:00:00.4042033 
Method3: AvgCollisions: 115, AvgDuration: 00:00:04.6037259 
Method4: AvgCollisions: 234, AvgDuration: 00:00:09.2195856 
Method5: AvgCollisions: 233, AvgDuration: 00:00:09.1788223 

は、私は再びテストを数回実行し、それは同じ年ごろ常にでした。

あなたにも奇妙なのですか?私が仮定したことはすべて驚きではありませんが、その結果は私にとって意味があります。乱数を生成するにはmethod2が最もランダムで、最も速く、生成される最小値と最大値を設定できます。私はそれをテストする方法を知らないので、Method2がMethod3よりどれだけ予測可能かを知らないでください。

私は間違っていますか、または方法#4と#5の衝突が最も少なく、衝突の割合が常に同じである理由を説明できますか?それはランダムではありませんか?

EDIT: ここで私がやったこのテストのVisual Studioの2010年のソリューションです:http://bit.ly/nxLODw

+1

最初の結果に表示される衝突の回数は確かですか?他のすべてのものは、[this](http://stackoverflow.com/questions/1654887/random-next-returns-always-the-same-values)(そして何千もの同様の議論がここにあります - これは一つです上位5つのプログラミング誤解のうちの1つ)。テストケースを投稿できますか? –

+4

あなたの#4 /#5仮定は誤りです。乱数が必要なときには 'new Random()'を呼び出すべきではありません。これを一度だけ行います。 –

+0

+1マイケルペトロッタ。 'その他多くの似たようなディスカッション ' –

答えて

6

だけ奇妙な振る舞いはメソッドである5.方法1、4では

、あなたが生成するには、 0〜int.MaxValueの範囲の数値。

メソッド2,3および5では、int.MinValueからint.MaxValueの範囲の数値を生成します。

したがって、方法2と3では、範囲が約2倍大きく、方法1,4と比較して約半分の衝突があります。これはかなり普通のようです。

なぜ、方法5は、より大きな範囲で数値を生成するにもかかわらず、方法1および4と同数の衝突を生成するのはなぜですか?さて、それはSystem.Randomコンストラクタが種の絶対値を取ることが分かります。つまり、ランダムシーケンスの数を半分に減らすことができます。したがって、より大きな範囲から数値を取得しても、より少ない数のシーケンスから数値を生成できます。

+0

あなたはポイントを持っています。どのように私は1と4が正の数を生成することを逃すことができるか分からない..今それは私には意味がある、thx。 – MSkuta

+0

新しい質問が出てきますが、すべてのメソッドの衝突数が同じなのはなぜですか?メソッド3は最小限の衝突しかないでしょうか?それはRNGクリプトです... – MSkuta

+0

本当に。あなたは '本当に'ランダムな順序でも衝突するでしょう。可能な数字の約1/2000または1/4000しか生成していないので、あなたのデニシティはあまりにも小さく、とにかく違いを見ることはできません。 –

0

あなたがそこにいる間、あなたのように#3を変更することがあります。

 var buffer = new byte[sizeof(int)]; 

     using (var rng = new RNGCryptoServiceProvider()) 
     { 
      rng.GetBytes(buffer); 
     } 

     return BitConverter.ToInt32(buffer, 0); 

これは、a)は、あなたの配列はint型のサイズ(というよりマジックナンバー4である保証)およびb)適切にのうち、RNGCryptoServiceProviderが処分されます。

+0

ええ、それはおそらく良い考えです。 – MSkuta

関連する問題