Я работаю в Microsoft Visual C # 2008 Express.

Я нашел этот фрагмент кода:

    public static int RandomNumber(int min, int max)
    {
        Random random = new Random();

        return random.Next(min, max);
    }

Проблема в том, что я запускал его более 100 раз, и он ВСЕГДА дает мне тот же ответ, когда мои min = 0 и max = 1. Я получаю 0 каждый раз. (Я создал тестовую функцию для ее запуска - правда - каждый раз получаю 0). Мне трудно поверить, что это совпадение ... Могу ли я еще что-нибудь сделать, чтобы проверить или проверить это? (Я повторно запускал тест с min = 0 и max = 10 и первые 50 раз, результат всегда был «5», второй раз 50, результат всегда был «9».

?? Мне нужно что-то более случайное ...

-Адина

20
adeena 31 Май 2009 в 21:39

13 ответов

Лучший ответ

Проблема с min = 0 и max = 1 заключается в том, что min является включающим, а max исключающим. Таким образом, единственное возможное значение для этой комбинации - 0.

47
Annath 31 Май 2009 в 17:43
random = new Random();

Это запускает генератор случайных чисел с текущим временем (в секундах). Когда вы вызываете свою функцию много раз до изменения системных часов, генератор случайных чисел запускается с тем же значением, поэтому он возвращает ту же последовательность значений.

32
mateusza 31 Май 2009 в 18:00

Не создавайте метод-оболочку для Next. Он тратит циклы на создание нового экземпляра класса Random. Просто используйте тот же самый!

Random myRand = new Random();

for(int i = 0; i < 10; i++)
{
    Console.WriteLine(myRand.Next(0, 10).ToString());
}

Это должно дать вам десять случайных значений.

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

Кроме того, как уже говорили люди, остерегайтесь того, что MinValue является включающим, а MaxValue - эксклюзивным. Для чего вы хотите, сделайте myRand.Next (0, 2).

19
Eric 31 Май 2009 в 17:47

Эта перегрузка Next () возвращает:

32-разрядное целое число со знаком, большее или равное minValue и меньшее maxValue; то есть диапазон возвращаемых значений включает minValue, но не MaxValue. Если minValue равно maxValue, возвращается minValue.

0 - единственное возможное значение для его возврата. Возможно, вам нужен random.NextDouble (), который вернет двойное значение от 0 до 1.

7
Dave Bauman 31 Май 2009 в 17:45

Минимум включает, но максимум исключает. Ознакомьтесь с API

6
AgileJon 31 Май 2009 в 17:43

Вы всегда получаете 0, потому что Random.Next возвращает целые числа. Вам нужно вызвать Random.NextDouble, который вернет число от 0 до 1. Кроме того, вы должны повторно использовать свой экземпляр Random, например:

[ThreadStatic]
static Random random;
public static Random Random { 
    get {
        if (random == null) random = new Random();
        return random;
    }
}
public static int RandomInteger(int min, int max)
{
    return Random.Next(min, max);
}
public static double RandomDouble() //Between 0 and 1
{ 
    return Random.NextDouble();
} 

Если вам нужны криптографически безопасные случайные числа, используйте класс RNGCryptoServiceProvider; см. эту статью

РЕДАКТИРОВАТЬ: безопасность потока

6
SLaks 1 Июн 2009 в 21:00

Помимо проблемы 0-1, уже отмеченной в других ответах, ваша проблема является реальной, когда вы ищете диапазон 0-10 и получаете идентичные результаты 50 раз подряд.

new Random() должен возвращать случайное число с начальным значением, инициализированным таймером (текущая секунда), но, очевидно, вы вызываете этот код 50 раз в секунду. MSDN предлагает: «Для повышения производительности , создайте одно случайное число для генерации множества случайных чисел с течением времени, вместо многократного создания нового случайного числа для генерации одного случайного числа. ". Если вы однажды создадите свой генератор случайных чисел вне метода, это должно решить вашу проблему «неслучайности», а также повысить производительность.

Также обратите внимание на этот пост для лучшего генератора псевдослучайных чисел. чем системный, если вам нужны псевдослучайные числа «более высокого качества».

3
Alex Martelli 31 Май 2009 в 17:50

Как уже упоминали другие, Random, который создается несколько раз в секунду, использует ту же секунду, что и семя, поэтому я бы поместил конструктор Random за пределы вашего цикла и передал его как параметр, например:

public static int RandomNumber(Random random, int min, int max)
{
    return random.Next(min, max);
}

Также, как упоминалось другими, max является исключительным, поэтому, если вы хотите 0 или 1, вы должны использовать [0,2] как свой [min, max] или какой-то больший max, а затем выполнить двоичное И с 1.

public static int RandomOneOrZero(Random random)
{
    return random.Next(0, int.MaxValue) & 1;
}
1
Chris Doggett 31 Май 2009 в 17:51

Это дополнение к любым ответам, поскольку ответ на этот конкретный вопрос заключается в том, что границы должны быть (0, 2), а не (0, 1).

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

public static class ThreadSafeRandom
{
    private static readonly Random seed = new Random();

    [ThreadStatic]
    private static Random random;

    public static int Next(int min, int max)
    {
        if (random == null)
        {
            lock (seed)
            {
                random = new Random(seed.Next());
            }
        }

        return random.Next(min, max);
    }

    // etc. for other members
}
1
Greg Beech 31 Май 2009 в 18:25

Вы неправильно поняли строку «random.Next (min, max)». «min» стоит на месте наименьшего числа, которое может быть сгенерировано случайным образом. В то время как "max" стоит на месте наименьшего числа, которое НЕ разрешено генерировать, оно не находится на месте наибольшего числа, которое разрешено рисовать. Итак, когда строка является случайной.Next (0, 1), вы в основном разрешаете рисовать только 0.

1
Tom 25 Ноя 2017 в 17:41

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

0
Stephen Martin 31 Май 2009 в 19:26

Я нашел очень простой, но эффективный способ сгенерировать случайные числа, просто взяв две последние цифры текущей даты и времени в миллисекундах:

   int seed = Convert.ToInt32(DateTime.Now.Millisecond.ToString().Substring(1, 2));
   int cnr = new Random(seed).Next(100);

Это грубо, но работает! :-)

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

0
Fedor Alexander Steeman 26 Окт 2010 в 11:49

В VB я всегда начинаю с функции Randomize (). Просто вызовите Randomize () и запустите случайную функцию. Еще я делаю следующее:

Function RandomInt(ByVal lower As Integer, ByVal upper As Integer) As Integer
    Return CInt(Int((upper - lower + 1) * Rnd() + lower))
End Function

Надеюсь это поможет! :)

-2
Jason 31 Май 2009 в 17:42