Как я могу сгенерировать N случайных значений, которые суммируются с заданным значением? - PullRequest
23 голосов
/ 30 апреля 2011

Мне нужна ваша помощь с небольшой проблемой.У меня есть четыре метки, и я хочу отобразить на них случайные значения от 0 до 100, а сумма их должна быть 100.

Это мой код:

private void randomly_Click(object sender, EventArgs e)
{
    double alpha = 0, beta = 0, gamma = 0, delta = 0;
    double temp;
    int tempDouble;

    Random rnd = new Random();

    alpha = rnd.Next(0, 100);

    temp = 100 - alpha;
    tempDouble = (int)temp;
    beta = rnd.Next(0, tempDouble);

    temp = 100 - (alpha + beta);
    tempDouble = (int)temp;
    gamma = rnd.Next(0, tempDouble);

    temp = 100 - (alpha + beta + gamma);
    tempDouble = (int)temp;
    delta = rnd.Next(0, tempDouble);

    temp = alpha + beta + delta + gamma;
    temp = 100 - temp;
    temp = temp / 4;

    alpha = alpha + temp;
    beta = beta + temp;
    gamma = gamma + temp;
    delta = delta + temp;

    cInsertion.Text = alpha.ToString();
    cMoyens.Text = beta.ToString();
    cInternational.Text = gamma.ToString();
    cRecherche.Text = delta.ToString();
}   

Проблема в том,что я даю альфе шанс получить значение biggest, а для дельты значение lowest.

Есть ли способ дать им одинаковый шанс получить реальный random значение?

Ответы [ 6 ]

45 голосов
/ 30 апреля 2011

Вы можете сделать что-то вроде этого:

double alpha = 0, beta = 0, gamma = 0, delta = 0, k = 0;
Random rnd = new Random();

alpha = rnd.Next(0, 100);
beta = rnd.Next(0, 100);
gamma = rnd.Next(0, 100);
delta = rnd.Next(0, 100);

k = (alpha + beta + gamma + delta) / 100;

alpha /= k;
beta /= k;
gamma /= k;
delta /= k;

cInsertion.Text = alpha.ToString();
cMoyens.Text = beta.ToString();
cInternational.Text = gamma.ToString();
cRecherche.Text = delta.ToString();

Таким образом, вы говорите, давайте возьмем случайное значение для всех 4 переменных, а затем мы масштабируем их с коэффициентом k, который сделает их сумму равной 100.

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

Что если вы поместите все четыре значения в массив, , затем перетасуете их , а затем назначите их в соответствии с их порядковым положением? Таким образом, каждая переменная (гамма, тета и т. Д.) Имеет равную вероятность получения высокого и низкого значений.

0 голосов
/ 30 апреля 2011

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

В коде вы просто то, что предложил Иван, за исключением альфа, бета, гамма и дельтавсе должны быть извлечены из гамма-распределений с параметрами формы alpha_shape, beta_shape, gamma_shape и delta_shape соответственно.(Пусть другой параметр гамма-распределения равен 1.) Эти параметры формы определяют ожидаемые относительные пропорции.

0 голосов
/ 30 апреля 2011

Вместо генерации отдельных чисел случайным образом сгенерируйте частичные суммы, а затем вычислите части:

double alpha, beta, gama, delta = 0;

var rnd = new System.Random();
var cuts = new List<double>();

cuts.Add(Math.Floor(rnd.Next(0, 101)));
cuts.Add(Math.Floor(rnd.Next(0, 101)));
cuts.Add(Math.Floor(rnd.Next(0, 101)));

cuts.Sort();

alpha = cuts[0];
beta = cuts[1] - cuts[0];
gamma = cuts[2] - cuts[1];
delta = 100 - cuts[2];
0 голосов
/ 30 апреля 2011

Это очень интересная проблема.Мне нравится решение @ Ivan_Ferić, я думаю, оно идеально, но у меня есть другая идея:

int total = 100;
Random rand = new Random();

int half = rand.next(0,total);   // the line

a = rand.Next(0,half);
b = max - a;
c = rand.Next(0,half);
d = max - c;

(не проверено, возможно, +/- 1 необходимо добавить к некоторым переменным.) Также вы можете перемешатьзначения.

Интересная часть идет сейчас.Если мы изменим «линию»:

min = <some_value>
max = <another_value>;
int half = rand.next(min,max);

... тогда мы можем точно настроить результат:

  • min = 0;макс = 100: оригинал;
  • мин = 20;max = 80: избегать маленьких цифр;
  • min = 33;max = 100: заставить два числа быть меньше 32.
0 голосов
/ 30 апреля 2011

A действительное случайное число?Короче нет.Только псевдослучайное число.

Генератор случайных чисел работает вне тактовых циклов, и типично видеть повторяющиеся последовательности.Используемое начальное число зависит от свойства .Tick текущего DateTime.Now (, если я правильно помню ).Существует множество приличных генераторов случайных чисел и API для .Net. Я бы порекомендовал искать их, если вы чувствуете, что у вас нет времени или желания вкладывать свои собственные усилия.

Перешли к комментариям, так как они кажутся более подходящими.

...