2012-11-13 24 views
20

これは非常に論理的な説明があるかもしれませんが、なぜシード02,147,483,647が.NETのRandom Class (System)同じ「ランダム」シーケンスを生成する2つの異なるシード

クイックコード例:

var random1 = new Random(0); 
var random2 = new Random(1); 
var random3 = new Random(int.MaxValue); //2,147,483,647 

var buffer1 = new byte[8]; 
var buffer2 = new byte[8]; 
var buffer3 = new byte[8]; 

random1.NextBytes(buffer1); 
random2.NextBytes(buffer2); 
random3.NextBytes(buffer3); 

for (int i = 0; i < 8; i++) 
{ 
    Console.WriteLine("{0}\t\t{1}\t\t{2}", buffer1[i], buffer2[i], buffer3[i]); 
} 

出力:あなたが見ることができるように

26  70  26 
12  208  12 
70  134  76 
111  130  111 
93  64  93 
117  151  115 
228  228  228 
216  163  216 

、第一及び第3のシーケンスが同じです。誰かがこれを私に説明してもらえますか?

EDIT:明らかに、これらの配列は同じではないことが指摘されています。しかし、彼らは非常に似ています。

+1

他の任意の数字を試してみましたか?そうであれば、その数字で同じ結果が得られますか? –

+3

'System.Random'は多くの点でデザインごとに壊れています。これはその一つです。 – CodesInChaos

+3

+1非常に興味深い観察のために! – quetzalcoatl

答えて

10

この理由は、Randomクラスが種から擬似乱数列を導出するために使用される導関数に関係しています。 答え、したがって、数学的です(私の能力を超えています)。

確かに、2つの異なる種が必然的に異なる配列を生成するという保証はないと私は信じています。

編集わかりました - 私は何をしたかbitbonkするつもりです - しかし、なぜを説明します。

public Random(int Seed) 
{ 
    int num = (Seed == -2147483648) ? 2147483647 : Math.Abs(Seed); 
    int num2 = 161803398 - num; 
    this.SeedArray[55] = num2; 
    int num3 = 1; 
    for (int i = 1; i < 55; i++) 
    { 
     int num4 = 21 * i % 55; 
     this.SeedArray[num4] = num3; 
     num3 = num2 - num3; 
     if (num3 < 0) 
     { 
      num3 += 2147483647; 
     } 
     num2 = this.SeedArray[num4]; 
    } 
    for (int j = 1; j < 5; j++) 
    { 
     for (int k = 1; k < 56; k++) 
     { 
      this.SeedArray[k] -= this.SeedArray[1 + (k + 30) % 55]; 
      if (this.SeedArray[k] < 0) 
      { 
       this.SeedArray[k] += 2147483647; 
      } 
     } 
    } 
    this.inext = 0; 
    this.inextp = 21; 
    Seed = 1; 
} 

私たちが実際に理由を確認するためにコードに行き過ぎする必要はありません - 上から下にコードを読み取るこれらの種子は0であるとき、上記のコードによって格納される値は、種子は2147483647である場合:

int num = (Seed == -2147483648) ? 2147483647 : Math.Abs(Seed); 
    => num is 0 and 2147483647 

int num2 = 161803398 - num; 
    => num2 is 161803398 and -1985680249 

this.SeedArray[55] = num2; 
    => this.SeedArray is as above in both cases 

int num3 = 1; 
for (int i = 1; i < 55; i++) 
{ 
    int num4 = 21 * i % 55 
    this.SeedArray[num4] = num3; 

    => num4 is 21, SeedArray[21] is 1 

num3 = num2 - num3 
    => num3 is 161803397 and -1985680250 

if(num3 < 0) 
    num3 += 2147483647 

    => num3 is 161803397 and 161803397 

非常に最初のループの後、アルゴリズムはすでに2つのシード値に対して収束しています。

質問に指摘したように編集

- 配列は同じではありません - しかし、彼らは明らかに非常によく似ています - と、ここで私たちはその類似性の理由を見ることができます。

+1

おかげで詳細!特にこのスレッドが証明するように、{0、int.Max、int.Min}は同じシードになります。私は、もしこの実装が他のそのような共種子をどれだけ持っているのだろうか?それらの多くがある場合、それは記事の素敵な基盤を形成するでしょう:) – quetzalcoatl

+0

+1いい仕事です!私はSystem.Randomの実装がまともな乱数生成器であることを意図していないが、あなたはその良さについて考える必要がなくなるたびに使用する準備ができて、非常に簡単なルーチンだと思う。そのため、(フレームワーク内であっても)非常に多くの異なる実装が存在します。 –

+0

@Adrianoしかし、ドキュメンテーションはもっと意味します。 http://msdn.microsoft.com/en-us/library/ctssatww.aspxアプリケーションで異なる乱数シーケンスが必要な場合は、このコンストラクタを異なるシード値で繰り返し呼び出します。 – Paparazzi

関連する問題