Начальное значение Random() в C#

162
10 апреля 2019, 14:40

Подскажите, пожалуйста, на что указывает и влияет начальное значение в объявлении нового объекта Random. Допустим 999, в нашем случае.

Random random = new Random(999);

В пособии я прочитал, что объявление инициирующего значения позволяет постоянно иметь одни и те же последовательности случайных чисел при запуске метода. До конца не понял.

Answer 1

Одно и то же начальное значение генерирует одну ту же последовательность на выходе https://msdn.microsoft.com/ru-ru/library/ctssatww(v=vs.110).aspx

Другими словами, разные параметры генерируют разные псевдослучайные последовательности. То есть вот пользуешься рандомом, ждешь, что он все время случайное число генерит, а нет - перезапускаешь программу а последовательность чисел такая же, как и в прошлый раз. А все потому, что создал рандом с конкретным значением (например, ваш 999). Так вот, чтобы такого не было, обычно в качестве начального значения указывают какую то случайную величину, например

new Random(DateTime.UtcNow.Millisecond);

при таком раскладе получить 2 раза подряд повторяющуюся последовательность маловероятно.

Если посмотреть в код конструктора по умолчанию (https://referencesource.microsoft.com/#mscorlib/system/random.cs,52) - в нём идёт вызов

: this(Environment.TickCount)

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

Именно проблема инициализации класса Random часто приводит к вопросам новичков. Как я писал выше, по умолчанию Random создается с параметром Environment.TickCount. Таким образом, если создать 2 класса Random подряд, то они скорее всего будут инициализированы одним и тем же значением, и, как следствие, будут генерировать одну и ту же последовательность.

Проверить это легко:

// Смотрим, что можно получить одинаковый TickCount, 
// если запросить его 2 раза подряд
var test1 = Environment.TickCount;
var test2 = Environment.TickCount;
Console.WriteLine($"test1: {test1}");
Console.WriteLine($"test2: {test2}");
// Создаем 2 рандома подряд. Так как интервал времени 
// между созданием экземпляров небольшой, 
// скорее всего они будут инициализировны одним и тем же TickCount 
// и будут генерировать одну и ту же последовательность превдослучайных чисел
var r1 = new Random();
var r2 = new Random();
Console.WriteLine($"random1: {r1.Next()}");
Console.WriteLine($"random2: {r2.Next()}");

Вывод примера в консоль:

test1: 570009681
test2: 570009681
random1: 888018196
random2: 888018196

Как видно, были сгенерированы одни и те же случайные числа для рандомов, созданных в одно и то же время. Непонимание этой особенности обычно порождает вопросы у начинающих программистов. Как примеры:

На русском:

random заполняет две матрицы одинаковыми значениями

C# случайные числа

Заполнение массивов случайными числами

на английском

https://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number

READ ALSO
Как показать реальное время, если оно неправильное на компьютере?

Как показать реальное время, если оно неправильное на компьютере?

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

202
Как перезапустить форму Windows form?

Как перезапустить форму Windows form?

Всем приветВопрос следующий: у меня есть форма и мне надо ,чтоб пользователь по нажатию на кнопку "Reset" обнулял форму(возвращал ее в исходное...

239
Проблема с подсчетом суммы в C#

Проблема с подсчетом суммы в C#

Задача: Даны числовой ряд и некоторое число e>0Найти сумму тех членов последовательности ряда, модуль которых больше или равен заданному e

164
Рисование дерева в Windows Forms

Рисование дерева в Windows Forms

у меня проблема с AutoScroll и рисованием (суть вопроса после кода)Я вот по такому коду рисую AVL- дерево:

211