Как я могу генерировать действительно (не псевдо) случайные числа с C #? - PullRequest
29 голосов
/ 05 августа 2009

Я знаю, что класс Random может генерировать псевдослучайные числа, но есть ли способ генерировать действительно случайные числа?

Ответы [ 12 ]

54 голосов
/ 05 августа 2009

Ответ здесь имеет две основные стороны. Есть несколько довольно важных тонкостей, на которые стоит обратить должное внимание ...

Легкий путь (для простоты и практичности)

RNGCryptoServiceProvider, который является частью Crypto API в BCL, должен выполнить эту работу за вас. Технически это все еще генерируемое псевдослучайное число, но качество «случайности» намного выше - подходит для криптографических целей, как можно предположить из названия.

Также доступны другие криптографические API с высококачественными псевдослучайными генераторами. Такие алгоритмы, как Mersenne twister , довольно популярны.

Сравнивая это с классом Random в BCL, это значительно лучше. Например, если вы нанесете числа, сгенерированные Random, на график, вы сможете распознать шаблоны, что является сильным признаком слабости. Во многом это связано с тем, что алгоритм просто использует заполненную таблицу соответствия фиксированного размера.

Трудный путь (для теоретической случайности высокого качества)

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

Теперь обратите внимание, что если вам действительно требуются действительно случайные числа , вы можете использовать такой сервис, как Random.org , который генерирует числа с очень высокая случайность / энтропия (на основе атмосферный шум ). Данные свободно доступны для скачивания. Тем не менее, это может быть излишне сложно для вашей ситуации, хотя, безусловно, дает вам данные, пригодные для научных исследований и еще много чего.

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

12 голосов
/ 05 августа 2009

краткий ответ: напрямую сгенерировать ИСТИННЫЕ СЛУЧАЙНЫЕ ЧИСЛА напрямую невозможно, используя только C # (т.е. используя только чисто математическую конструкцию).

длинный (er) ответ: Только посредством использования внешнего устройства, способного генерировать "случайность", такого как генератор белого шума или аналогичный - и захвата выходных данных этого устройства в качестве начального числа для генератор псевдослучайных чисел (PRG). Эта часть может быть выполнена с использованием C #.

4 голосов
/ 05 августа 2009

Как шутил Джон фон Нейман: «Любой, кто рассматривает арифметические методы получения случайных цифр, конечно, находится в состоянии греха».

4 голосов
/ 05 августа 2009

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

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

Генераторы псевдослучайных чисел - следующая лучшая вещь, и лучшие из них очень трудно предсказать.

3 голосов
/ 04 декабря 2012

Тема старая и ответила, но я все равно решил продолжить. Это для полноты, и люди должны знать кое-что о Random в c #.

Что касается действительно случайного, лучшее, на что вы можете надеяться, это использовать «безопасный псевдослучайный генератор», такой как salsa20 или RC4 (вроде как, иногда). Они проходят множество испытаний, где «эффективные» противники пытаются отличить их от случайных. Это связано с определенными затратами и, вероятно, не является необходимым для большинства применений.

Случайный класс в c # в большинстве случаев довольно хорош, имеет статическое распределение, которое выглядит случайным. Однако начальным значением для random () является системное время. Так что, если вы берете много случайных в «одно и то же время», они принимаются с одним и тем же семенем и будут одинаковыми («случайный» является полностью детерминированным, не позволяйте этому обмануть вас). Подобные начальные значения системного времени также могут давать аналогичные числа из-за недостатков случайного класса. Способ справиться с этим - установить собственные семена, например

Random random = new Random((int)DateTime.Now.Ticks & (0x0000FFFF + x));

где x - это какое-то значение, которое вы увеличиваете, если, например, создали цикл для получения набора случайных чисел.

Кроме того, с помощью случайных расширений c # для вашей новой переменной, такой как NextDouble (), может быть полезно при манипулировании случайными числами, в этом случае дробление их в интервал (0,1) становится unif (0,1), что происходит распределение, которое вы можете подключить к формулам статистики, чтобы создать все распределения в статистике.

2 голосов
/ 06 августа 2009

Взгляните на использование алгоритма типа Ярроу или Фортуна с накоплением энтропии. Смысл этих алгоритмов состоит в том, что они отслеживают энтропию как меру теоретического информационного содержания, доступного для предсказания будущих чисел, зная прошлые числа и алгоритмы, используемые для их создания; и они используют криптографические методы, чтобы сложить новые источники энтропии в генератор чисел.

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

1 голос
/ 27 июля 2012

Этот код вернет вам случайное число от min до max:

private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public int RandomNumber(int min, int max)
{
    lock (syncLock)
    { // synchronize
        return random.Next(min, max);
    }
}

Использование:

int randomNumber = RandomNumber(0, 10); // a random number between 1 and 10
1 голос
/ 26 сентября 2009

В компьютерах нет «истинного» случайного числа, все основано на чем-то другом. Для некоторых (выполнимых) способов генерирования псевдослучайных данных попробуйте что-нибудь, например, пул временных параметров HD, временных характеристик процессора, использования сети (пакетов в секунду) и, возможно, попаданий в секунду на веб-сервер.

1 голос
/ 05 августа 2009

Мне всегда нравилась эта идея, для стиля ретро 60-х:

Lavarand

1 голос
/ 05 августа 2009

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

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