БлогNot. Генератор случайных чисел - своими руками :)

Генератор случайных чисел - своими руками :)

В вашей системе программирования наверняка уже есть генератор равномерно распределённых случайных чисел или даже несколько таких генераторов, и работают они обычно лучше всего того, что вы можете придумать сами. Тем не менее, в учебных целях такое делают. Сделаем собственный генератор и сравним его "равномерность" со встроенным в систему, для простоты ограничимся реализацией в MathCAD 15. Как и большинство подобных разработок, наша программка будет использовать тот факт, что компьютер вносит погрешность практически в любые операции с вещественными числами. А можно опираться и на переполнение при целочисленных операциях, конечно.

Вот совсем несложный алгоритм для генерации равномерно распределённых случайных чисел. Основную работу сделает функция rnd01, генерирующая n равномерно распределенных случайных чисел из интервала [0,1].

Генерация вектора из n равномерно распределенных в интервале[0,1] случайных чисел
Генерация вектора из n равномерно распределенных в интервале[0,1] случайных чисел

Всё, что с нижними индексами - обычные векторы.

Что означают второй и третий параметры функции? А это "зёрна" последовательности или seed'ы. Возьмите другие seed'ы - и будет другая последовательность.

Почему стандартный алгоритм при обновлении документа даёт разные значения мат.ожидания и дисперсии, а наш - одни и те же? Просто потому, что стандартный начинает всегда со случайного seed, зависящего от текущего счётчика времени в системе, добавить такую возможность, передавая соответствующие данные функции rnd01, было бы совсем несложно.

Чтобы "масштабировать" распределение из интервала [0,1] в произвольный интервал [a,b], достаточно следующего кода:

преобразовать равномерное из интервала [0,1] в произвольный интервал [a,b]
преобразовать равномерное из интервала [0,1] в произвольный интервал [a,b]

Кстати, если нужны целые числа, равновероятно выбранные из множества [m, m+1, ..., n], их легче всего было бы получить кодом

k = trunc[ m + (n-m+1-10-8)*e ],

где trunc[] - функция получения целой части числа, e - очередное псевдослучайное число из интервала [0,1], полученное нашей функцией rnd01.

Стандартная функция MathCAD всю проделанную нами работу выполнит одним оператором:

x:=runif(n,a,b)

Для построения гистограммы относительных частот используем подход, показанный вот тут, только перепишем алгоритм в собственную функцию hist (не показана на рисунке, в файле есть):

сравнение гистограмм относительных частот для нашего и стандартного алгоритмов
сравнение гистограмм относительных частот для нашего и стандартного алгоритмов

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

отклонения полученных характеристик выборок от теоретических значений
отклонения полученных характеристик выборок от теоретических значений

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

Имея толковый генератор равномерно распределённых псевдослучайных чисел, легко получить и другие распределения. Например, для нормального распределения существует преобразование Бокса-Мюллера. Ну и ещё много чего можно придумать, основываясь на центральной предельной теореме.

 Скачать этот пример в архиве .zip с документом MathCAD 15 внутри (33 Кб)

05.07.2015, 19:15 [14089 просмотров]


теги: random статистика алгоритм математика mathcad

К этой статье пока нет комментариев, Ваш будет первым