Если вы ищете нормально распределенные числа с наименьшей корреляцией, насколько это возможно, и вам необходимо строго об этом *, я бы посоветовал вам воспользоваться следующим математическим подходом и перевести в код.
(*строго говоря: проблема с другими подходами состоит в том, что вы можете получить «длинные хвосты» в своих дистрибутивах - другими словами, редко, но возможно иметь выбросы, которые сильно отличаются от вашего ожидаемого результата)
- Генерировать N-1 независимых и одинаково распределенных (IID) гауссовых случайных величин v 0 , v 1 , v 2 , ... v N-1 , чтобы соответствовать N-1 степеням свободы вашей задачи.
- Создать вектор столбца V, где V = [0 v 0 , v 1 , v 2 , ... v N-1 ] T
- Используйте фиксированную весовую матрицу W, где W состоит изортонормированная матрица **, верхняя строка которой [1 1 1 1 1 1 1 ... 1] / sqrt (N).
- Ваш выходной вектор - это произведение WV + SU / N where S - искомая сумма, а U - вектор-столбец 1.Другими словами, i-я выходная переменная = произведение точек (строка #i матрицы W) и вектор-столбец V, добавленные к S / N.
Стандартное отклонение каждой выходной переменнойбудет (я считаю, не могу проверить прямо сейчас) sqrt (N / N-1) * стандартное отклонение входных случайных величин.
** ортонормированная матрица: это сложная часть, я положилв вопрос на math.stackexchange.com и есть простая матрица W, которая работает и может быть определена алгоритмически только с 3 различными значениями, так что вам на самом деле не нужно создавать матрицу.
W является отражением домохозяина vw, где v = [sqrt (N), 0, 0, 0, ...] и w = [1 1 1 1 1 ... 1] можно определить как:
W(1,i) = W(i,1) = 1/sqrt(N)
W(i,i) = 1 - K for i >= 2
W(i,j) = -K for i,j >= 2, i != j
K = 1/sqrt(N)/(sqrt(N)-1)
Проблема с подходом Марка:
Почему бы просто не сгенерировать правильное количество равномерно распределенных случайных чисел, суммировать их и масштабировать?
в том, что если вы сделаете это, вы получите дистрибутив "длинный хвост".Вот пример в MATLAB:
>> X = rand(100000,10);
>> Y = X ./ repmat(sum(X,2),1,10);
>> plot(sort(Y))
Я сгенерировал 100 000 наборов из N = 10 чисел в матрице X и создал матрицу Y, где каждая строка Y является соответствующей строкой X, разделенной на ее сумму (так что каждая строка Y суммирует до 1,0)
Построение отсортированных значений Y (каждый столбец сортируется отдельно) дает примерно одинаковое совокупное распределение:
Истинное равномерное распределение даст прямую линию от 0 до максимального значения.Вы заметите, что это отчасти похоже на истинное равномерное распределение, за исключением конца, где есть длинный хвост.Существует избыток чисел, генерируемых между 0,2 и 0,5.Хвост становится хуже при больших значениях N, потому что, хотя среднее значение чисел уменьшается (среднее = 1 / N), максимальное значение остается равным 1,0: вектор, состоящий из 9 значений 0,0 и 1 значения 1,0, действителени может генерироваться таким образом, но патологически редко.
Если вас это не волнует, продолжайте и используйте этот метод.И, возможно, существуют способы генерирования «почти» -однородных или «почти» гауссовских распределений с желаемыми суммами, которые намного проще и эффективнее, чем те, которые я описал выше.Но я предупреждаю вас, чтобы вы были осторожны и понимали последствия выбранного вами алгоритма.
Одно исправление, которое оставляет вещи как-то равномерно распределенными без длинного хвоста, выглядит следующим образом:
- Генерация вектора V = N равномерно распределенных случайных чисел от 0,0 до 1,0.
- Найти их сумму S и их максимальное значение M.
- Если S
- Вывести вектор V * S желаемый / S
Пример в MATLAB для N = 10:
>> X = rand(100000,10);
>> Y = X ./ repmat(sum(X,2),1,10);
>> i = sum(X,2)>(10/2)*max(X,[],2);
>> plot(sort(Y(i,:)))