Sign in Join
Wiki copytemporary

Generating Random Numbers/ru: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-<figure>
2-<img src="fpc_source_logo.png" title="fpc_source_logo.png" />
3-<figcaption>fpc_source_logo.png</figcaption>
4-</figure>
1+![](/wiki-images/8/84/Fpc_source_logo.png)
52
63**Случайные числа** являются важными ресурсами для научных приложений, образования, разработки игр и визуализации. Они играют ключевую роль в численном моделировании.
74
85Генерируемые алгоритмом случайные числа являются псевдослучайными числами. Они принадлежат (большому) набору повторяющихся чисел, последовательность которых невозможно или, по крайней мере, трудно предсказать. В отличие от Delphi, в котором используется линейный конгруэнтный генератор (см. [[Delphi compatible LCG Random]]), Free Pascal использует алгоритм MersenneTwister для своей стандартной [[doc:rtl/system/random.html|random]] функции, определенной в [[RTL]]. Перед первым использованием генератор случайных чисел FPC должен быть проинициализирован единичным вызовом функции [[doc:rtl/system/randomize.html|randomize]], которая устанавливает начальное число генератора. Предпочтительнее это делать на этапе запуска программы.
96
107Кроме того, в системах на основе Unix и Linux доступны виртуальные устройства [[Dev random|/dev/random]] и `/dev/urandom`. Они генерируют (псевдо) случайные числа на основе оборудования.
118
129Третий вариант - использовать случайные числа из внешних источников, либо из специализированных аппаратных устройств, либо из общедоступных источников, например. на основе данных радиоактивного распада.
1310
1411## Равномерное распределение
1512
1613Непрерывное равномерное распределение (также называемое прямоугольным распределением) представляет собой семейство симметричных вероятностных распределений. Здесь для каждого члена семьи все интервалы одинаковой длины в поддержке распределения одинаково вероятны.
1714
1815Стандартная функция [[RTL]] [[doc:rtl/system/random.html|random]] генерирует случайные числа с равномерным распределением. При вызове без параметра `random` выдает псевдослучайное число с плавающей запятой в интервале \[0, 1), т.е. 0 \<= result \< 1. Если `random` вызывается с аргументом `longint L`, возвращается случайное значение longint в интервале \[0, L).
1916
2017Дополнительный набор равномерно распределенных генераторов случайных чисел представлен в [[Marsaglia&|генераторах псевдослучайных чисел Марсальи.]]\
21-\
18+
2219Равномерно распределенные случайные числа полезны не для каждого приложения. Для создания случайных чисел других распределений необходимы специальные алгоритмы.
2320
2421## Нормальное (гауссово) распределение
2522
2623Одним из наиболее распространенных алгоритмов получения нормально распределенных случайных чисел из равномерно распределенных случайных чисел является [преобразование Бокса-Мюллера](https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%BE%D0%BA%D1%81%D0%B0_%E2%80%94_%D0%9C%D1%8E%D0%BB%D0%BB%D0%B5%D1%80%D0%B0). Следующая функция вычисляет распределенные по Гауссу случайные числа:
2724
2825``` pascal
2926 function rnorm (mean, sd: real): real;
3027 {Вычисляет гауссовы случайные числа в соответствии с преобразованием Бокса-Мюллера}
3128 var
3229 u1, u2: real;
3330 begin
3431 u1 := random;
3532 u2 := random;
3633 rnorm := mean * abs(1 + sqrt(-2 * (ln(u1))) * cos(2 * pi * u2) * sd);
3734 end;
3835```
3936
4037Тот же алгоритм используется функцией randg [[doc:rtl/math/randg.html|randg]] из модуля [[RTL]] [[doc:rtl/math/index.html|math]]:
4138
4239``` pascal
4340function randg(mean,stddev: float): float;
4441```
4542
4643## Экспоненциальное распределение
4744
4845Экспоненциальное распределение часто встречается в реальных задачах. Классическим примером является распределение времени ожидания между независимыми пуассоновскими случайными событиями, например, радиоактивный распад ядер \[Press et al. 1989\].
4946
5047Следующая функция возвращает одно действительное случайное число из экспоненциального распределения. *Rate* является обратным к среднему значению, а константа *RESOLUTION* определяет гранулярность генерируемых случайных чисел.
5148
5249``` pascal
5350function randomExp(a, rate: real): real;
5451const
5552 RESOLUTION = 1000;
5653var
5754 unif: real;
5855begin
5956 if rate = 0 then
6057 randomExp := NaN
6158 else
6259 begin
6360 repeat
6461 unif := random(RESOLUTION) / RESOLUTION;
6562 until unif <> 0;
6663 randomExp := a - rate * ln(unif);
6764 end;
6865end;
6966```
7067
7168## Гамма-распределение
7269
7370Гамма-распределение - это двухпараметрическое семейство непрерывных случайных распределений. Это обобщение как экспоненциального распределения, так и распределения Эрланга. Возможные применения гамма-распределения включают моделирование и имитацию линий ожидания, или очередей, и актуарную(страховую) науку.
7471
7572Следующая функция возвращает одно действительное случайное число из гамма-распределения. Форма распределения определяется параметрами *a*, *b* и *c*. Функция использует функцию **randomExp**, как определено выше.
7673
7774``` pascal
7875function randomGamma(a, b, c: real): real;
7976const
8077 RESOLUTION = 1000;
8178 T = 4.5;
8279 D = 1 + ln(T);
8380var
8481 unif: real;
8582 A2, B2, C2, Q, p, y: real;
8683 p1, p2, v, w, z: real;
8784 found: boolean;
8885begin
8986 A2 := 1 / sqrt(2 * c - 1);
9087 B2 := c - ln(4);
9188 Q := c + 1 / A2;
9289 C2 := 1 + c / exp(1);
9390 found := False;
9491 if c < 1 then
9592 begin
9693 repeat
9794 repeat
9895 unif := random(RESOLUTION) / RESOLUTION;
9996 until unif > 0;
10097 p := C2 * unif;
10198 if p > 1 then
10299 begin
103100 repeat
104101 unif := random(RESOLUTION) / RESOLUTION;
105102 until unif > 0;
106103 y := -ln((C2 - p) / c);
107104 if unif <= power(y, c - 1) then
108105 begin
109106 randomGamma := a + b * y;
110107 found := True;
111108 end;
112109 end
113110 else
114111 begin
115112 y := power(p, 1 / c);
116113 if unif <= exp(-y) then
117114 begin
118115 randomGamma := a + b * y;
119116 found := True;
120117 end;
121118 end;
122119 until found;
123120 end
124121 else if c = 1 then
125122 { Гамма-распределение становится экспоненциальным, если c = 1 }
126123 begin
127124 randomGamma := randomExp(a, b);
128125 end
129126 else
130127 begin
131128 repeat
132129 repeat
133130 p1 := random(RESOLUTION) / RESOLUTION;
134131 until p1 > 0;
135132 repeat
136133 p2 := random(RESOLUTION) / RESOLUTION;
137134 until p2 > 0;
138135 v := A2 * ln(p1 / (1 - p1));
139136 y := c * exp(v);
140137 z := p1 * p1 * p2;
141138 w := B2 + Q * v - y;
142139 if (w + D - T * z >= 0) or (w >= ln(z)) then
143140 begin
144141 randomGamma := a + b * y;
145142 found := True;
146143 end;
147144 until found;
148145 end;
149146end;
150147```
151148
152149## Распределение Эрланга
153150
154151Распределение Эрланга - это двухпараметрическое семейство непрерывных распределений вероятностей. Это обобщение экспоненциального распределения и частный случай гамма-распределения, где *c* - целое число. Распределение Эрланга было впервые описано Агнером Крарупом Эрлангом для моделирования временного интервала между телефонными звонками. Он используется для теории очередей и для моделирования линий ожидания.
155152
156153``` pascal
157154 function randomErlang(mean: real; k: integer): real;
158155 const
159156 RESOLUTION = 1000;
160157 var
161158 i: integer;
162159 unif, prod: real;
163160 begin
164161 if (mean <= 0) or (k < 1) then
165162 randomErlang := NaN
166163 else
167164 begin
168165 prod := 1;
169166 for i := 1 to k do
170167 begin
171168 repeat
172169 unif := random(RESOLUTION) / RESOLUTION;
173170 until unif <> 0;
174171 prod := prod * unif;
175172 end;
176173 randomErlang := -mean * ln(prod);
177174 end;
178175 end;
179176```
180177
181178## Распределение Пуассона
182179
183180Распределение Пуассона применяется к целочисленным значениям. Оно представляет вероятность успеха *k*, когда вероятность успеха в каждом испытании мала, а частота появления (среднее значение) постоянна.
184181
185182``` pascal
186183function randomPoisson(mean: integer): integer;
187184{ Генератор для распределения Пуассона (алгоритм Дональда Кнута) }
188185const
189186 RESOLUTION = 1000;
190187var
191188 k: integer;
192189 b, l: real;
193190begin
194191 assert(mean > 0, 'mean < 1');
195192 k := 0;
196193 b := 1;
197194 l := exp(-mean);
198195 while b > l do
199196 begin
200197 k := k + 1;
201198 b := b * random(RESOLUTION) / RESOLUTION;
202199 end;
203200 randomPoisson := k - 1;
204201end;
205202```
206203
207204## t-распределение (Стьюдента)
208205
209206t-распределение (также относится к t-распределению Стьюдента, поскольку оно было опубликовано Уильямом Сили Госсетом в 1908 году под псевдонимом *Student*) - это непрерывное распределение вероятностей. Его форма определяется одним параметром, степенями свободы (*df*). В статистике много оценок являются t-распределением. Таким образом, t-распределение Стьюдента играет главную роль в ряде широко используемых статистических анализов, включая t-критерий Стьюдента для оценки статистической значимости разницы между двумя средними выборками, построение доверительных интервалов для разницы между двумя средними значениями, и в линейном регрессионном анализе. Т-распределение также возникает при Байесовском выводе данных из нормального семейства.
210207
211208Следующий алгоритм зависит от функции [[RTL]] [[doc:rtl/system/random.html|random]] и от функции **randomChisq**
212209
213210``` pascal
214211function randomT(df: integer): real;
215212{ Генератор для распределения Стьюдента }
216213begin
217214 if df < 1 then
218215 randomT := NaN
219216 else begin
220217 randomT := randg(0, 1) / sqrt(randomChisq(df) / df);
221218 end;
222219end;
223220```
224221
225222## Распределение хи-квадрат
226223
227224Распределение хи-квадрат - это непрерывное распределение случайных чисел со степенями свободы *df*. Это распределение суммы квадратов независимых стандартных нормальных случайных величин. Распределение хи-квадрат имеет множество применений в выводной статистике, например, в оценке дисперсий и для тестов хи-квадрат. Это специальное гамма-распределение с *c* = *df*/ 2 and *b* = 2. Поэтому следующая функция зависит от функции **randomGamma**.
228225
229226``` pascal
230227function randomChisq(df: integer): real;
231228begin
232229 if df < 1 then
233230 randomChisq := NaN
234231 else
235232 randomChisq := randomGamma(0, 2, 0.5 * df);
236233end;
237234```
238235
239236## F-распределение (Фишера)
240237
241238Распределение F, также называемое распределением Фишера-Снедекора, является непрерывным распределением вероятности. Используется для F-теста(критерия Фишера) и ANOVA(ANalysis Of VAriance, или дисперсионный анализ). Оно имеет две степени свободы, которые служат параметрами формы *v* и *w*, и являются положительными целыми числами. Следующая функция **randomF** использует **randomChisq**.
242239
243240``` pascal
244241function randomF(v, w: integer): real;
245242begin
246243 if (v < 1) or (w < 1) then
247244 randomF := NaN
248245 else
249246 randomF := randomChisq(v) / v / (randomChisq(w) / w);
250247end;
251248```
252249
253250## См.также
254251
255252- [[Dev random]]
256253- [[Functions for descriptive statistics]]
257254- [[Marsaglia&|Marsaglia's pseudo random number generators]]
258255- [[A simple implementation of the Mersenne twister]]
259256- [[Delphi compatible LCG Random]]
260257
261258## Рекомендации
262259
2632601. [G. E. P. Box and Mervin E. Muller, *A Note on the Generation of Random Normal Deviates*, The Annals of Mathematical Statistics (1958), Vol. 29, No. 2 pp. 610–611](http://projecteuclid.org/DPubS/Repository/1.0/Disseminate?view=body&id=pdf_1&handle=euclid.aoms/1177706645)
2642612. Dietrich, J. W. (2002). [Der Hypophysen-Schilddrüsen-Regelkreis](http://openlibrary.org/books/OL24586469M/Der_Hypophysen-Schilddrüsen-Regelkreis). Berlin, Germany: Logos-Verlag Berlin. ISBN 978-3-89722-850-4. OCLC 50451543.
2652623. Press, W. H., B. P. Flannery, S. A. Teukolsky, W. T. Vetterling (1989). [Numerical Recipes in Pascal](http://openlibrary.org/works/OL16807779W/). The Art of Scientific Computing, Cambridge University Press, ISBN 0-521-37516-9.
2662634. Richard Saucier, [Computer Generation of Statistical Distributions](http://ftp.arl.mil/random/random.pdf), ARL-TR-2168, US Army Research Laboratory, Aberdeen Proving Ground, MD, 21005-5068, March 2000.
2672645. R.U. Seydel, Generating Random Numbers with Specified Distributions. In: Tools for Computational Finance, Universitext, [DOI 10.1007/978-1-4471-2993-6_2](http://dx.doi.org/10.1007/978-1-4471-2993-6_2), © Springer-Verlag London Limited 2012
2682656. Christian Walck, Hand-book on STATISTICAL DISTRIBUTIONS for experimentalists, Internal Report SUF–PFY/96–01, University of Stockholm 2007
269-
270-\
271266
272267---
273268*From the Free Pascal wiki, page "Generating Random Numbers/ru", as it stood on 2019-07-26 after a change by Zoltanleo, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history