2012-11-13 10 views
20

Może jest to bardzo logiczny wytłumaczenie dla tego, ale ja po prostu nie potrafię zrozumieć, dlaczego nasiona 0 i 2,147,483,647 wytwarzają taką samą sekwencję „Random”, przy użyciu .NET na Random Class (System) .Dwa różne nasiona produkujące ten sam „” losową sekwencję

Krótki przykład kodu:

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

wyjściowa:

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

Jak widać, pierwszy i trzeci ciąg są takie same. Czy ktoś może mi to wyjaśnić?

EDIT: Najwyraźniej, jak wspomniano, te sekwencje nie są takie same. Ale są bardzo podobne.

+1

Czy wypróbowałeś inny arbitralny numer, a jeśli tak, to czy uzyskujesz te same wyniki z tym numerem? –

+3

'System.Random' jest rozbity po projekcie na wiele sposobów. To jedna z nich. – CodesInChaos

+3

+1 za bardzo interesującą obserwację! – quetzalcoatl

Odpowiedz

10

Cóż, powód będzie związany z dowolną funkcją pochylenia używaną przez klasę losową do wyprowadzenia pseudolosowej sekwencji z nasienia. Dlatego odpowiedź brzmi matematycznie (i poza moimi możliwościami).

Rzeczywiście - nie sądzę, że istnieje jakakolwiek gwarancja, że ​​dwa różne nasiona i tak z konieczności wygenerują różne sekwencje.

Edit Ok - ja zrobię co bitbonk zrobiła - ale wyjaśnić dlaczego:

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

Nie rzeczywiście trzeba iść zbyt daleko do kodu, aby zobaczyć, dlaczego - odczyt kodu z góry do dołu są to wartości, które będą składowane w wyżej kodu gdy nasiona są 0 a gdy nasiona są 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 

Już po pierwszej pętli algorytm był już zbieżny dla dwóch wartości początkowych.

Edit

Jak zostało wskazane w pytaniu - sekwencje nie są takie same - ale są one wyraźnie bardzo podobny - i tu widzimy przyczynę tego podobieństwa.

+1

Dzięki za szczegóły! W szczególności {0, int.Max, int.Min} dają w rezultacie to samo nasiono, co udowodnił ten wątek. Zastanawiam się, czy i na ile ta implementacja ma inne tego typu dodatkowe nasiona? Jeśli jest ich więcej, to stanowiłoby dobrą bazę do artykułu :) – quetzalcoatl

+0

+1 Dobra robota! @quetzalcoatl well Myślę, że implementacja System.Random nie ma być nawet przyzwoitym generatorem liczb losowych, ale gotową do użycia, bardzo szybką procedurą do użycia za każdym razem, gdy nie musisz nawet myśleć o jej dobroci. Właśnie dlatego (nawet w ramach) istnieje tak wiele różnych implementacji tego. –

+0

@Adriano Ale dokumentacja implikuje więcej. http://msdn.microsoft.com/en-us/library/ctssatww.aspx Jeśli twoja aplikacja wymaga różnych sekwencji liczb losowych, wywołaj ten konstruktor wielokrotnie z różnymi wartościami początkowymi. – Paparazzi

Powiązane problemy