PHP: Случайное получение значения с указанием шанса
Как получить рандомное значение, указав шанс его выпадения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// Значение => шанс его выпадения $chances = [ 'a' => 75, 'b' => 20, 'c' => 5 ]; $selectArray = []; // Массив, из которого будем выбирать рандомное значение foreach ($chances as $item => $chance) { $selectArray = array_merge($selectArray, array_fill(0, $chance, $item)); } shuffle($selectArray); var_dump($selectArray[rand(0, sizeof($selectArray)-1)]); |
Тесты данного метода:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
// Значение => шанс его выпадения $chances = [ 'a' => 75, 'b' => 20, 'c' => 5 ]; // Чтоб результаты теста были достоверными, сумма шансов должна быть 100% !!! /** * Получить рандомное значение, учитывая шанс выпадения * @param array $chances Массив вида [значение => шанс выпадения] */ function getRandomItem(array $chances){ $selectArray = []; // Массив, из которого будем выбирать рандомное значение foreach ($chances as $item => $chance) { $selectArray = array_merge($selectArray, array_fill(0, $chance, $item)); } shuffle($selectArray); return $selectArray[rand(0, sizeof($selectArray)-1)]; } /** * Тесты */ $results = []; $iters = 100000; for ($i = 0; $i < $iters; $i++) { $result = getRandomItem($chances); $results[$result] = ($results[$result] ?? 0) + 1; } // Вывод результатов теста ksort($results); foreach ($results as $item => $chance) { echo "Значение '$item' выпадало в " . ($chance / $iters * 100) . "% случаев \n"; } // Результаты после 100к итераций: // Значение 'a' выпадало в 74.724% случаев // Значение 'b' выпадало в 20.279% случаев // Значение 'c' выпадало в 4.997% случаев |
Тот же тест в среде DevelNext
Демо проект:
test-random.dnproject (224 Загрузки)
Весь код в загрузчике.
Есть также немного неправильный способ – сделать для каждого числа/символа свой процент, и повторить его в строке (помню, что есть какая-то функция в php для этого) столько раз, сколько процентов, после этого использовать str::random