0 added
0 removed
Original
2026-01-01
Modified
2026-02-21
1
<p><a>#статьи</a></p>
1
<p><a>#статьи</a></p>
2
<ul><li>28 янв 2021</li>
2
<ul><li>28 янв 2021</li>
3
<li>0</li>
3
<li>0</li>
4
</ul><p>Случайность управляет миром, а вы будете управлять случайностью. С помощью Python, конечно.</p>
4
</ul><p>Случайность управляет миром, а вы будете управлять случайностью. С помощью Python, конечно.</p>
5
<p> vlada_maestro / shutterstock</p>
5
<p> vlada_maestro / shutterstock</p>
6
<p>Кандидат философских наук, специалист по математическому моделированию. Пишет про Data Science, AI и программирование на Python.</p>
6
<p>Кандидат философских наук, специалист по математическому моделированию. Пишет про Data Science, AI и программирование на Python.</p>
7
<p>Чтобы имитировать бросок кубика в игре или предсказать загруженность интернет-ресурса, нужны случайные числа.</p>
7
<p>Чтобы имитировать бросок кубика в игре или предсказать загруженность интернет-ресурса, нужны случайные числа.</p>
8
<p>Мы разобрали самые популярные вопросы о случайных числах в Python с собеседований. Чаще всего для ответа достаточно написать код и кратко его прокомментировать. Да пребудет с вами Великий Рандом!</p>
8
<p>Мы разобрали самые популярные вопросы о случайных числах в Python с собеседований. Чаще всего для ответа достаточно написать код и кратко его прокомментировать. Да пребудет с вами Великий Рандом!</p>
9
<ul><li>Случайные числа - это последовательность чисел, которая подчиняется одному из законов распределения.</li>
9
<ul><li>Случайные числа - это последовательность чисел, которая подчиняется одному из законов распределения.</li>
10
<li>Главных распределений два: равномерное, с графиком в виде горизонтальной линии, и нормальное, с графиком-колоколом (его ещё называют гауссианой).</li>
10
<li>Главных распределений два: равномерное, с графиком в виде горизонтальной линии, и нормальное, с графиком-колоколом (его ещё называют гауссианой).</li>
11
</ul><ul><li>Основная Python-библиотека для генерации случайных чисел называется random.</li>
11
</ul><ul><li>Основная Python-библиотека для генерации случайных чисел называется random.</li>
12
<li>Большинство случайных чисел в программировании - не случайные, а псевдослучайные.</li>
12
<li>Большинство случайных чисел в программировании - не случайные, а псевдослучайные.</li>
13
</ul><p><strong>Сложность: 1/3</strong></p>
13
</ul><p><strong>Сложность: 1/3</strong></p>
14
<p>Что нужно помнить: случайные числа - это математическое понятие, и их не следует путать с обыденными, произвольными числами. Случайное число в математике и программировании - это:</p>
14
<p>Что нужно помнить: случайные числа - это математическое понятие, и их не следует путать с обыденными, произвольными числами. Случайное число в математике и программировании - это:</p>
15
<ul><li>число из определённого диапазона,</li>
15
<ul><li>число из определённого диапазона,</li>
16
<li>у которого есть определённая вероятность выпадения.</li>
16
<li>у которого есть определённая вероятность выпадения.</li>
17
</ul><p>Другими словами, существует закон или правило, которое называется "функцией распределения" или просто "распределением". И это самое распределение "раздаёт" каждому числу из диапазона определённую вероятность выпадения.</p>
17
</ul><p>Другими словами, существует закон или правило, которое называется "функцией распределения" или просто "распределением". И это самое распределение "раздаёт" каждому числу из диапазона определённую вероятность выпадения.</p>
18
<p>В качестве диапазона значений математикам и программистам привычнее всего использовать диапазон действительных чисел от 0 до 1, но это могут быть и целые числа от 1 до 6, как в игральном кубике, или от 100 до 1 000 000 - и так далее. Главное, что и распределение, и диапазон известны заранее, а само число нет.</p>
18
<p>В качестве диапазона значений математикам и программистам привычнее всего использовать диапазон действительных чисел от 0 до 1, но это могут быть и целые числа от 1 до 6, как в игральном кубике, или от 100 до 1 000 000 - и так далее. Главное, что и распределение, и диапазон известны заранее, а само число нет.</p>
19
<p>Итого: случайные числа - это искусственно полученная последовательность чисел из определённого диапазона, которая подчиняется одному из законов распределения случайной величины.</p>
19
<p>Итого: случайные числа - это искусственно полученная последовательность чисел из определённого диапазона, которая подчиняется одному из законов распределения случайной величины.</p>
20
<p>Распределения бывают разные. Так, равномерное распределение - это когда любое значение из диапазона имеет одну и ту же вероятность выпадения (как у игрального кубика или монетки). Если же распределение, например,<a>нормальное (гауссиана)</a>, то чаще выпадают числа из середины диапазона. Есть даже<a>таблица</a> - она поможет выбрать подходящее распределение.</p>
20
<p>Распределения бывают разные. Так, равномерное распределение - это когда любое значение из диапазона имеет одну и ту же вероятность выпадения (как у игрального кубика или монетки). Если же распределение, например,<a>нормальное (гауссиана)</a>, то чаще выпадают числа из середины диапазона. Есть даже<a>таблица</a> - она поможет выбрать подходящее распределение.</p>
21
<p><strong>Сложность: 1/3</strong></p>
21
<p><strong>Сложность: 1/3</strong></p>
22
<p>Основных способов два: с помощью "родной" библиотеки<a>random</a>и с помощью модуля<a>numpy.random</a>из библиотеки numpy.</p>
22
<p>Основных способов два: с помощью "родной" библиотеки<a>random</a>и с помощью модуля<a>numpy.random</a>из библиотеки numpy.</p>
23
<p>Прежде чем интервьюер придерётся, не забудьте сказать, что и random, и numpy.random - генераторы<strong>псевдо</strong>случайных чисел (о них ниже).<em>Истинно</em>случайные числа можно получить, например, c сайта<a>Random.Org</a>: там они генерируются с помощью атмосферного шума.</p>
23
<p>Прежде чем интервьюер придерётся, не забудьте сказать, что и random, и numpy.random - генераторы<strong>псевдо</strong>случайных чисел (о них ниже).<em>Истинно</em>случайные числа можно получить, например, c сайта<a>Random.Org</a>: там они генерируются с помощью атмосферного шума.</p>
24
import random # Случайное число между 0 и 1 (исключая 1) random.random() # Случайное число между 1 и 2, равномерное распределение random.uniform(1,2) # Случайное число, нормальное распределение # 1 и 2 здесь уже не границы диапазона, а параметры mu и sygma random.gauss(1,2)<p>Библиотека random имеет меньший объём, чем numpy.random, и проще в использовании. Зато numpy.random содержит дополнительные распределения для научных вычислений, а также функции для генерирования целых массивов случайных данных.</p>
24
import random # Случайное число между 0 и 1 (исключая 1) random.random() # Случайное число между 1 и 2, равномерное распределение random.uniform(1,2) # Случайное число, нормальное распределение # 1 и 2 здесь уже не границы диапазона, а параметры mu и sygma random.gauss(1,2)<p>Библиотека random имеет меньший объём, чем numpy.random, и проще в использовании. Зато numpy.random содержит дополнительные распределения для научных вычислений, а также функции для генерирования целых массивов случайных данных.</p>
25
from numpy.random import default_rng rng = default_rng() vals = rng.standard_normal(10)<p>В первой строчке мы импортировали default_rng - это "генератор генераторов" случайных массивов из модуля numpy.random. Во второй - создали экземпляр такого генератора и присвоили ему имя rng. В третьей использовали его метод standard_normal, чтобы получить numpy-массив из 10 случайных чисел, и записали массив в переменную vals.</p>
25
from numpy.random import default_rng rng = default_rng() vals = rng.standard_normal(10)<p>В первой строчке мы импортировали default_rng - это "генератор генераторов" случайных массивов из модуля numpy.random. Во второй - создали экземпляр такого генератора и присвоили ему имя rng. В третьей использовали его метод standard_normal, чтобы получить numpy-массив из 10 случайных чисел, и записали массив в переменную vals.</p>
26
<p><strong>Сложность: 3/3</strong></p>
26
<p><strong>Сложность: 3/3</strong></p>
27
<p>Псевдослучайные числа - это, если очень упрощать, последовательность чисел, которая только выглядит случайной, а на самом деле каждое число в ней определяется алгоритмом, то есть вычисляется. Псевдослучайные последовательности цикличны: через какой-то период все числа повторяются в точности в том же порядке.</p>
27
<p>Псевдослучайные числа - это, если очень упрощать, последовательность чисел, которая только выглядит случайной, а на самом деле каждое число в ней определяется алгоритмом, то есть вычисляется. Псевдослучайные последовательности цикличны: через какой-то период все числа повторяются в точности в том же порядке.</p>
28
<p>Библиотека random и модуль numpy.random содержат в себе генератор не истинно случайных, а именно псевдослучайных чисел.</p>
28
<p>Библиотека random и модуль numpy.random содержат в себе генератор не истинно случайных, а именно псевдослучайных чисел.</p>
29
<p>Генерировать истинно случайные числа дорого и сложно. Основная трудность состоит в том, чтобы гарантировать отсутствие какого-либо цикла, правила или алгоритма. Чаще всего истинно случайные числа<a>берут из физического мира</a>: шумов атмосферы, детекторов частиц, колебаний электрического тока или из космического излучения.</p>
29
<p>Генерировать истинно случайные числа дорого и сложно. Основная трудность состоит в том, чтобы гарантировать отсутствие какого-либо цикла, правила или алгоритма. Чаще всего истинно случайные числа<a>берут из физического мира</a>: шумов атмосферы, детекторов частиц, колебаний электрического тока или из космического излучения.</p>
30
<p>То, что псевдослучайная последовательность, в отличие от истинно случайной, воспроизводима, очень удобно для практических задач: часто нужно подать на вход ту же самую последовательность второй раз, чтобы посмотреть, как работает программа после добавления новых фич.</p>
30
<p>То, что псевдослучайная последовательность, в отличие от истинно случайной, воспроизводима, очень удобно для практических задач: часто нужно подать на вход ту же самую последовательность второй раз, чтобы посмотреть, как работает программа после добавления новых фич.</p>
31
Визуализация работы генератора псевдослучайных чисел. Видите какую-нибудь закономерность? А она есть.<a>Источник</a><p>Наиболее популярный современный алгоритм генерирования псевдослучайных чисел разработан в 1997 году и носит красивое название "<a>Вихрь Мерсенна</a>". Он используется и в Python. Последовательность чисел, порождённая им, статистически неотличима от истинно случайной и имеет период, равный числу с шестью тысячами знаков. Этого хватает для задач симуляции и моделирования, но с точки зрения криптографии такая последовательность всё равно небезопасна: для успешной атаки достаточно иметь сравнительно небольшую сгенерированную этим генератором последовательность.</p>
31
Визуализация работы генератора псевдослучайных чисел. Видите какую-нибудь закономерность? А она есть.<a>Источник</a><p>Наиболее популярный современный алгоритм генерирования псевдослучайных чисел разработан в 1997 году и носит красивое название "<a>Вихрь Мерсенна</a>". Он используется и в Python. Последовательность чисел, порождённая им, статистически неотличима от истинно случайной и имеет период, равный числу с шестью тысячами знаков. Этого хватает для задач симуляции и моделирования, но с точки зрения криптографии такая последовательность всё равно небезопасна: для успешной атаки достаточно иметь сравнительно небольшую сгенерированную этим генератором последовательность.</p>
32
<p><strong>Сложность: 2/3</strong></p>
32
<p><strong>Сложность: 2/3</strong></p>
33
<p>Истинно случайную последовательность повторить невозможно. Но для повторения псевдослучайных чисел в обеих основных библиотеках - random и numpy.random есть функция seed (), которая отвечает за инициализацию ("посев") последовательности.</p>
33
<p>Истинно случайную последовательность повторить невозможно. Но для повторения псевдослучайных чисел в обеих основных библиотеках - random и numpy.random есть функция seed (), которая отвечает за инициализацию ("посев") последовательности.</p>
34
import random random.seed(42) print(random.random()) # 0.6394267984578837 print(random.random()) # 0.025010755222666936 random.seed(42) print(random.random()) # 0.6394267984578837<p>Передавая аргумент 42 в функцию seed (), мы указываем конкретное место в псевдослучайной последовательности, поэтому команда random.random () в третьей и последней строках выдаёт одинаковое число - оно идёт первым после точки, помеченной как seed (42).</p>
34
import random random.seed(42) print(random.random()) # 0.6394267984578837 print(random.random()) # 0.025010755222666936 random.seed(42) print(random.random()) # 0.6394267984578837<p>Передавая аргумент 42 в функцию seed (), мы указываем конкретное место в псевдослучайной последовательности, поэтому команда random.random () в третьей и последней строках выдаёт одинаковое число - оно идёт первым после точки, помеченной как seed (42).</p>
35
<p>В seed () можно передать целые и дробные числа, а также строки и кортежи. Если оставить скобки пустыми, то в качестве аргумента seed () возьмёт текущее системное время.</p>
35
<p>В seed () можно передать целые и дробные числа, а также строки и кортежи. Если оставить скобки пустыми, то в качестве аргумента seed () возьмёт текущее системное время.</p>
36
<p>Аналогичная функция есть в модуле numpy.random:</p>
36
<p>Аналогичная функция есть в модуле numpy.random:</p>
37
import numpy as np np.random.seed(42) print(np.random.rand()) # 0.3745401188473625 print(np.random.rand()) # 0.9507143064099162 np.random.seed(42) print(np.random.rand()) # 0.3745401188473625<p><strong>Сложность: 1/3</strong></p>
37
import numpy as np np.random.seed(42) print(np.random.rand()) # 0.3745401188473625 print(np.random.rand()) # 0.9507143064099162 np.random.seed(42) print(np.random.rand()) # 0.3745401188473625<p><strong>Сложность: 1/3</strong></p>
38
<p>Часто на собеседованиях просят написать программу, связанную с вероятностями. Например, код для численной проверки ответа к задачке "Какова вероятность вытащить зелёный шар из мешка, в котором 1 зелёный и 4 красных шара". (Ответ ⅕ = 0,2).</p>
38
<p>Часто на собеседованиях просят написать программу, связанную с вероятностями. Например, код для численной проверки ответа к задачке "Какова вероятность вытащить зелёный шар из мешка, в котором 1 зелёный и 4 красных шара". (Ответ ⅕ = 0,2).</p>
39
<p>Иными словами, если 100 раз вынимать шар из мешка, возвращая его обратно, количество выпадения зелёных шаров должно приближаться к 20. Вариант кода для проверки:</p>
39
<p>Иными словами, если 100 раз вынимать шар из мешка, возвращая его обратно, количество выпадения зелёных шаров должно приближаться к 20. Вариант кода для проверки:</p>
40
import random green_ball_count = 0 # счётчик зелёных шаров for i in range(0,100): new_ball = random.choice(['green', 'red', 'red', 'red', 'red']) if new_ball == 'green': green_ball_count = green_ball_count + 1 print (green_ball_count)<p>Функция random.choice () случайным образом выбирает значение из заданного диапазона - списка из одного "green" и четырёх "red". Код выведет количество зелёных шаров после 100 попыток.</p>
40
import random green_ball_count = 0 # счётчик зелёных шаров for i in range(0,100): new_ball = random.choice(['green', 'red', 'red', 'red', 'red']) if new_ball == 'green': green_ball_count = green_ball_count + 1 print (green_ball_count)<p>Функция random.choice () случайным образом выбирает значение из заданного диапазона - списка из одного "green" и четырёх "red". Код выведет количество зелёных шаров после 100 попыток.</p>
41
<p><strong>Сложность: 1/3</strong></p>
41
<p><strong>Сложность: 1/3</strong></p>
42
<p>Другой вариант: предположим, у нас есть так называемая "нечестная" монетка, где орёл (H, "heads") и решка (T, "tails") выпадают не с вероятностью ½, как положено, а по-другому: орёл с вероятностью p (H) = 0,2, а решка, соответственно, p (T) = 0,8.</p>
42
<p>Другой вариант: предположим, у нас есть так называемая "нечестная" монетка, где орёл (H, "heads") и решка (T, "tails") выпадают не с вероятностью ½, как положено, а по-другому: орёл с вероятностью p (H) = 0,2, а решка, соответственно, p (T) = 0,8.</p>
43
<p>Тогда код для проверки будет выглядеть примерно так:</p>
43
<p>Тогда код для проверки будет выглядеть примерно так:</p>
44
import random H_count = 0 for i in range(0,10000): new_flip = random.choices(['H', 'T'], weights=[0.2, 0.8]) if new_flip == ['H']: # внимание: функция choices возвращает список! H_count = H_count + 1 print (H_count)<p>Здесь используется другая функция, choices, в которую вместе со списком значений можно в параметре weights передавать вероятности их выпадения.</p>
44
import random H_count = 0 for i in range(0,10000): new_flip = random.choices(['H', 'T'], weights=[0.2, 0.8]) if new_flip == ['H']: # внимание: функция choices возвращает список! H_count = H_count + 1 print (H_count)<p>Здесь используется другая функция, choices, в которую вместе со списком значений можно в параметре weights передавать вероятности их выпадения.</p>
45
<p>Код выведет количество выпавших орлов после 10 000 бросков.</p>
45
<p>Код выведет количество выпавших орлов после 10 000 бросков.</p>
46
<p><strong>Сложность: 2/3</strong></p>
46
<p><strong>Сложность: 2/3</strong></p>
47
<p>Закон больших чисел (ЗБЧ) говорит, что при увеличении количества попыток случайная величина стремится к своему математическому ожиданию - всё усредняется. Подробнее об этом можно прочитать<a>в нашей статье</a>об основах математики для Data Science.</p>
47
<p>Закон больших чисел (ЗБЧ) говорит, что при увеличении количества попыток случайная величина стремится к своему математическому ожиданию - всё усредняется. Подробнее об этом можно прочитать<a>в нашей статье</a>об основах математики для Data Science.</p>
48
<p>Код для иллюстрации ЗБЧ на примере честной монетки выглядит так:</p>
48
<p>Код для иллюстрации ЗБЧ на примере честной монетки выглядит так:</p>
49
import random import matplotlib.pyplot as plt total_flips = 0 numerical_probability = [] H_count = 0 for i in range(0,5000): new_flip = random.choices(['H', 'T'], weights=[0.5, 0.5]) total_flips = total_flips + 1 if new_flip == ['H']: # внимание: функция choices возвращает список, а не строку ‘H’ или ‘T’! H_count = H_count + 1 numerical_probability.append(H_count/total_flips) # рисуем график plt.plot(numerical_probability) plt.xlabel("Количество бросков") plt.ylabel("Численная вероятность")<p>Вначале мы импортировали уже знакомый нам модуль random и модуль matplotlib.plt - он нужен для рисования простых графиков. После этого определили переменные: общее количество бросков (total_flips), список из значений вероятностей (numerical_probability), количество выпавших орлов (H_count).</p>
49
import random import matplotlib.pyplot as plt total_flips = 0 numerical_probability = [] H_count = 0 for i in range(0,5000): new_flip = random.choices(['H', 'T'], weights=[0.5, 0.5]) total_flips = total_flips + 1 if new_flip == ['H']: # внимание: функция choices возвращает список, а не строку ‘H’ или ‘T’! H_count = H_count + 1 numerical_probability.append(H_count/total_flips) # рисуем график plt.plot(numerical_probability) plt.xlabel("Количество бросков") plt.ylabel("Численная вероятность")<p>Вначале мы импортировали уже знакомый нам модуль random и модуль matplotlib.plt - он нужен для рисования простых графиков. После этого определили переменные: общее количество бросков (total_flips), список из значений вероятностей (numerical_probability), количество выпавших орлов (H_count).</p>
50
<p>Теперь в цикле мы 5 000 раз "подбрасываем" монетку. Если выпадает орёл ("H"), то делим текущее количество выпавших орлов на текущее количество бросков и добавляем итоговое значение в конец списка numerical_probability. В конце рисуем график.</p>
50
<p>Теперь в цикле мы 5 000 раз "подбрасываем" монетку. Если выпадает орёл ("H"), то делим текущее количество выпавших орлов на текущее количество бросков и добавляем итоговое значение в конец списка numerical_probability. В конце рисуем график.</p>
51
<p>Чем больше бросков, тем ближе к 0,5 вероятность выпадения орла. Всё, как и предсказывает закон больших чисел.</p>
51
<p>Чем больше бросков, тем ближе к 0,5 вероятность выпадения орла. Всё, как и предсказывает закон больших чисел.</p>
52
<p><strong>Сложность: 2/3</strong></p>
52
<p><strong>Сложность: 2/3</strong></p>
53
<p><strong>В логистике</strong>: при<a>расчётах страховых запасов</a>товара - чтобы склад внезапно не опустел или, наоборот, не пришлось держать избыток товара слишком долго. Принято считать, что поведение покупателей случайно и подчиняется одной из разновидностей нормального распределения. В особо запущенных случаях считается случайным даже поведение поставщиков.</p>
53
<p><strong>В логистике</strong>: при<a>расчётах страховых запасов</a>товара - чтобы склад внезапно не опустел или, наоборот, не пришлось держать избыток товара слишком долго. Принято считать, что поведение покупателей случайно и подчиняется одной из разновидностей нормального распределения. В особо запущенных случаях считается случайным даже поведение поставщиков.</p>
54
<p><strong>В науке</strong>: с помощью<a>метода Монте-Карло</a>учёные моделируют<a>поведение частиц</a>во фрактальном окружении в трёхмерном пространстве. Метод Монте-Карло основан на использовании большого количества генерируемых случайных чисел.</p>
54
<p><strong>В науке</strong>: с помощью<a>метода Монте-Карло</a>учёные моделируют<a>поведение частиц</a>во фрактальном окружении в трёхмерном пространстве. Метод Монте-Карло основан на использовании большого количества генерируемых случайных чисел.</p>
55
<p><strong>В микроэлектронике</strong>: броуновское движение частиц играет важную роль в формировании пористости плёночного покрытия полупроводников при напылении его на поверхность. Просчитать это на компьютере гораздо дешевле, чем экспериментировать с реальным покрытием, поэтому сначала его рассчитывают, а потом запускают в производство.</p>
55
<p><strong>В микроэлектронике</strong>: броуновское движение частиц играет важную роль в формировании пористости плёночного покрытия полупроводников при напылении его на поверхность. Просчитать это на компьютере гораздо дешевле, чем экспериментировать с реальным покрытием, поэтому сначала его рассчитывают, а потом запускают в производство.</p>
56
<p><strong>В криптографии:</strong>для генерации шифровальных ключей. Здесь становится особенно важным различие между псевдослучайными и истинно случайными числами.</p>
56
<p><strong>В криптографии:</strong>для генерации шифровальных ключей. Здесь становится особенно важным различие между псевдослучайными и истинно случайными числами.</p>
57
<p>Так говорил мастер Угвэй, и мы теперь понимаем его чуть лучше: он жил довольно долго, мог заметить период повторения одних и тех же событий и догадаться, что все случайности в этом мире на самом деле псевдослучайны. У нас с вами времени меньше, поэтому придётся изучать документацию:<a>random</a>,<a>numpy.random</a>.</p>
57
<p>Так говорил мастер Угвэй, и мы теперь понимаем его чуть лучше: он жил довольно долго, мог заметить период повторения одних и тех же событий и догадаться, что все случайности в этом мире на самом деле псевдослучайны. У нас с вами времени меньше, поэтому придётся изучать документацию:<a>random</a>,<a>numpy.random</a>.</p>
58
<a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>
58
<a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>