Заселение генератора псевдослучайных чисел в С#
Мне нужно семя для экземпляра класса С# Random
, и я читал, что большинство людей используют текущий счетчик тиков времени для этого. Но это 64-битное значение, и семя должно быть 32-битным значением. Теперь я подумал, что метод GetHashCode()
, который возвращает int
, должен обеспечивать разумно распределенное значение для своего объекта, и это можно использовать, чтобы избежать использования только младших 32-бит количества отсчетов. Однако я не мог найти ничего о GetHashCode() типа данных Int64
.
Итак, я знаю, что это не имеет большого значения, но будет работать так же хорошо, как я думаю (я не могу случайно и случайным образом), или, может быть, он работает так же, как с помощью (int)DateTime.Now.Ticks
в качестве семена? Или, может быть, это еще хуже? Кто может пролить свет на это.
int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random r = new Random(seed);
Изменить: Почему мне нужно семя и не просто позволить конструктору Random()
выполнить эту работу? Мне нужно отправить семя другим клиентам, которые используют одно и то же семя для одной и той же случайной последовательности.
Ответы
Ответ 1
new Random()
уже использует текущее время. Это эквивалентно new Random(Environment.TickCount)
.
Но это детализация реализации и может измениться в будущих версиях .net
Я бы рекомендовал использовать новый Random() и предоставить только фиксированное семя, если вы хотите получить воспроизводимую последовательность псевдослучайных значений.
Поскольку вам нужно знать семя, просто используйте Environment.TickCount
так же, как MS. А затем передайте его другим экземплярам программы в качестве семени.
Если вы создаете несколько экземпляров Random
за короткий промежуток времени (может быть 16 мс), они могут быть засеяны до одного значения и, таким образом, создать ту же псевдослучайную последовательность. Но это, скорее всего, не проблема. Эта общая ошибка вызвана обновлением окна текущего времени (DateTime.Now
/.UtcNow
) и TickCount (Environment.TickCount
) только каждые несколько миллисекунд. Точный интервал зависит от версии окон и от того, какие другие программы работают. Типичные интервалы, в которых они не изменяются, составляют 16 мс или 1 мс.
Ответ 2
Если вам нужно засеять его чем-то другим, кроме текущего (в этом случае вы можете использовать конструктор по умолчанию), вы можете использовать это:
Random random = new Random(Guid.NewGuid().GetHashCode());
Ответ 3
У меня был аналогичный вопрос, чтобы выбрать случайный набор вопросов из более широкого списка вопросов. Но когда я использую время как семя, он дает одинаковое случайное число.
Итак, вот мое решение.
int TOTALQ = 7;
int NOOFQ = 5;
int[] selectedQuestion = new int[TOTALQ];
int[] askQuestion = new int[NOOFQ];
/* Genarae a random number 1 to TOTALQ
* - if that number in selectedQuestion array is not o
* - Fill askQuestion array with that number
* - remove that number from selectedQuestion
* - if not re-do that - - while - array is not full.
*/
for (int i = 0; i < TOTALQ; i++) // fill the array
selectedQuestion[i] = 1;
int question = 0;
int seed = 1;
while (question < NOOFQ)
{
DateTime now1 = new DateTime();
now1 = DateTime.Now;
Random rand = new Random(seed+now1.Millisecond);
int RandomQuestion = rand.Next(1, TOTALQ);
Response.Write("<br/> seed " + seed + " Random number " + RandomQuestion );
if (selectedQuestion[RandomQuestion] != 0)
{
selectedQuestion[RandomQuestion] = 0; // set that q =0 so not to select
askQuestion[question] = selectedQuestion[RandomQuestion];
Response.Write(". Question no " + question + " will be question " + RandomQuestion + " from list " );
question++;
}
seed++;
}