2012-11-13 9 views
20

Vielleicht gibt es eine sehr logische Erklärung dafür, aber ich kann einfach nicht zu verstehen, warum die Samen 0 und 2,147,483,647 produzieren die gleiche "zufällige" Sequenz, mit .NET Random Class (System) .Zwei verschiedene Samen produzieren die gleiche "zufällige" Sequenz

Schnellcodebeispiel:

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]); 
} 

Ausgang:

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

Wie Sie sehen können, die erste und die dritte Folge sind die gleichen. Kann mir bitte jemand das erklären?

BEARBEITEN: Offenbar, wie alro wies darauf hin, sind diese Sequenzen nicht die gleichen. Aber sie sind sehr ähnlich.

+1

Haben Sie schon eine andere beliebige Zahl ausprobiert, und wenn ja, erhalten Sie mit dieser Zahl die gleichen Ergebnisse? –

+3

'System.Random' ist in vielerlei Hinsicht defekt. Dies ist einer von ihnen. – CodesInChaos

+3

+1 für sehr interessante Beobachtung! – quetzalcoatl

Antwort

10

Nun, der Grund wird verbunden mit was auch immer Ableitungsfunktion von der Random-Klasse verwendet wird, um eine pseudo-zufällige Sequenz aus dem Seed abzuleiten. Die echte Antwort ist daher mathematisch (und über meine Fähigkeit hinaus).

In der Tat - ich glaube nicht, es gibt keine Garantie, dass zwei verschiedene Samen sowieso unterschiedliche Sequenzen erzeugen werden.

bearbeiten Ok - ich tun werde, was bitbonk getan hat - aber warum erklären:

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; 
} 

Wir brauchen eigentlich nicht zu weit in den Code zu gehen, zu sehen, warum - den Code von oben nach unten zu lesen, das sind die Werte, die durch den obigen Code gespeichert wird, wenn der Samen 0 ist und wenn der Samen ist 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 

Nach der ersten Schleife konvergierte der Algorithmus bereits für die beiden Startwerte.

bearbeiten

Wie auf die Frage hingewiesen wurde - die Sequenzen sind nicht gleich - aber sie sind offensichtlich sehr sehr ähnlich - und hier können wir den Grund für diese Ähnlichkeit sehen.

+1

Danke für die Details! Bemerkenswerterweise ergibt {0, int.Max, int.Min} denselben Keim, wie dieser Thread beweist. Ich frage mich, ob und wie viel diese Implementierung andere solche Co-Samen hat? Wenn es mehr von ihnen gibt, würde das eine gute Basis für einen Artikel bilden :) – quetzalcoatl

+0

+1 Netter Job! @quetzalcoatl ich denke, System.Random Implementierung soll nicht einmal ein anständiger Zufallszahlengenerator sein, sondern eine gebrauchsfertige, sehr schnelle Routine, die man jedes Mal verwenden kann, wenn man nicht einmal über seine Güte nachdenken muss. Deshalb gibt es (sogar innerhalb des Rahmens) so viele verschiedene Implementierungen davon. –

+0

@Adriano Aber die Dokumentation impliziert mehr. http://msdn.microsoft.com/en-us/library/ctssatww.aspx Wenn Ihre Anwendung verschiedene Zufallszahlenfolgen erfordert, rufen Sie diesen Konstruktor wiederholt mit anderen Startwerten auf. – Paparazzi

Verwandte Themen