Почему кажется, что мой генератор случайных чисел не случаен в C#?

Как насчет Guid.NewGuid().ToString();?

19
задан adeena 31 May 2009 в 17:39
поделиться

11 ответов

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

47
ответ дан 30 November 2019 в 01:44
поделиться

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

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

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

7
ответ дан 30 November 2019 в 01:44
поделиться

Не создавать метод оболочки для 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).

18
ответ дан 30 November 2019 в 01:44
поделиться
random = new Random();

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

32
ответ дан 30 November 2019 в 01:44
поделиться

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

6
ответ дан 30 November 2019 в 01:44
поделиться

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

[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
ответ дан 30 November 2019 в 01:44
поделиться

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

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

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

3
ответ дан 30 November 2019 в 01:44
поделиться

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

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

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

public static int RandomOneOrZero(Random random)
{
    return random.Next(0, int.MaxValue) & 1;
}
1
ответ дан 30 November 2019 в 01:44
поделиться

Это дополнение к любым ответам, как ответ на этот конкретный вопрос в том, что границы должны быть (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
ответ дан 30 November 2019 в 01:44
поделиться

Several posters have stated that Random() uses a seed based on the current second on the system clock and any other instance of Random created in the same second will have the same seed. This is incorrect. The seed for the parameterless constructor of Random is based on the tick count, or number of milliseconds since boot time. This value is updated on most systems approximately every 15 milliseconds but it can vary depending on hardware and system settings.

0
ответ дан 30 November 2019 в 01:44
поделиться

в 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
ответ дан 30 November 2019 в 01:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: