Как работает генератор случайных чисел?

Как работает генератор случайных чисел? (например, в C/С++ Java)

Как я могу написать свой собственный генератор случайных чисел? (например, в C/С++ Java)

Ответ 1

Существует также этот алгоритм:

enter image description here

О, и более серьезно:

Генераторы случайных чисел используют математические формулы для передачи одного или нескольких чисел в другой. Если, например, вы принимаете постоянное число N и другое число n_0, а затем принимаете значение n mod N (оператор modulo), вы получите новый номер n_1, который выглядит так, как если бы не имеет отношения к n_0. Теперь повторите этот процесс с помощью n_1, и вы получите еще один номер. У вас здесь есть генератор (ОЧЕНЬ ПЛОХО), представляющий собой случайные числа. Помните, метод, который я описал здесь, представляет собой игрушечный метод, который нельзя использовать ни для чего серьезного. Это, однако, иллюстрирует общий принцип.

Помните:

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

(перефразировано из главы 7 Численные рецепты). Это обязательный текст для всех, кто использует генераторы случайных чисел для любой серьезной работы.

Ответ 2

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

Одним из самых простых примеров этого (для реализации также является Линейный конгруэнтный генератор. Конечно, цифры выглядят непредсказуемыми для вас и для меня, но они фактически равномерно распределены в конечном поле.

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

Ответ 3

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

Следующее, что вам нужно сделать, это применить некоторую формулу, которая будет генерировать новый номер из этого "входного" номера и скопировать его в нужный диапазон, например 0..255:

random_number = integer (формула (значение таймера)) MOD 255

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

Примерной функцией формулы может быть:
формула (x) = ((постоянная XOR) + константа2) Диапазон MOD
XOR раньше был одним из моих фаворитов.


Обновление: Я понимаю, что эта формула очень плохая, она генерирует довольно предсказуемый набор чисел. Кроме того, системный таймер слишком предсказуем в качестве источника. Поэтому для большинства приложений этого недостаточно. Если вам нужна лучшая случайность, используйте больше источников, чем системный таймер, и лучшие формулы, чтобы объединить их.

Ответ 5

Существует много информации о том, как они работают... см. Konamiman и немного используйте google.

Почему вы хотите написать новый случайный генератор? Вы, вероятно, не должны пытаться это сделать... пока вам не понадобится что-то особенное. Например, в игре вы можете использовать сумка в случайном порядке, которая производит "справедливые" случайные значения, - посмотрите этот интересный вопрос о SO.
Я публикую это здесь, потому что мне очень понравилась идея и реализация, когда я читал об этом в первый раз:)

Ответ 6

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

 DIM pad(15) AS INTEGER
CLS
egg$ = "EFCDBA01457FA968"
  ghh$ = egg$
 nom% = 0
zen% = LEN(ghh$)
WHILE zen% > 0
opp$ = LEFT$(ghh$, 1)
eff% = ASC(opp$)
IF eff% >= 48 AND eff% <= 57 THEN eff% = eff% - 48 ELSE eff% = (eff% - 65) + 10
IF eff% > 15 THEN eff% = eff% - 32
pad(nom%) = eff%
nom% = nom% + 1
zen% = LEN(ghh$) - 1
ypp$ = RIGHT$(ghh$, zen%)
ghh$ = ypp$
WEND
sol& = 0
FOR zyx% = 0 TO 3
sol& = sol& * 16
sol& = sol& + pad(zyx%)
NEXT zyx%
sat% = sol& - 32768
RANDOMIZE sat%
FOR zyx% = 0 TO 15
PRINT HEX$(pad(zyx%));
NEXT zyx%
RANDOMIZE TIMER
respawn:
INPUT "sides per die"; die%
INPUT " number of dice"; dice%
INPUT "number to add to dice roll can be negative"; num%
INPUT "multiplier use 1 if so desired single precision floating point number"; g!
PRINT " hit any key to roll again with these values hit n for new values and q to quit"
PRINT " the number will be added or subtracted first before the multiplier takes effect"
reroll:
sum! = 0
FOR x% = 1 TO dice%
GOSUB rndmz
GOSUB demf
GOSUB drand
k% = INT(dr# * die%) + 1
sum! = sum! + k%
NEXT x%
sum! = (sum! + num) * g!
PRINT "you rolled a :"; sum!
i$ = ""
WHILE i$ = "": i$ = INKEY$: WEND
IF i$ = "n" THEN GOTO respawn
IF i$ = "q" THEN GOTO theend
GOTO reroll
theend:
SYSTEM
END
rndmz: rhet$ = ""
zum% = 0
FOR yxz% = 0 TO 15
FOR zyx% = 0 TO 15
IF zyx% MOD 3 = 0 THEN zum% = (zum% + pad(zyx%)) MOD 16
IF zyx% MOD 3 = 1 THEN zum% = (zum% + 16 - pad(zyx%)) MOD 16
IF zyx% MOD 3 = 2 THEN zum% = (zum% + INT(RND * 16)) MOD 16
NEXT zyx%
rhet$ = rhet$ + HEX$(zum%)
NEXT yxz%
ghh$ = rhet$
RETURN
demf: nom% = 0
zen% = LEN(ghh$)
WHILE zen% > 0
opp$ = LEFT$(ghh$, 1)
eff% = ASC(opp$)
IF eff% >= 48 AND eff% <= 57 THEN eff% = eff% - 48 ELSE eff% = (eff% - 65) + 10
IF eff% > 15 THEN eff% = eff% - 32
pad(nom%) = eff%
nom% = nom% + 1
zen% = LEN(ghh$) - 1
ypp$ = RIGHT$(ghh$, zen%)
ghh$ = ypp$
WEND
FOR zyx% = 0 TO 15
'PRINT HEX$(pad(zyx%));
NEXT zyx%
RETURN
drand: dr# = pad(0)
FOR eff% = 1 TO 15
dr# = dr# / 16
dr# = dr# + pad(eff%)
NEXT eff%
dr# = dr# / 16
RETURN
derf: a# = 1
x# = 1
b# = 1 / (2 ^ .5)
c# = .2500000000000011#
FOR u% = 1 TO 3
y# = a#
a# = (a# + b#) / 2
b# = (b# * y#) ^ .5
c# = c# - x# * (a# - y#) ^ 2
x# = 2 * x#
pi# = ((a# + b#) ^ 2) / (4 * c#)
PRINT pi#
NEXT u%
pi# = pi# + .000000000000015#
PRINT pi#

это здесь, в конце, вычисляет pi почти столько же мест, сколько возможно всего за 3 цикла через алгоризм, жаль, что он написан на архаичном базовом языке, это единственный язык программирования, который я знаю, возможно, это можно будет перенести на С++ или Java
Просто внимательно изучите логику этого и особенно пристальное внимание к процедурам priming или seeding/initialization, которые должны быть использованы, или он будет терпеть неудачу, как хороший rng... это тот, который я разработал для игровых целей, где есть огромная безопасность это не такая уж большая проблема, как скорость...

Ответ 7

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