彩票算法 - PHP - 数学似乎不错,但功能是否有效?

ver*_*jas 6 php algorithm

我想进行自定义彩票提取,以激励用户参与在线实验.规则是:

  • 10%可获得10美元
  • 1%的几率获得50美元
  • 0.1%的几率获得500美元

彩票是一个PHP函数,它被调用一次并返回奖品(0,10,50或500).我创建了下面的函数,经过70 000次试验后,统计数据是:

  • 10美元9.11%
  • 50%的.91%
  • 500美元的.01%

我应该担心这个算法吗?有没有比mt_rand更好的方法来创造良好的机会分配?

function lottery() {
  // winnings before extraction
  $win=0;

  // choose a winning number between 1 and 10
  $target=mt_rand(1,10);

  // make three independent extractions, each with 1/10 probability
  if (mt_rand(1,10) == $target) {
    // if first extraction is the winning number -> prize=10
    // probability: 1/10
    $win=10;

    if (mt_rand(1,10) == $target) {
        // if second extraction is ALSO the winning number -> prize=50
        // probability: 1/10 * 1/10
        $win=50;

        if (mt_rand(1,10) == $target) {
            // if third extraction is ALSO the winning number -> prize=500
            // probability: 1/10 * 1/10 * 1/10
            $win=500;
        }
    }
  }
  // return the prize
  return $win;
}
Run Code Online (Sandbox Code Playgroud)

谢谢你帮助新手!

Mar*_*iel 12

这是因为在代码中获取每个代码的真正机会是:

10美元 - 0.1*0.9= 9%

50美元 - 0.1*0.1*0.9= 0.9%

500美元 - 0.1*0.1*0.1= 0.1%


这不是因为mt_rand().这只是一个统计问题.尝试运行更多迭代,您将看到数字收敛到上面的数字.

正如你在上面的计算中所看到的那样,你第一次做到正确就得不到10美元,你第一次得到10美元得到10美元,第二次得到错误(90%).

按照这个逻辑,你可以延长相同的数学50美元(前两次正确,10%和10%,然后第三次错误,90%),500美元(你得到钻孔).

使用您的特定代码,真实概率的计算如上所述.


请参阅已接受答案中的代码,以获得具有准确概率的正确代码.


M O*_*ehm 2

在给定的概率下,您有四种结果:

  • 0.1% 的概率赢得 500 美元。
  • 1% 的概率赢得 500 美元。
  • 10% 的概率赢得 500 美元。

第四个结果——没有获胜——是100%减去其他三个结果的总和,即88.9%。

马克·加布里埃尔(Mark Gabriel)解释了为什么你的初始代码失败了:通过晋升赢得 10 至 50 美元获奖者的 10%,你将他们从 10 美元获奖者池中剔除,而这将只占所有人的 9%。

Pham Trung 提出了一个解决方案,从迄今为止未获奖的池子中取出金额较高的获奖者,并调整概率。这是一个可行的解决方案,但我认为最简单的解决方案是仅调用随机数生成器一次。

该解决方案也最能体现门票类比:您将 10,000 张门票放入一个盒子中。从 1 到 1000 的 1,000 张彩票将赢得 10 美元。从 1001 到 1100 的 100 张彩票将赢得 50 美元。从 1101 到 1110 的十张彩票将赢得 500 美元。从 1111 开始的所有 8890 彩票都没有赢得任何东西:

function lottery() {
    var pick = Math.floor(10000 * Math.random());
               // random number in the range [0, 10000).

    if (pick < 1000) return 10;
    if (pick < 1100) return 50;
    if (pick < 1110) return 500;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在此代码中,门票上只写有其号码。你选一个。然后您检查票号是否符合 10 美元的资格。如果没有,您检查同一张彩票是否可以赢得 50 美元的奖金。实际上只涉及一个随机动作。

(我在 Javascript 中使用了从零开始的随机数函数,而不是 PHP 的mt_rand,但我认为解决方案很明确。)