Как я могу генерировать поистине (а не псевдо) случайные числа с помощью С#?

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

Ответ 1

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

Простой способ (для простоты и практичности)

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

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

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

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

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

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

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

Ответ 2

короткий ответ: напрямую невозможно генерировать TRULY RANDOM NUMBERS, используя только С# (т.е. используя только чисто математическую конструкцию).

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

Поток старый и ответил, но я думал, что все равно продолжу. Это для полноты, и люди должны знать некоторые вещи о Random в С#.

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

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

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

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

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

Ответ 6

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

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

Ответ 7

Нет способа генерировать по-настоящему случайные числа с компьютером. Истинная случайность требует внешнего источника, который контролирует естественное явление.

Тем не менее, если у вас нет доступа к такому источнику действительно случайных чисел, вы можете использовать процесс "бедный человек" следующим образом:

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

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

Здесь образец библиотеки, которая реализует вышеописанный алгоритм в С++: http://www.boost.org/doc/libs/1_39_0/libs/random/random-generators.html

Ответ 8

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

Ответ 9

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

Lavarand

Ответ 10

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

Ответ 11

Этот код вернет вам случайное число между 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

Ответ 12

Просто для того, чтобы разъяснить всем, что нет True RNG, доступного на С# или на вашем компьютере, ошибочно. Многоядерный процессор по своей сути является True RNG. Очень просто, используя преимущество спина процессора, вы можете генерировать bools, которые не имеют различимого шаблона. Оттуда вы можете сгенерировать нужный диапазон чисел, используя bools как биты, и построить число, добавив бит вместе.

Да, это величины медленнее, чем чисто математическое решение, но чисто математическое решение всегда будет иметь шаблон.

public static bool GenerateBoolean()
{
    var gen1 = 0;
    var gen2 = 0;
    Task.Run(() =>
    {
        while (gen1 < 1 || gen2 < 1)
            Interlocked.Increment(ref gen1);
    });
    while (gen1 < 1 || gen2 < 1)
        Interlocked.Increment(ref gen2);
    return (gen1 + gen2) % 2 == 0;
}