PHP Выбор случайного числа с весами

73
8

Предположим, что я хочу choose число из 1-10 наугад, но есть веса для каждого числа.


1 - 15% chance
2 - 15% chance
3 - 12% chance
4 - 12% chance
5 - 10% chance
6 - 10% chance
7 - 8% chance
8 - 8% chance
9 - 5% chance
10 - 5% chance

Как я буду кодировать это в PHP?

спросил(а) 2012-05-12T00:52:00+04:00 7 лет, 11 месяцев назад
1
Решение
80

Я предполагаю, что ваши проценты составляют до 100%?


Создайте массив с


15 times a '1' value, 
15 times a '2' value,
...
10 times a '6' value,
8 times a '7' value,
...
5 times 1 '10' value

В итоге вы получите единственный массив, содержащий 100 элементов.


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

ответил(а) 2012-05-12T00:54:00+04:00 7 лет, 11 месяцев назад
51

примерное эхо-значение с весом OP с классом ниже:


echo 1+Rand::get_weighted_rand(array(15,15,12,12,10,10,8,8,5,5));

и класс:


class Rand
{
/*
* generates a random value based on weight
* @RETURN MIXED: returns the key of an array element
* @PARAM $a ARRAY:
* the array key is the value returned and the array value is the weight
* if the values sum up to less than 100 than the last element of the array
* is the default value when the number is out of the range of other values
* @PARAM $p INT: number of digits after decimal
*
* i.e array(1=>20, 'foo'=>80): has an 80 chance of returning Foo
* i.e array('bar'=>0.5, 2=>1, 'default'=>0), 1: 98.5% chance of returning default
*/
public static function get_weighted_rand($a, $p=0)
{
if(array_sum($a)>100)
return FALSE;#total must be less than 100
$p=pow(10, $p+2);
$n=mt_rand(1,$p)*(100/$p);
$range=100;
foreach($a as $k=>$v)
{
$range-=$v;
if($n>$range)
return $k;
}
#returning default value
end($a);
return key($a);
}
}

ответил(а) 2012-05-12T00:57:00+04:00 7 лет, 11 месяцев назад
51

Если ваши веса находятся в процентах, выберите случайное число от 0 до 100, затем итеративно вычтите проценты, пока не пересечете нуль:


<?php
function getWeightedRandom() {
$weights = array(15, 15, 12, ...); // these should add up to 100
$r = rand(0, 99);
for ($i=0; $i<count($weights); $i++) {
$r -= $weights[$i];
if ($r < 0)
return $i+1;
}
}
?>

Это дает дополнительное преимущество поддержки нецелых весов.

ответил(а) 2012-05-12T00:57:00+04:00 7 лет, 11 месяцев назад
37

Поместите их все несколько раз в массив, например. 1 15 раз, 3 12 раз и так далее.
Затем выберите случайное число из этого массива.


$array = array_merge (array_fill (0, 15, 1), array_fill (0, 15, 2), array_fill (0, 12, 3), array_fill (0, 12, 4), array_fill (0, 10, 5), array_fill (0, 10, 6), array_fill (0, 8, 7), array_fill (0, 8, 8), array_fill (0, 5, 9), array_fill (0, 5, 10));
$random_number = array_rand ($array);

ответил(а) 2012-05-12T00:55:00+04:00 7 лет, 11 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема