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

Случайные числа с использованием С#

Я ищу случайное число от 1 до 5 миллионов. Процесс не должен быть быстрым (хотя было бы хорошо, если бы оно было), но оно должно быть как можно более случайным (я знаю, что ничего не случайное). У меня есть множество источников данных для семян.

Я не уверен, что .NET < Класс i1 > будет достаточно хорош для этого.

Это будет использоваться для выбора выигрышного билета.

4b9b3361

Ответ 1

Класс System.Random, вероятно, достаточно хорош:

Псевдослучайные числа выбираются с равной вероятностью из конечного набора чисел. Выбранные числа не являются полностью случайными, потому что для их выбора используется определенный математический алгоритм, но они достаточно случайны для практических целей. Текущая реализация класса Random основана на алгоритме генератора случайных чисел Дональда Э. Кнута. Для получения дополнительной информации см. D. E. Knuth. "Искусство программирования, том 2: Семинумерные алгоритмы". Addison-Wesley, Reading, MA, второе издание, 1981 год.

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

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

Ответ 2

Если вам требуется криптографическое случайное число, перейдите в класс System.Security.Cryptography.RNGCryptoServiceProvider или используйте метод RandomNumberGenerator.Create() factory для создания настроенного генератора случайных чисел по умолчанию.

Ответ 3

См. сообщение в блоге Jon Skeet Пересмотр случайности очень хороший обзор того, как использовать Случайность:

Повторение случайности
Почти каждый вопрос, который включает слова" случайный "и" повторный "имеет тот же основной ответ. Это одна из самых распространенных" gotchas "в .NET, Java, и, без сомнения, другие платформы: создание нового случайного генератор чисел без указания семя будет зависеть от текущего момент времени. Текущее время как измеренный компьютером, не часто меняются по сравнению с тем, как часто вы можете создавать и использовать случайные генератор чисел - поэтому код, который неоднократно создает новый экземпляр Случайный и использует его один раз показывая много повторений.

подробнее...

Ответ 4

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

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

Алгоритм Кнута, используемый классом .NET System.Random, оптимизирован в основном для скорости, а не для случайного распределения. Это "достаточно случайный" для многих целей, которые большинство приложений никогда не заходят слишком далеко, но в областях (а) игр и (б) статистического моделирования большинство людей, похоже, считают, что это плохой выбор. Это лучше, чем LCG, которые раньше были стандартными в старых библиотеках, но вы все еще не хотите использовать его для чего-то вроде лото.

Не обманывайтесь, думая, что вы просто используете источник криптографии. Проблема с криптовальными RNG заключается в том, что они заполняют поток байтов, но превращая это в одно случайное целое число между x и y, требует, чтобы вы выполняли некоторую модульную арифметику (или округление - один и тот же результат в любом случае). И если ваш случайный диапазон не делится совершенно равномерно на любую силу 2, определяемую длиной байта, тогда вы будете в конечном итоге с уклоном в более низких числах. Сгенерированные данные имеют высокую энтропию, но ваш результат будет предвзятым.

Как простой пример, позвольте сказать, что вы получаете "идеальное" случайное число от 1 до 10, и теперь вы хотите превратить это в случайное число от 1 до 7. Как вы это делаете? Простое вычисление result % 7 будет сильно смещено к номерам 1-3. Есть несколько способов уменьшить смещение при использовании криптографического RNG, но точка, которую я пытаюсь сделать, заключается в том, что криптовальные RNG предназначены для криптографических приложений, и использование одного из них для моделирования методом Монте-Карло обычно не является лучшей идеей.

Насколько я знаю, самым популярным "хорошим" PRNG сегодня, который обычно используется в игровых приложениях, является Mersenne Twister. Здесь .NET реализация здесь. Этот алгоритм передает все Diehard Tests для случайного распределения; он практически не имеет предвзятости и является хорошим выбором, когда вы используете случайные числа для вероятностных и статистических приложений.

Научная библиотека GNU также имеет ряд алгоритмов RNG, и, что не удивительно, Mersenne Twister находится в верхней части списка. Однако некоторые из них заслуживают внимания ради любопытства; RANLUX также очень хорошо оценивает тест IIRC.

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

Ответ 5

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

Next(int minimum, int maximum);
Next(int Maximum);

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

Фрагмент кода:

Random random = new Random();
int maxValue = 100;

int r = random.Next(maxValue);

Ответ 6

Класс System.Random очень проблематичен и не соответствует требованиям. Теоретически, он должен обеспечивать лучшие результаты, чем многие другие псевдослучайные генераторы. Это прямой и буквальный порт примера кода C для генератора с запаздыванием Fibonacci (LFG), представленного на стр. 283 второго издания "Численные рецепты в C" (код был переписан в более поздних выпусках). LFG используют лучший алгоритм, чем используемые линейные конгруэнтные генераторы (LCG) - это много других библиотек (например, Java).

К сожалению, у Microsoft в классе System.Random есть ошибка. Подробнее см. http://connect.microsoft.com/VisualStudio/feedback/details/634761/system-random-serious-bug. Кажется, кто-то случайно набрал "21", когда намеревался ввести "31". Это компрометирует алгоритм псевдослучайных характеристик. Ссылка включает в себя объяснение от MS о том, почему они не могут исправить ошибку на этом этапе.

Ответ 7

Если вы ищете истинные случайные числа, вам следует рассмотреть возможность использования генератора случайных чисел в сети, который использует естественное явление, например http://www.random.org, который использует атмосферный шум. Истинные случайные числа также делают хорошие семена для генераторов псевдо-случайных чисел.

Sipwiz показывает, как использовать его в С# в своем ответе: Генерировать случайные значения в С#. Здесь также обсуждается: http://www.vcskicks.com/random-number-generator.php.

Там много углов для генераторов случайных чисел. Интересной альтернативной версией является ISSAC (ttp://burtleburtle.net/bob/rand/isaac.html), который также содержит хорошее обсуждение предвзятости и т.д., А также версия С# (http://burtleburtle.net/bob/rand/isaacafa.html).

Ответ 8

.NET Случайно должно быть хорошо для этого:

var random = new Random(System.DateTime.Now.Millisecond);

int randomNumber = random.Next(1, 5000000);