我想进行自定义彩票提取,以激励用户参与在线实验.规则是:
彩票是一个PHP函数,它被调用一次并返回奖品(0,10,50或500).我创建了下面的函数,经过70 000次试验后,统计数据是:
我应该担心这个算法吗?有没有比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美元(你得到钻孔).
使用您的特定代码,真实概率的计算如上所述.
请参阅已接受答案中的代码,以获得具有准确概率的正确代码.
在给定的概率下,您有四种结果:
第四个结果——没有获胜——是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
,但我认为解决方案很明确。)