Выбор n чисел с фиксированной суммой - PullRequest
7 голосов
/ 11 апреля 2011

В каком-то коде я хочу выбрать n случайные числа в [0,1), которые составляют 1.

Я делаю это, выбирая числа независимо в [0,1) и нормализуя их путем деления каждогоодин на общую сумму:

numbers = [random() for i in range(n)]
numbers = [n/sum(numbers) for n in numbers]

Моя "проблема" в том, что дистрибутив, который я получаю, довольно искажен.Выбирая миллион чисел, ни одно из них не превысит 1/2.Некоторым усилием я вычислил pdf, и это нехорошо.

Вот странно выглядящий pdf, который я получаю для 5 переменных:

enter image description here

есть идея для хорошего алгоритма выбора чисел, что приводит к более равномерному или простому распределению?

Ответы [ 3 ]

19 голосов
/ 11 апреля 2011

Вы хотите разделить расстояние от 0 до 1.

Выберите n - 1 чисел от 0 до 1, отсортируйте их и определите расстояния между ними.

Это разделит пространство от 0 до 1, что должно дать случайный большой результат, который вы не получаете.

Несмотря на это, при больших значениях n можно ожидать, что максимальное значение также будет уменьшаться, но не так быстро, как ваш метод.

6 голосов
/ 11 апреля 2011

Возможно, вас заинтересует распределение Дирихле , которое используется для генерации величин, равных 1, если вы ищете вероятности. Там также есть раздел о том, как сгенерировать их с помощью гамма-распределения здесь .

0 голосов
/ 13 апреля 2017

Другой способ получить n случайных чисел, которые в сумме до 1:

import random


def create_norm_arr(n, remaining=1.0):
    random_numbers = []
    for _ in range(n - 1):
        r = random.random()  # get a random number in [0, 1)
        r = r * remaining
        remaining -= r
        random_numbers.append(r)
    random_numbers.append(remaining)
    return random_numbers

random_numbers = create_norm_arr(5)
print(random_numbers)
print(sum(random_numbers))

Это делает более высокие числа более вероятными.

...