Выбор случайного элемента с двойным смещением

#java #random

#java #Случайный

Вопрос:

Я уже прочитал много сообщений на эту тему, но я не удовлетворен тем, что я нашел.

У меня есть список объектов, давайте назовем их «L».

«L» имеет два свойства, « L.small » и « L.big «.

Я хочу выбрать случайную букву «L», но сместите выделение так, чтобы у меня было больше шансов выбрать объекты с более низким значением «L.small» и более высоким «L.big». Итак, чтобы было понятно, именно сочетание низкого « L.small » и высокого « L.big » делает объект более привлекательным.

Вот пример:

Допустим, максимально возможное значение L.small равно 50. а максимальное L.big значение равно 1000 000. Таким образом, L.small это случайный диапазон малых значений и L.big это случайный диапазон больших значений.

L1.small = 1 //максимально возможный .small

L1.big = 1000,000//максимально возможный .big

L2.small = 50 //наименее желательный .small

L2.big = 1 //наименее желательный .big

L3.small = 25 //довольно среднее

L3.big = 500 000 // довольно среднее

В этом примере наиболее вероятным будет выбран L1, наименее вероятным — L2, а промежуточным — L3.

Также, чтобы дать больше информации, мои реальные значения — это длинные значения.

Комментарии:

1. Вы сказали о «более вероятном» и «менее вероятном» — но насколько они вероятны? По сути, вам нужно предоставить какую-то функцию взвешивания, чтобы присвоить каждому элементу неотрицательный вес, после чего применяется остальная часть моего ответа. Мы не можем точно угадать функцию взвешивания… это может быть big - small 100 например, который будет работать для ваших выборочных данных, но это может быть не тот вес, который вы действительно хотите.

Ответ №1:

РЕДАКТИРОВАТЬ: Хорошо, я неправильно истолковал вопрос. Точный алгоритм, который вы используете, будет зависеть от того, насколько вы хотите, чтобы все было предвзятым. Например, вы могли бы эффективно просто рассматривать каждый объект как имеющий «вес» big - small … затем сложить все веса элементов в списке:

 int totalWeight = 0;
for (Foo foo : list)
{
    totalWeight  = foo.getWeight();
}

// As usual, normally you'd reuse an existing instance
Random rng = new Random();
int value = rng.nextInt(totalWeight);

// Pick an item based on the random value we've chosen
for (Foo foo : list)
{
    if (value < foo.getWeight())
    {
        return foo;
    }
    value -= foo.getWeight();
}
  

Комментарии:

1. Спасибо, Джон. Прошу прощения, мой вопрос не должен быть четко определен. Прежде всего, я хочу весь объект, а не foo.small или foo.big, я хочу Foo. Кроме того, я хочу, чтобы оба свойства, .small и .big учитывались вместе, чтобы с большей вероятностью был выбран объект с очень маленьким foo.small и очень большим foo.big, чем тот, который имеет, скажем, средние foo.small и foo.big.

2. @zuki: Хорошо, я понимаю… но, пожалуйста, приведите конкретный пример, включая то, насколько предвзято вы хотите, чтобы это внесло свой вклад.

3. @zuki: Вам следует отредактировать свой вопрос с помощью примера, а не помещать его в комментарии. Смотрите мою правку для примера подхода.

4. @jon-skeet: Спасибо, я добавил пример к вопросу, надеюсь, это поможет. Я могу вдаваться в подробности, если необходимо, но я не хочу путать вопрос с моей фоновой проблемой.

5. @jon-skeet: Чувак, это выглядит точно так же, как мой код прямо сейчас! Возможно, действительно сложная часть тогда заключается в объединении foo.small и foo.big в одно единственное foo.weight значение, которое является репрезентативным для предпочтения, чтобы одно было низким, а другое — большим

Ответ №2:

Если я вас правильно понимаю, вы хотите генерировать случайные переменные с неоднородными функциями плотности вероятности (PDF-файлы)? Если это так, вас может заинтересовать выборка с обратным преобразованием, которая позволяет преобразовать равномерно распределенное случайное число (такое, которое вы могли бы получить из java.util.Random ) в число с произвольным PDF.

Комментарии:

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