Подтвердить что ты не робот

Два разных семени, производящих одну и ту же "случайную" последовательность

Возможно, для этого существует очень логичное объяснение, но я просто не могу понять, почему семена 0 и 2,147,483,647 производят одну и ту же "случайную" последовательность, используя .NET Случайный класс (система).

Пример быстрого кода:

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

Как вы можете видеть, первая и третья последовательности одинаковы. Может кто-нибудь, пожалуйста, объясните мне это?

РЕДАКТИРОВАТЬ. По-видимому, как отмечали алро, эти последовательности не совпадают. Но они очень похожи.

4b9b3361

Ответ 1

Ну, причина будет связана с тем, что функция деривации используется классом Random для получения псевдослучайной последовательности из семени. Поэтому ответ реальный является математическим (и помимо моих возможностей).

В самом деле - я не верю, что есть гарантия, что два разных семени будут в любом случае создавать разные последовательности.

Изменить. Хорошо. Я сделаю то, что сделал битбонк, но объясните, почему:

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

После всего самого первого цикла алгоритм уже сходится для двух начальных значений.

Изменить

Как было указано на вопрос - последовательности не одно и то же, но они явно очень похожи - и здесь мы можем видеть причину такого сходства.