Как генерируется случайное число во время выполнения? - PullRequest
12 голосов
/ 14 декабря 2010

Поскольку компьютеры не могут выбирать случайные числа (могут?), Как на самом деле генерируется это случайное число. Например, в C # мы говорим,

Random.Next()

Что происходит внутри?

Ответы [ 7 ]

14 голосов
/ 14 декабря 2010

Вы можете оформить заказ в этой статье .Согласно документации конкретная реализация, используемая в .NET, основана на алгоритме вычитающего генератора случайных чисел Дональда Кнута.Для получения дополнительной информации см. DE Knuth.«Искусство компьютерного программирования, том 2: Получисленные алгоритмы».Эддисон-Уэсли, Рединг, Массачусетс, второе издание, 1981 .

6 голосов
/ 14 декабря 2010

Поскольку компьютеры не могут выбирать случайные числа (не так ли?)

Как уже отмечали другие, «Случайность» на самом деле псевдослучайная. Чтобы ответить на вопрос в скобках: да, компьютеры могут выбирать действительно случайные числа. Это намного дороже, чем простая целочисленная арифметика генератора псевдослучайных чисел, и обычно не требуется. Однако есть приложения, в которых вы должны иметь непредсказуемую истинную случайность: сразу приходят на ум криптография и онлайн-покер. Если любой из них использует предсказуемый источник псевдослучайности, злоумышленники могут гораздо легче дешифровать / подделывать сообщения, а мошенники могут выяснить, кто что имеет в своих руках.

Крипто-классы .NET имеют методы, которые дают случайные числа, подходящие для криптографии или игр, в которых деньги находятся на линии. Что касается того, как они работают: литература по случайности криптостойкости обширна; за подробностями обращайтесь к любому хорошему учебнику для студентов старших курсов по криптографии.

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

4 голосов
/ 14 декабря 2010

Я просто добавлю ответ на первую часть вопроса (часть «могут ли они?») .H

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

Однако это не имеет отношения ко второму вопросу (как работало Random.Next()).

4 голосов
/ 14 декабря 2010

Кнут хорошо освещает тему случайности.

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

Существует три категории генераторов случайных чисел, которые усиливаются в приведенном выше комментарии.

Во-первых, у вас есть генераторы псевдослучайных чиселгде, если вы знаете текущее случайное число, легко вычислить следующее.Это облегчает обратный инжиниринг других чисел, если вы обнаружите несколько.

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

Рассмотрим простой генератор по модулю (аналогично некоторым реализациям вC rand ())

int rand () {возврат семян = seed * m + a;}

если m = 0 и a = 0, это паршивый генератор с периодом 1: 0, 0, 0, 0, .... если m = 1 и a = 1, это тоже не оченьслучайный вид: 0, 1, 2, 3, 4, 5, 6, ...

Но если вы выберете m и a в качестве простых чисел около 2 ^ 16, то это будет очень красиво выглядеть очень случайнымесли вы случайно осматриваете.Но поскольку оба числа нечетные, вы увидите, что младший бит будет переключаться, то есть число будет попеременно нечетным и четным.Не отличный генератор случайных чисел.А поскольку в 32-битном числе только 2 ^ 32 значения, по определению после максимум 2 ^ 32 итераций вы будете повторять последовательность еще раз, делая очевидным, что генератор НЕ является случайным.

Если выПредставьте, что средние биты хороши и скремблированы, в то время как младшие биты не так случайны, из нескольких из них вы можете построить лучший генератор случайных чисел, с различными битами XOR, сгруппированными вместе, чтобы все биты были хорошо покрыты,Что-то вроде:

(rand1 () >> 8) ^ rand2 () ^ (rand3 ()> 5) ...

Тем не менее, каждое число синхронизируется, что делает этопредсказуемы.И если вы получите два последовательных значения, они будут коррелированы, так что если вы построите их, вы получите линии на экране.Теперь представьте, что у вас есть правила, объединяющие генераторы, так что последовательные значения не являются следующими.Например,

v1 = rand1 () >> 8 ^ rand2 () ... v2 = rand2 () >> 8 ^ rand5 () ..

и представьте, что семена нет всегда вперед.Теперь вы начинаете делать что-то, что намного сложнее предсказать, основываясь на обратном инжиниринге, и последовательность длиннее.

Например, если вы каждый раз вычисляете rand1 (), но только продвигаете начальное число в rand2 () каждый третий раз объединяющий их генератор может не повторяться гораздо дольше, чем период одного из них.

Теперь представьте, что вы прокачиваете свой (довольно предсказуемый) генератор случайных чисел по модулю через DES или другое шифрованиеалгоритм.Это будет накапливать биты.

Очевидно, есть лучшие алгоритмы, но это дает вам представление.У Числовых Рецептов есть много алгоритмов, реализованных в коде и объясненных.Один очень хороший трюк: генерировать не одно, а блок случайных значений в таблице.Затем используйте независимый генератор случайных чисел, чтобы выбрать одно из сгенерированных чисел, сгенерировать новое и заменить его.Это нарушает любую корреляцию между соседними парами чисел.

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

http://www.random.org/randomness/

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

В библиотеке boost есть отличные реализации на С ++ генераторов Фибоначчи, царствующих королей псевдослучайных последовательностей, если вы хотите увидеть некоторый исходный код.

2 голосов
/ 14 декабря 2010

Класс Random является генератором псевдослучайных чисел .

Это в основном чрезвычайно длинная, но детерминированная повторяющаяся последовательность.«Случайность» происходит от начала с разных позиций.Укажите, с чего начать, выбрав seed для генератора случайных чисел и, например, это можно сделать с помощью системного времени или путем получения случайного начального числа из другого случайного источника.Конструктор случайных чисел по умолчанию использует системное время в качестве начального числа.

Фактический алгоритм, используемый для генерации последовательности чисел, задокументирован в MSDN :

Текущая реализация класса Random основана на алгоритме вычитающего генератора случайных чисел Дональда Кнута.Для получения дополнительной информации см. DE Knuth.«Искусство компьютерного программирования, том 2: Получисленные алгоритмы».Эддисон-Уэсли, Рединг, Массачусетс, второе издание, 1981.

1 голос
/ 14 декабря 2010

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

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

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

0 голосов
/ 14 декабря 2010

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

Если вы получите случайные числа, основанные на одном и том же семени, они будут часто одинаковыми.

...