Генератор случайных чисел - своими руками :)
В вашей системе программирования наверняка уже есть генератор равномерно распределённых случайных чисел или даже несколько таких генераторов, и работают они обычно лучше всего того, что вы можете придумать сами. Тем не менее, в учебных целях такое делают. Сделаем собственный генератор и сравним его "равномерность" со встроенным в систему, для простоты ограничимся реализацией в MathCAD 15. Как и большинство подобных разработок, наша программка будет использовать тот факт, что компьютер вносит погрешность практически в любые операции с вещественными числами. А можно опираться и на переполнение при целочисленных операциях, конечно.
Вот совсем несложный алгоритм для генерации равномерно распределённых случайных чисел. Основную работу сделает функция rnd01
, генерирующая n
равномерно распределенных случайных чисел из интервала [0,1]
.
Генерация вектора из n равномерно распределенных в интервале[0,1] случайных чисел
Всё, что с нижними индексами - обычные векторы.
Что означают второй и третий параметры функции? А это "зёрна" последовательности или seed'ы. Возьмите другие seed'ы - и будет другая последовательность.
Почему стандартный алгоритм при обновлении документа даёт разные значения мат.ожидания и дисперсии, а наш - одни и те же? Просто потому, что стандартный начинает всегда со случайного seed, зависящего от текущего счётчика времени в системе, добавить такую возможность, передавая соответствующие данные функции rnd01
, было бы совсем несложно.
Чтобы "масштабировать" распределение из интервала [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 [14476 просмотров]