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

Почему 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) говорит: "Возвращает неотрицательный случайный число меньше указанного максимума. Возможно, я не понимая что-то основное.

4b9b3361

Ответ 1

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

Если вы хотите создать статичное, случайное число, которое выполняет разные результаты, вы должны немного переработать его. Однако, поскольку 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);
     }
}

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

Не знаю, как работают внутренние элементы. Проверьте вики, но это очень просто.

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 последовательность из многих чисел, random * не реально, но приблизительно *)

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

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 из последовательности.

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

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

Ответ 6

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

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

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

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

Ответ 7

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

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

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