Насколько случайным является Random.Next()?

Я проводил тестирование в классе Random и использовал следующий код:

while (x++ <= 5000000)
{
    y = rnd.Next(1, 5000000);
    if (!data.Contains(y))
        data.Add(y);
    else
    {
        Console.WriteLine("Cycle {2}: Repetation found for number {0} after {1} iteration", y, x, i);
        break;
    }
}

Я продолжал изменять максимальный предел rnd (то есть 5000000), изменил количество итераций и получил следующий результат:

1) if y = rnd.Next(1, 5000) : The average is between 80 to 110 iterations
2) if y = rnd.Next(1, 5000000) : The average is between 2000 to 4000 iterations
3) if y = rnd.Next(1, int.MaxValue) : The average is between 40,000 to 80,000 iterations.

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

Что я могу сделать, чтобы получить довольно случайное число.

Ответ 1

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

Кстати, на прошлой неделе я написал статью в блоге об этом конкретном предмете. Он выйдет в прямом эфире 22 марта; см. мой блог, затем для деталей.

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

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

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

Ответ 2

Вы предполагаете, что случайность лучше, если числа не повторяются. Это неверно.

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

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

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

Ответ 3

Вы оцениваете случайность с помощью пар повтора, что не является лучшим критерием случайности. Повторения, которые вы видите, сродни парадокс дня рождения: http://en.wikipedia.org/wiki/Birthday_problem, где событие повторения может происходить с небольшим размером выборки, если вы не ищет конкретное событие.

Ответ 4

В документации по http://msdn.microsoft.com/en-us/library/system.random.aspx

Чтобы создать криптографически безопасный случайное число, подходящее для создания случайный пароль, например, используйте класс, полученный из System.Security.Cryptography..::. RandomNumberGeneratorтакие как System.Security.Cryptography..::. RNGCryptoServiceProvider.

Ответ 5

Компьютер не может создать реальное случайное число. если вам нужно реальное случайное число (Дэвид дал вам лучший вариант из сетки dot net) вам нужен внешний случайный источник.