Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [ 20 ] 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242

2.8. Раскрутка генератора случайных чисел 77

> Смотри также-

Описание функций int, rand и join вperlfunc(l). Случайные числа исследуются в рецептах 2.8-2.10, а используются - в рецепте 1.9.

2.8. Раскрутка генератора длучайных чисел

Проблема

При каждом запуске программы вы получаете один и тот же набор «случайных» чисел. Требуется «раскрутить» генератор, чтобы Perl каждый раз генерировал разные числа. Это важно практически для любых применений случайных чисел, особенно для игр.

Решение

Воспользуйтесь функцией Perl srand: stand EXPR;

Комментарий

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

Функция srand задает новое стартовое значение для генератора псевдослучайных чисел. Если она вызывается с аргументом, то указанное число будет использовано в качестве стартового. При отсутствии аргумента srand использует величину, значение которой трудно предсказать заранее (относится к Perl 5.004 и более поздним версиям; до этого использовалась функция time, значения которой совсем не были случайными). Не вызывайте srand в программе более одного раза.

Если вы не вызвали srand сами, Perl версий 5.004 и выше вызывает srand с «хорошим» стартовым значением при первом запуске rand. Предыдущие версии этого не делали, поэтому программы всегда генерировали одну и ту же последовательность чисел. Если вы предпочитаете именно такое поведение, вызывайте srand с конкретным аргументом:

srand( <STOIN> );

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

> Смотри также-

Описание функции srand вperlfuncl). Примеры ее применения приведены в рецептах 2.7 и 2.9.



2.9. Повышение фактора случайности

Проблема

Требуется генерировать случайные числа, которые были бы «более случайными», чем выдаваемые генератором Perl. Иногда возникают проблемы, связанные с ограниченным выбором стартовых значений в библиотеках С. В некоторых приложениях последовательность псевдослучайных чисел начинает повторяться слишком рано.

Решение

Воспользуйтесь другими генераторами случайных чисел - например, теми, которые присутствуют в модулях Math-Random и Math::TrulyRandom с CP AN:

use Math:iTrulyRandom;

Srandoffl = truly random value();

use Math Random;

$random = random unifor(n();

Комментарий

Для генерации случайных чисел в Perl используется стандартная библиотечная функция С rand(3) (впрочем, на стадии компоновки это можно изменить). Некоторые реализации функции rand возвращают только 16-разрядные случайные числа или используют слабые алгоритмы, не обеспечивающие достаточной степени случайности.

Модуль Math::TrulyRandom генерирует случайные числа, используя погрешности системного таймера. Процесс занимает некоторое время, поэтому им не стоит пользоваться для генерации большого количества случайных чисел.

Модуль Math::Random генерирует случайные числа с помощью библиотеки randlib. Кроме того, он содержит многочисленные вспомогательные функции.

О Смотри также--

Описание функций srand и rand вperlfunc{\)\ рецепты 2.7-2.8; документация по модулям Math::Random и Math;:TrulyRandom с CPAN.

2.10. Генерация случайных чисел с неравномерным распределением

Проблема

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



2.10. Генерация случайных чисел с неравномерным распределением 79

иного баннера. А может быть, вы имитируете нормальное распределение (закон распределения Гаусса).

Решение

Если вам потребовались случайные величины, распределенные по конкретному закону (допустим, по закону Гаусса), загляните в учебник по статистике и найдите в нем нужную функцию или алгоритм. Следующая функция генерирует случайные числа с нормальным распределением, со стандартным отклонением 1 и нулевым математическим ожиданием.

sub gaussian rand {

my ($u1, $u2); # Случайные числа с однородным распределением

ту $w; # Отклонение, затем весовой коэффициент

ту ($g1, $g2); # Числа с гауссовским распределением

do {

$u1 = 2 . rand() - 1; $u2 = 2 . randO - 1; $w = $u1.$u1 + $u2.u2 } while ($w >= 1);

$w = sqrt( (-2 . log($w)) / $w); $g2 = $u1 • $w; $g1 = $u2 * $w;

# Возвратить оба числа или только одно return wantarray ? ($g1, $g2) : $g1;

Если у вас есть список весовых коэффициентов и значений и вы хотите выбирать элементы списка случайным образом, выполните два последовательных шага. Сначала превратите весовые коэффициенты в вероятностное распределение с помощью приведенной ниже функции weight to dist, а затем воспользуйтесь функцией weighted rand для случайного выбора чисел.

# weight to dist; получает хэш весовых коэффициентов

# и возвращает хэш вероятностей sub weight to dist {

my %weights = @ ; my %dist =0; my $total = 0; my ($key, Sweight); local $ ;

foreach (values %weights) { Stotal += $ ;

while ( ($key, Sweight) = each %weights ) { $dist{$key} = $weight/$total;



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [ 20 ] 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242