Pull to refresh

Random'изация в Python. Так ли она рандомна?

Reading time 2 min
Views 4.9K
image
Доброе время суток, хабравчане. Несмотря на глубокое название поста, суть его состоит в описании борьбы с собственной глупостью в решении уже изученных проблем. Последнее время часто размышлял над темой «случайность». Что же задает эту самую случайность? Ввиду того, что люблю до всего доходить сам — не полез в поисковики, а полез в Python.

Первым, в голову пришел следующий алгоритм:
1) Получить некоторое количество случайных чисел.
2) Узнать сколько в каждом случайном числе чисел «0», «1», «2» и т. д.
3) Подсчитать сумму этих чисел.
4) Для наглядности построить диаграмму.
Результатом я был по своей глупости крайне удивлен:
image
Почему количество нолей так заметно превышает количество всех остальных цифр? Ответ был прост, но о нем немного позже.
Я решил увеличить количество случайных чисел, заранее подозревая, что количество будет выравниваться.
Однако картина, которую я лицезрел была пугающей:
image
image
Вопрос после такого сразу возник к коду, в котором «рандомное» число генерируется как:
while ii<kol:
           a = random.random()
           z = str(a)
           L = len(z)
           i = 0
           while i <L:
                if z[i]=="0":
                   s0 +=1
               elif z[i]=="1":
                   s1 +=1
               elif z[i]=="2":
                   s2 +=1
               elif z[i]=="3":
                   s3 +=1
               elif z[i]=="4":
                   s4 +=1
               elif z[i]=="5":
                    s5 +=1
               elif z[i]=="6":
                   s6 +=1
               elif z[i]=="7":
                   s7 +=1
               elif z[i]=="8":
                   s8 +=1
               elif z[i]=="9":
                   s9 +=1
               i+=1
        ii +=1

Думаю вы уже догадались, в чем была моя первая ошибка? А была она в random.random(), возвращающей случайное число от 0 до 1 с определенным количеством знаков после запятой.
На этом дело не закончилось. Исправив ошибку:
...
while ii<kol:
           a = random.random()
           z = str(a)
           l = len(z)
           i = 2
           while i <L:
               if z[i]=="0":
                   s0 +=1
               elif z[i]=="1":
...

Получил следующую картину «рандома»:
image
Эта ситуация не менялась с увеличением количества чисел. Однако и здесь ответ крылся вовсе не в теории, а опять же в реализации. Догадались?
Дело в том, что Python округляет число, полученное с помощью random.random(). Достаточно легко понять, что при округлении, «округлиться в 0» шансов гораздо меньше, чем «округлиться в любое другое число». Т.к. для того, чтобы «округлиться в 0», необходимо, чтобы предпоследняя цифра случайного числа была 9. И этот шанс — 1 к 10.
«Подлечив» код:

while ii<kol:
           a = random.random()
           z = str(a)
           l = len(z)
           i = 2
           while i <L-1:
               if z[i]=="0":
                   s0 +=1
               elif z[i]=="1":


image
Справедливость Рандомность восторжествовала. Глупость была уничтожена. Будьте внимательны, дорогие хабравчане. Спасибо всем, кто дочитал этот пост до конца.
Tags:
Hubs:
-17
Comments 14
Comments Comments 14

Articles