it-swarm.com.ru

Почему Random.Next () всегда возвращает одно и то же число

Рассмотрим этот метод:

private static int GenerateRandomNumber(int seed, int max)
{
   return new Random(seed).Next(max);
}

На моем компьютере выполнение этого цикла дает такое же число через 1500 итераций:

  for (int i = 0; i < 1501; i++)
            {
                int random = GenerateRandomNumber(100000000, 999999999);
                Console.WriteLine(random.ToString());
                Console.ReadKey();
            }

Я получаю 145156561 за каждую итерацию.

У меня нет острой проблемы, мне было просто интересно это поведение, потому что .Next (max) говорит: «Возвращает неотрицательное случайное число меньше указанного максимума. Возможно, я не понимаю чего-то базового.

18
kd7

Вы всегда сеете новый экземпляр тем же семенем, а затем получаете первый максимум. Используя Семя, вы гарантируете те же результаты.

Если вы хотите, чтобы генерирование статических случайных чисел давало разные результаты, вам следует немного переделать это. Однако, так как Random не является потокобезопасным, он требует некоторой синхронизации при статическом использовании. Что-то вроде:

private static Random random;
private static object syncObj = new object();
private static void InitRandomNumber(int seed)
{
     random = new Random(seed);
}
private static int GenerateRandomNumber(int max)
{
     lock(syncObj)
     {
         if (random == null)
             random = new Random(); // Or exception...
         return random.Next(max);
     }
}
39
Reed Copsey

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

Генерация случайных чисел не является действительно случайной, см. эту запись в Википедии для более подробной информации.

6
Eric Giguere

Дилберт столкнулся с той же проблемой еще в 2001 году:

http://dilbert.com/strips/comic/2001-10-25/

Стечение обстоятельств?

Я так не думаю.

И random.org соглашается: http://www.random.org/analysis/

6
dbrin

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

В .NET есть «только» 2 ^ 32 разных случайных последовательностей.

3
Jens

Не уверен, как работает внутреннее устройство .. проверьте вики на это, но это очень просто.

public class MathCalculations
{
    private Random rnd = new Random();

    public Int32 getRandom(Int32 iMin, Int32 iMax)
    {
        return rnd.Next(iMin, iMax);
    }
}

public class Main
{
    MathCalculations mathCalculations = new MathCalculations();
    for (int i = 0; i < 6; i++)
    {
        getRandom(0,1000);
    }
}

сгенерирует Number1, Number2, Number3, Number4, Number5, Number6 (1 начальное число, 1 последовательность из многих чисел, случайное * не совсем, но приблизительно *)

если вы, однако, делаете это:

public class MathCalculations
{
    public Int32 getRandom(Int32 iMin, Int32 iMax)
    {  
        Random rnd = new Random();
        return rnd.Next(iMin, iMax);
    }
}

public class Main
{
    MathCalculations mathCalculations = new MathCalculations();
    for (int i = 0; i < 6; i++)
    {
        getRandom(0,1000);
    }
}

Теперь вы получите Number1, Number1, Number1, Number1, Number1, Number1 (1 начальное число, 6 равных последовательностей из многих чисел, всегда выбирайте один и тот же начальный номер из каждой равной последовательности). В какой-то момент Number1 будет другим, потому что начальное число меняется со временем ... но вам нужно подождать некоторое время для этого, тем не менее, вы никогда не выбираете число 2 из последовательности.

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

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

2
user957537

В случае, если кто-то ищет «быстрое и грязное» «решение» (и я использую этот термин с осторожностью), этого будет достаточно для большинства.

int secondsSinceMidnight = Convert.ToInt32(DateTime.Now.Subtract(DateTime.Today).TotalSeconds);
Random Rand = new Random(secondsSinceMidnight); 
var usuallyRandomId = Rand.Next();

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

0
AnthonyJ

Салам всем, Ну, это также сводило меня с ума. Ответ прост. Измените семя, прежде чем генерировать случайный.

Пример: Я хочу сгенерировать случайное число от 1 до 10

Random rnd = new Random(DateTime.Now.Seconds);
int random_number = rnd.Next(10);

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

0
Talha