php шанс в процентах

Это действительно больше вопрос подхода, но я представляю его на php.

Предположим, у нас есть список из четырех процентов того, что событие Give произойдет на итерации.

array=('walk the dog'=>.25,'read the paper'=>.25,'drink coffee'=>.0,'listen to music'=>.50)

(Ключи - это просто тесты - на практике это будет использоваться в шаблоне стратегии, который случайно применяет разные методы к объекту, используя call_user_func())

В цикле, каким будет лучший способ выбрать одно из этих событий путем случайного выбора с учетом их соответствующих весов (IE, для этой конкретной конфигурации будет прослушано много музыки, а не много кофе). пил)

В настоящее время у меня есть что-то вроде:

for($i=1;$i<=3;$i++){
  $rand = 1/rand(1,10);
  //choose from the list
}

Но для этого потребуется сопоставить проценты с диапазонами значений (50-100% становятся прослушиванием музыки, 0-25% гуляют с собакой и 25-50% читают газету), потому что «значение» для этой итерации рассчитывается как число с плавающей запятой. между 0 и 1. Этот вид меняет способ записи процентов.

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


person DeaconDesperado    schedule 10.01.2012    source источник
comment
Кстати, в вашем списке 4 пункта, а не три.   -  person MrGlass    schedule 10.01.2012


Ответы (4)


Я бы сделал что-то вроде:

$arr = array (
    'walk the dog'    =>  array('min' =>  0, 'max' =>  25),
    'read the paper'  =>  array('min' => 25, 'max' =>  50),
    'drink coffee'    =>  array('min' =>  0, 'max' =>   0),
    'listen to music' =>  array('min' => 50, 'max' => 100),
);

$rnd = rand(1,100);
foreach($arr as $k =>$v) {
    if ($rnd > $v['min'] && $rnd <= $v['max']) {
        echo $k,"\n";
    }
}
person Toto    schedule 10.01.2012

Рассматривали ли вы возможность использования процентных значений в качестве совокупного числа?

$array = array('walk the dog'=>.25,'read the paper'=>.25,'drink coffee'=>.0,'listen to music'=>.50);

$rand = rand();
$cur = 0;
foreach ($key=>$val in $array) {
  $cur += $val;
  if ($rand <= $cur)
    return $key;
}

Это предполагает, что значения в массиве в сумме составляют 1. Порядок также не имеет значения...

person CNeo    schedule 10.01.2012

$arr = array('walk the dog'=>25,'read the paper'=>25,'listen to music'=>50);
$rand = rand(1,100);
$sum = 0;
$action = '';

foreach ($arr as $k => $v) {
    $sum .= $k;
    if ($sum <= $k)
        $action = $v;
}

Удалены те, у которых значение ключа равно нулю, и умножено значение ключа на 100, чтобы сделать его более читаемым.

person OptimusCrime    schedule 10.01.2012
comment
Это то, что я более или менее хотел применить, но проблема в том, чтобы выбрать правильный из списка. Так как есть четыре потенциальных события для любого прохода цикла (3, если мы не учитываем кофе, так как в этой конфигурации он установлен на ноль). - person DeaconDesperado; 10.01.2012
comment
Всегда ли сумма этих ключей равна 100 (или 1)? - person OptimusCrime; 10.01.2012
comment
Да, добавление новых в список уменьшит вероятность появления других. В сумме они всегда будут равны 1 (или 100, если рассчитывать по этой шкале). - person DeaconDesperado; 10.01.2012
comment
Я думаю, что у вас может быть опечатка с заменой $k на $v, но да, это работает. - person DeaconDesperado; 10.01.2012
comment
Какой смысл генерировать случайное число, если оно даже не используется? - person dukevin; 24.06.2012

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

Затем вы просто перебираете массив и возвращаете событие, для которого его значение больше, чем $rand.

person crenate    schedule 10.01.2012