verjas - 1 year ago 70
PHP Question

Lottery algorithm - PHP - math seems good, but is the function valid?

I want to make a custom lottery extraction to motivate users to participate in an online experiment. The rules are:

• 10% to get 10\$

• 1% chance to get 50\$

• 0.1% chance to get 500\$

The lottery is a PHP function that gets called once and returns the prize (0, 10, 50 or 500). I created the function below, and after 70 000 trials the statistics are:

• 9.11% for 10\$

• .91% for 50\$

• .01% for 500\$

Should I be worried about the algorithm? Is there a better way to create a good distribution of chances than 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;
}
``````

Thank you for helping a newbie!

You have four outcomes with given probabilities:

• 0.1% probability to win \$500.
• 1% probability to win \$500.
• 10% probability to win \$500.

The fourth outcome - no win - is 100% minus the sum of the other three outcomes, namely 88.9%.

Mark Gabriel has explained why your initial code was off: By promoting 10% of the people who have won \$10 to \$50 winners, you take them away from the pool of \$10 winner, which will be only 9% of all people.

Pham Trung has contributed a solution that takes the winners of higher amounts from the pool of non-winners so far and adjusts the probabilities. That's a workable solution, but the easiest solution is in my opintion to call the random number generator just once.

This solution also reflects the ticket analogy best: You place 10,000 tickets in a box. The 1,000 tickets from 1 to 1000 win \$10. The 100 tickets from 1001 to 1100 win \$50. The ten tickets from 1101 to 1110 win \$500. All 8890 tickets from 1111 on don't win anything:

``````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;
}
``````

In this code, the tickets have only their number written on them. You pick one. Then you check whether the ticket number is eligible for \$10. If not, you check the same ticket whether it may bet a \$50 win. There is really just one random action involved.

(I've used a zero-based random-number function in Javascript instead of PHP's `mt_rand`, but I think the solution is clear.)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download