Получение N случайных чисел с суммой M
Я хочу получить N случайных чисел, чья сумма является значением.
Например, предположим, я хочу 5 случайных чисел, сумма которых равна 1.
Тогда действительная возможность:
0.2 0.2 0.2 0.2 0.2
Другая возможность:
0.8 0.1 0.03 0.03 0.04
И так далее. Мне это нужно для создания матрицы вещей для нечетких C-средних.
Ответы
Ответ 1
Короткий ответ:
Просто сгенерируйте N случайных чисел, вычислите их сумму, разделите каждое на сумму и умножьте на M.
Более длинный ответ:
Приведенное выше решение не дает равномерного распределения, которое может быть проблемой в зависимости от того, для чего используются эти случайные числа. Другой метод, предложенный Матти Вирккуненом:
Сгенерируйте N-1 случайных чисел от 0 до 1, добавьте в список сами числа 0 и 1, отсортируйте их и возьмите различия соседних чисел.
Я не уверен, что это даст равномерное распределение
Ответ 2
Генерировать случайные числа N-1 между 0 и 1, добавлять числа 0 и 1 в список, сортировать их и принимать различия соседних чисел.
Ответ 3
Я думаю, что стоит отметить, что принятый в настоящее время ответ не дает равномерного распределения:
"Просто сгенерируйте N случайных чисел, вычислите их сумму, разделите их на сумма"
Чтобы увидеть это, рассмотрим случай N = 2 и M = 1. Это тривиальный случай, так как мы можем сгенерировать список [x, 1-x], выбирая x равномерно в диапазоне (0,1).
Предлагаемое решение порождает пару [x/(x + y), y/(x + y)], где x и y равномерны в (0,1). Чтобы проанализировать это, выберем некоторое г такое, что 0 < z < 0,5 и вычислить вероятность того, что
первый элемент меньше z. Эта проблема должна быть равна z, если распределение равномерно. Однако мы получаем
Prob (x/(x + y) < z) = Prob (x < z (x + y)) = Prob (x (1-z) < zy) = Prob (x < y ( z/(1-z))) = z/(2-2z).
Я сделал несколько быстрых вычислений, и кажется, что единственное решение, которое пока что привело к равномерному распределению, было предложенное Матти Вирккуненом:
"Генерировать случайные числа N-1 между 0 и 1, добавлять числа 0 и 1 в список, сортировать их и брать различия соседних чисел".
Ответ 4
В Java:
private static double[] randSum(int n, double m) {
Random rand = new Random();
double randNums[] = new double[n], sum = 0;
for (int i = 0; i < randNums.length; i++) {
randNums[i] = rand.nextDouble();
sum += randNums[i];
}
for (int i = 0; i < randNums.length; i++) {
randNums[i] /= sum * m;
}
return randNums;
}
Ответ 5
Просто сгенерируйте N случайных чисел, вычислите их сумму, разделите каждое на сумму.
Развертывая принятый ответ Гийома, здесь Java-функция, которая делает именно это.
public static double[] getRandDistArray(int n, double m)
{
double randArray[] = new double[n];
double sum = 0;
// Generate n random numbers
for (int i = 0; i < randArray.length; i++)
{
randArray[i] = Math.random();
sum += randArray[i];
}
// Normalize sum to m
for (int i = 0; i < randArray.length; i++)
{
randArray[i] /= sum;
randArray[i] *= m;
}
return randArray;
}
В тестовом прогоне getRandDistArray(5, 1.0)
вернул следующее:
[0.38106150346121903, 0.18099632814238079, 0.17275044310377025, 0.01732932296660358, 0.24786240232602647]
Ответ 6
Эта проблема эквивалентна задаче генерации случайных чисел с Распределение Дирихле. Для генерации N положительных чисел, которые суммируются с положительным числом M, где каждая возможная комбинация одинаково вероятна:
-
Генерировать N экспоненциально распределенных случайных чисел. Один из способов генерации такого числа можно записать как —
number = -ln(1.0 - RNDU())
где ln(x)
- естественный логарифм x
, а RNDU()
- метод, который возвращает случайное число 0 или больше и меньше 1 (например, JavaScript Math.random()
). Обратите внимание, что генерация этих чисел с равномерным распределением не является идеальной, поскольку приведет к смещенному распределению комбинаций случайных чисел.
- Разделите числа, сгенерированные таким образом по их сумме.
- Умножьте каждое число на M.
В результате получается N чисел в распределении Дирихле, сумма которых приблизительно равна M (я говорю "приблизительно" из-за ошибки округления).
Эта проблема также эквивалентна задаче генерации случайных чисел равномерно из N-мерного симплекса.
Ответ 7
- Создание случайных чисел N-1.
- Вычислить сумму указанных чисел.
- Добавьте разницу между вычисленной суммой и желаемой суммой к набору.
Теперь у вас есть N случайных чисел, и их сумма - это желаемая сумма.
Ответ 8
К сожалению, некоторые ответы здесь неверны, если вы хотите получить равномерно случайные числа. Самое простое (и самое быстрое во многих языках) решение, которое гарантирует равномерно случайные числа, это просто
# This is Python, but most languages support the Dirichlet.
import numpy as np
np.random.dirichlet(np.ones(n))*m
где n
- количество случайных чисел, которые вы хотите сгенерировать, а m
- сумма результирующего массива. Этот подход дает положительные значения и особенно полезен для генерации достоверных вероятностей, которые составляют 1 (пусть m = 1).
Ответ 9
Вы немного ограничены ограничениями. Много и много процедур будут работать.
Например, обычно ли номера распределены? Равномерное?
Я полагаю, что все числа должны быть положительными и равномерно распределены вокруг среднего значения, M/N.
Попробуйте это.
- mean = M/N.
- Генерировать значения N-1 между 0 и 2 *. Это может быть стандартное число от 0 до 1, u, а случайное значение - (2 * u-1) * означает создание значения в соответствующем диапазоне.
- Вычислить сумму значений N-1.
- Оставшееся значение - N-сумма.
- Если оставшееся значение не соответствует ограничениям (от 0 до 2 *), повторите процедуру.
Ответ 10
Найдите случайное число между 0 и общим количеством, которое вы хотите. Вычтите число из общего числа. Повторите n-1 раз. Конечная сумма - это окончательное число.
List<Double> result= new ArrayList<Double>();
double total = 1.0;
for (int i = 0;++i < 5;) {
double db = Math.random() * total;
result.add( db );
total -= db;
}
result.add( total );