PERL: БИБЛИОТЕКА ПРОГРАММИСТА - стр. 86
# weight_to_dist: получает хэш весовых коэффициентов
# и возвращает хэш вероятностей
sub weight_to_dist {
my %weights = @>_; my %dist =(); my $total = 0; my ($key, Sweight); local $_;
foreach (values %weights) { $total += $_;
while ( ($key, Sweight) = each %weights ) { $dist{$key} = $weight/$total;
80 Глава 2 • Числа
return %dist;
# weighted_ran: получает хэш вероятностей 8 и возвращает случайный элемент хэша sub weighted_rand {
my %dist = @_;
my ($key, $weight);
while (1) { # Чтобы избежать погрешностей вычислений
# с плавающей запятой (см. ниже), ray $rand = rand,
while ( ($кеу, $weight) = each %dist ) { return $key if ($rand -= $weight) <0;
Комментарий
Функция gaussian_rand реализует полярный метод Бокса—Мюллера для преобразования двух независимых случайных чисел с однородным распределением, лежащих в интервале от 0 до 1 в два числа с математическим ожиданием 0 и стандартным отклонением 1 (то есть распределенных по закону Гаусса). Чтобы сгенерировать числа с другим математическим ожиданием и стандартным отклонением, умножьте выходные данные gaussian_rand на нужное стандартное отклонение и прибавьте математическое ожидание:
# gaussian_rand - см. выше
$mean = 25;
$sdev = 2;
Ssalary - gaussian_rand() * $sdev + $mean;
printf("You have been hired at \$%.2f\n", Ssalary);
Функция weighted_rand получает случайное число из интервала от 0 до 1. Затем она использует вероятности, сгенерированные weight_to_dist, и определяет, какому элементу соответствует это случайное число. Из-за погрешностей представления с плавающей запятой накопленные ошибки могут привести к тому, что возвращаемый элемент не будет найден. Поэтому код размещается в цикле while, который в случае неудачи выбирает новое случайное число и делает очередную попытку.
Кроме того, модуль Math::Random с CPAN содержит функции, генерирующие случайные числа для многих распределений.
t> Смотри также--------------------------------------------------------------------------------------------
