PHP随机数生成

4

我的任务:

生成1到20之间的随机数,精确到1位小数。

然而,我遇到了一个问题,就是简单使用mt_rand函数无法满足要求。我希望大部分生成的数字都在0.5-4.5之间,偶尔有一些数字在4.5-10之间,还有一些非常罕见的数字会在10-20之间,比如说每12-20个小时只会出现一次。

我一直在使用下面的代码,但我不知道该怎么继续下去,因为我只是一个基础的自学程序员。

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

也许如果我简要解释一下为什么我需要这个,可能会有所帮助...
我拥有一个在线游戏,想添加3个“银行”,每个银行每小时产生不同的利息。大部分时间我想要低利息,但有时候需要更高,而且很少需要非常高(15-20%)。
使用以上代码,随机数太频繁地变得过高。
非常感谢您提供任何帮助!

可能是定义随机数百分比的重复问题。 - Rizier123
由于您想要创建的分布是单调递减的,因此您可以使用“Ziggurat算法”将您的分布(均匀分布)映射到您想要的分布上(您可以任意创建)。或者您可以使用Box-Muller变换,但它的效率较低(而且由于您需要频繁进行此操作,您可能希望预先计算Ziggurat算法中描述的表格)。 - will
3个回答

3
您需要进行指数计算。如果使用类似以下函数的函数,则低数字的概率会增加。当然,您需要稍微调整一下这些数字,以提供适合您需求的输出。
$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  

如您所见,大部分打印的数字较小。

图表

在我的代码中,得到数字 20 的概率约为 1.4%,而得到一个小于 5 的数字的概率约为 78%


完美,这个答案和另一个答案都有效。正是我想要的!谢谢! - Harry Sinfield

2
尝试这个。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();
?>

非常感谢,这对我帮助很大。现在一切都更加清晰明了! - Harry Sinfield
再问一句,如果您不介意的话。我该如何将echo fun()的结果放入我的数据库中。我知道下面的代码可能没有意义,但也许它能更清楚地表达我的目标。$interest = (fun()的结果) mysql_query("UPDATE r$game[0]_$tab[pimp] SET suisseint=$interest WHERE id=$user1no[id];");谢谢! - Harry Sinfield
因为春节晚了,对不起。你的SQL语句是正确的,请检查表结构并重试。 - Wilon

0

这不是一个特定于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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接