Python: ошибка округления искажает равномерное распределение

Мне нужно отобрать 10 равномерно распределенных случайных чисел от 0 до 1. Поэтому я подумал, что следующий код на питоне сделает это:

positions = []
for dummy_i in range(1000000):
    positions.append(round(random.random(),1))

Однако при отображении результата на гистограмме результат выглядит следующим образом:

Частота округления чисел до 1 знака после запятой

Таким образом, округление, кажется, разрушает равномерное распределение, созданное random.random(). Интересно, что вызывает это и как предотвратить это. Спасибо за вашу помощь!


person harlekin    schedule 17.12.2015    source источник
comment
Простой способ получить количество (и увидеть, что это гистограмма искажает вещи) - это использовать collections.Counter: попробуйте collections.Counter(round(random.random(), 1) for _ in range(10**6)), и вы увидите, что количество примерно одинаково для 0.1 до 0.9.   -  person Mark Dickinson    schedule 17.12.2015


Ответы (4)


Кажется, у вас возникла проблема позже в коде... (например, при сборе статистики). Проверьте этот меньший фрагмент:

import random, collections
data = collections.defaultdict(int)
for x in range(1000000):
    data[round(random.random(),1)] += 1
print(data)

Вы увидите, что 0 и 1, конечно же, имеют около половины выборок других значений, которые практически однородны.

Например, я получил:

defaultdict(<class 'int'>,
            {0.4: 100083,
             0.9: 99857,
             0.3: 99892,
             0.8: 99586,
             0.5: 100108,
             1.0: 49874,     # Correctly about half the others
             0.7: 100236,
             0.2: 99847,
             0.1: 100251,
             0.6: 100058,
             0.0: 50208})    # Correctly about half the others
person 6502    schedule 17.12.2015

Ваш способ построения гистограммы неверен. У вас должно получиться примерно:

50к за 0 и 1

100к на все остальные номера

Но ваш третий бин — от 0,2 включительно до 0,3 включительно, что дает 200 тыс., а ваш четвертый бин — от 0,3 эксклюзивно до 0,4 эксклюзивно, что дает ноль.

Попробуйте создать гистограмму с краями 0,05, 0,15 и т. д., тогда у вас не будет таких ошибок точности.

person Daniel    schedule 17.12.2015

попробуй это

positions = []
for dummy_i in range(10):
    positions.append(random.randint (0, 10) / 10)
person Victor Voronov    schedule 17.12.2015

Я думаю, что здесь было бы чище и эффективнее использовать Numpy:

import numpy as np
positions = np.random.random(10000)
positions = np.round(positions, decimals=3)
person piman314    schedule 17.12.2015
comment
Хм. На самом деле это не ответ на вопрос ОП: это комментарий, маскирующийся под ответ. - person Mark Dickinson; 18.12.2015