Случайные числа, которые добавляют к 100: Matlab

29

[Я разбиваю номер популяции на разные матрицы и хочу проверить мой код с использованием случайных чисел на данный момент.]

Быстрый вопрос ребятам и спасибо за вашу помощь заранее -

Если я использую;

 100*rand(9,1)

Каков наилучший способ добавить эти 9 чисел в 100?

Мне бы хотелось 9 случайных чисел от 0 до 100, которые добавляют до 100.

Есть ли встроенная команда, которая делает это, потому что я не могу найти ее.

Теги:
random

4 ответа

70
Лучший ответ

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

Попробуйте этот простой тест в двух измерениях. Создайте огромную случайную выборку, затем масштабируйте ее до суммы до 1. Я буду использовать bsxfun для масштабирования.

xy = rand(10000000,2);
xy = bsxfun(@times,xy,1./sum(xy,2));
hist(xy(:,1),100)

Если бы они были действительно равномерно случайными, то координата x была бы равномерной, как и координата y. Любое значение будет в равной степени вероятным. По сути, для двух точек суммирования до 1 они должны лежать вдоль линии, соединяющей две точки (0,1), (1,0) в плоскости (x, y). Для того чтобы точки были равномерными, любая точка вдоль этой линии должна быть одинаково вероятна.

Изображение 6387

Четкая однородность не работает, когда я использую решение масштабирования. Любая точка на этой строке НЕ одинаково вероятна. Мы видим то же самое, что происходит в трехмерном пространстве. Смотрите, что на 3-м рисунке здесь точки в центре треугольной области более плотно упакованы. Это отражение неравномерности.

xyz = rand(10000,3);
xyz = bsxfun(@times,xyz,1./sum(xyz,2));
plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
view(70,35)
box on
grid on

Изображение 6388

Опять же, простое решение масштабирования выходит из строя. Он просто НЕ производит действительно однородные результаты в интересующей области.

Мы можем сделать лучше? Ну да. Простым решением в 2-d является создание единственного случайного числа, которое обозначает расстояние по линии, соединяющей точки (0,1) и 1,0).

t = rand(10000000,1);
xy = t*[0 1] + (1-t)*[1 0];
hist(xy(:,1),100)

Изображение 6389

Можно показать, что теперь ЛЮБОЙ пункт вдоль линии, определяемой уравнением x + y = 1, в единичном квадрате, в равной степени вероятен. Это отражается на хорошей плоской гистограмме.

Разве трюк, предложенный Дэвидом Шварцем, работает в n-измерениях? Ясно, что это делается в 2-й, и на рисунке ниже показано, что он делает это в 3-х измерениях. Без глубокой мысли по этому вопросу я считаю, что он будет работать для этого основного случая, о котором идет речь, в n-измерениях.

n = 10000;
uv = [zeros(n,1),sort(rand(n,2),2),ones(n,1)];
xyz = diff(uv,[],2);

plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
box on
grid on
view(70,35)

Изображение 6390

Также можно загрузить функцию randfixedsum из обмена файлами, вклад Роджера Стаффорда. Это более общее решение для создания действительно однородных случайных множеств в единичном гиперкубе с любой заданной фиксированной суммой. Таким образом, для генерации случайных множеств точек, лежащих в единичном 3-кубе, при условии ограничения они суммируют до 1,25...

xyz = randfixedsum(3,10000,1.25,0,1)';
plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
view(70,35)
box on
grid on

Изображение 6391

  • 1
    Я знаю, что это старый вопрос, но может ли кто-нибудь объяснить мне этот ответ? Как «сгенерировать» одно случайное число, обозначающее расстояние вдоль линии, соединяющей точки (0,1) и 1,0). Можно показать, что ЛЮБАЯ точка указывает на линию, определяемую уравнением x + y = 1, в единичном квадрате теперь с равной вероятностью был выбран. "? Это даже точно? Часть моего замешательства состоит в том, что код Matlab, который он выложил для доказательства, просто показал, что случайные числа были одинаковыми, однако они не были масштабированы до 1 ... что и составляет весь смысл.
  • 0
    @ jdfinch3: решаемая проблема - «выбрать пару чисел x, y, такую, что x + y = 1.» Решение таково: «выберите x в диапазоне [0, 1], а затем вычислите y = 1 - x». Это гарантирует, что пара (x, y) будет равномерно выбрана из вселенной всех возможных пар. Гистограмма демонстрирует, что это работает. Ответ Дэвида Шварца дает обобщение для более чем двух измерений (т. Е. Кортежей с более чем двумя элементами).
Показать ещё 2 комментария
50

Один простой способ - выбрать 8 случайных чисел от 0 до 100. Добавьте 0 и 100 в список, чтобы дать 10 чисел. Сортируйте их. Затем выведите разницу между каждой последовательной парой чисел. Например, здесь 8 случайных чисел от 0 до 100:

96, 38, 95, 5, 13, 57, 13, 20

Итак, добавьте 0 и 100 и выполните сортировку.

0, 5, 13, 13, 20, 38, 57, 95, 96, 100

Теперь вычитаем:

5-0 = 5
13-5 = 8
13-13 = 0
20-13 = 7
38-20 = 18
57-38 = 19
95-57 = 38
96-95 = 1
100-96 = 4

И там у вас есть девять чисел, которые суммируются до 100: 0, 1, 4, 5, 7, 8, 18, 19, 38. Это я получил нуль, а один был просто странным удачей.

  • 2
    Потрясающие! Я люблю это. Я адаптировал ваш метод для создания серии случайных чисел, сумма которых равна 0. Это позволяет мне создавать случайные изменения без какого-либо чистого эффекта. (Т.е. движущийся игровой спрайт, кажется, перемещается случайным образом более или менее, но никогда не выходит за пределы экрана. ^^)
  • 3
    Это работает только тогда, когда вам разрешено использовать любое случайное число от 0 до вашей суммы! Например, это не будет работать, когда диапазон случайных чисел меньше, чем желаемая сумма.
Показать ещё 3 комментария
1

Еще не поздно дать правильный ответ

Расскажите о выборке X1... XN в диапазоне [0... 1], чтобы Sum (X1,..., XN) равнялся 1. Тогда вы можете перемасштабировать его до 100

Это называется дистрибутив Дирихле, а ниже - код для его выборки. Самый простой случай - когда все параметры равны 1, тогда все предельные распределения для X1,..., XN будут U (0,1). В общем случае с параметрами, отличными от 1s, маргинальные распределения могут иметь пики.

----------------- взято из здесь ------- --------------

Дирихле - вектор гамма-случайных величин единичного масштаба, нормированный их суммой. Таким образом, без проверки ошибок вы получите следующее:

a = [1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0]; // 9 numbers to sample
n = 10000;
r = drchrnd(a,n)

function r = drchrnd(a,n)
  p = length(a);
  r = gamrnd(repmat(a,n,1),1,n,p);
  r = r ./ repmat(sum(r,2),1,p);
0

Возьмите список номеров N - 1, создайте список номеров N + 1, вставив 0 и 100, отсортируйте список и разделите их на N номеров.

  • 0
    Это не приводит к равномерному распределению.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню