Практическая информатика

Случайные числа


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

Для получения случайного целого числа в диапазоне от 0 до n используется метод rand(n). Случайное число в диапазоне от 0 до 1 получается с помощью этого же метода без указания параметра.

a1 = (1..10).collect { |j| rand(100)} a2 = (1..4).collect { |j| rand()} p a1, a2

Ниже представлен возможный вывод:

[64, 17, 21, 95, 58, 24, 29, 60, 47, 63] [0.2009671596, 0.8890923676, 0.3349569312, 0.8719313448]

Одним из применений случайных чисел является компьютерное моделирование метода Монте-Карло для определения площади некоторой фигуры, рассмотренный нами ранее. Напомним, что для применения этого метода фигуру вписывают в другую, известной площади, и случайным образом "бросают" точки, подсчитывая число попаданий в фигуру. При достаточно большом числе испытаний отношение числа точек, попавших внутрь фигуры, к общему числу точек, стремится к отношению их площадей.

Задача

Напишите программу, вычисляющее приближенное значение числа PI при помощи метода Монте-Карло.

Решение

Число PI равно отношению площади круга к квадрату его радиуса. Впишем круг единичного радиуса с центром в начале координат в квадрат и методом Монте-Карло найдем его площадь. Координаты случайных точек, бросаемых в круг, принадлежат интервалу (-1; 1). Величина, случайно распределенная в этом интервале, задается выражением 2*rand() - 1.

Для контроля за временем добавим два экземпляра класса Time: время начала и окончания расчета. Программа, реализующая этот алгоритм, представлена ниже. В ней используется оператор eval, чтобы количество точек можно было задавать в виде арифметического выражения.

puts "Введите количество точек:" n1, n, t1 = 0, eval(gets.chop), Time.now for i in 1 .. n x = 2*rand() - 1 y = 2*rand() - 1 # проверяем попадание внутрь круга n1 += 1 if (x**2 + y**2) < 1 end puts "PI=#{4.0*n1/n}" t2 = Time.now puts "Число точек #{n}, время расчета " + "около #{(t2 - t1).round} сек."

Возможные результаты работы программы будут похожи (случайность!) на следующие:

Введите количество точек: 10**5 PI=3.14028 Число точек 100000, время расчета около 2 сек.

Введите количество точек: 10**6 PI=3.142204 Число точек 1000000, время расчета около 20 сек.

Пример 1.15.

(html, txt)



Содержание раздела