Моя задача:

Генерация случайных чисел от 1 до 20 с точностью до 1 десятичного знака.

Однако моя проблема так же проста, как mt_rand. Я хочу, чтобы большинство сгенерированных чисел было меньше примерно на 0,5–4,5, иногда между 4,5–10 и очень редко, если раз в 12–20 часов было между 10–20.

Я использовал следующее, но не знаю, с чего начать. Я очень простой программист-самоучка.

$min = 1;
$max = 20;
$suisse_interest = mt_rand ($min*10, $max*10) / 10

Может быть, если я вкратце объясню, зачем мне это нужно, это поможет ..

У меня есть онлайн-игра, и я хочу добавить 3 «банка», каждый из которых будет приносить разные проценты каждый час. В большинстве случаев я хочу, чтобы он был низким, но иногда и выше и очень редко очень высоким (15-20%).

В приведенном выше коде случайное число становится слишком большим или часто.

Любая помощь в этом приветствуется!

4
Harry Sinfield 22 Фев 2015 в 12:16

3 ответа

Лучший ответ

Попробуйте это. Вероятность 1,0 ~ 4,5 составляет около 96%, 4,5 ~ 10,0 - около 2%, а 10,0 ~ 20,0 - около 2%.

<?php
    // 1.0~4.5    96%
    // 4.5~10.0   2%
    // 10.0~20.0  2%

    function fun() {
        $num = mt_rand(1, 100);
        if ($num > 0 && $num <= 96) {
            $return = mt_rand(10, 45) / 10;  // 96%
        } else if ($num > 96 && $num <= 98) {
            $return = mt_rand(45, 100) / 10;  // 2%
        } else {
            $return = mt_rand(100, 200) / 10;  // 2%
        }
        return sprintf("%01.1f",$return);
    }

    echo fun();
?>
2
Wilon 22 Фев 2015 в 10:25

Это не проблема PHP.

Что вам нужно, так это нелинейный вероятностный закон, который затем можно реализовать в PHP.

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

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

Разумным приближением было бы суммирование 3 или 4 случайных величин с использованием центральной предельной теоремы .

Суммирование случайных значений от 0 до двойного среднего значения создаст приближение гауссовского значения с центром вокруг вашего среднего значения. Затем вы можете ограничить значения ниже средней, если вам не нужны низкие значения. В конечном итоге шансы получить среднюю ставку будут составлять 50%, а шанс получить вдвое большую ставку будет постоянно снижаться.

Увеличение числа сумм «сузит» кривую, уменьшая вероятность получения высокого значения.

Например:

define ("INTEREST_MEAN", 10);
define ("INTEREST_SPREAD", 5);
function random_interest ()
{
    $res = 0;
    for ($i = 0 ; $i != INTEREST_SPREAD ; $i++) $res += mt_rand(0, 2*INTEREST_MEAN);
    $res /= INTEREST_SPREAD; // normalize the sum to get a mean-centered result
    $res = max ($res, INTEREST_MEAN); // clamp lower values
}
0
kuroi neko 22 Фев 2015 в 12:09

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

$i = 0;
while($i<30) {
    $i++;
    $rand = mt_rand(0, 7000) / 100; // 0.0 ~ 70.0
    // This is the most important line:
    $output = round( 20*(pow(0.95,$rand)) , 1);
    echo "$output ";
}

Пример вывода:

1.8  4.3  2.6  5.5  3.7  15.5  1.6  0.6  0.6  1.6  5.8  
1.3  6.1  3.2  0.8  1.7  14.7  7.9  1.3  10.3  5.5  12.6  
1.5  8.4  1.5  0.9  13.3  5.8  7.5  1.7  

Как видите, печатается в основном меньшее количество.

Chart

Вероятность получить 20 в моем коде составляет около 1.4%, тогда как вероятность получить число smaller than 5 составляет около 78%

3
ByteHamster 22 Фев 2015 в 10:36