There is a bad algorithm on the Internet, please see the link for details
The general principle is:
1, generate a random number;
2, circularly compare the probability of the Nth prize;
3, determine the prize;
If you follow this algorithm, subjectively the prize is drawn once, but objectively, each prize is drawn once in a cycle. In fact, it is drawn N times. I don’t know if my understanding is correct.
The following is the algorithm I wrote. The specific principles are:
1. First determine the range of random numbers (lucky numbers);
2. Determine the number range for each prize to ensure that only one draw can correspond to a certain prize;
3. Generate a lucky number based on the range;
4. Determine the prize based on the range;
Please ask the experts, do you have any better algorithms or ideas?
<code>$goods = [ 0 => [ 'id' => 1, 'name' => '苹果电脑', 'odds' => '0.01' //概率 ], 1 => [ 'id' => 2, 'name' => 'Iphone', 'odds' => '10.99' ], 2 => [ 'id' => 3, 'name' => '200元红包', 'odds' => '19' ], 3 => [ 'id' => 4, 'name' => '安慰奖', 'odds' => '30' ], 4 => [ 'id' => 5, 'name' => '什么都没抽到', 'odds' => '40' ], ]; $baseOdds = 100; //抽奖概率基数,默认100% $maxBase = 1; //抽奖概率基数倍数,默认1,如果奖品概率有小数位,该倍数为10的小数位数平方,具体看下面 foreach ($goods as $good) { $decimal = strpbrk($good['odds'], '.'); //获取小数点后面的内容 if ($decimal !== false) { $decimalCount = strlen($decimal) - 1;//获取小数点后面的位数 $newMaxBase = pow(10, $decimalCount); //例如概率如果是0.01,则全局的抽奖概率基数需要以10的平方倍数上涨 if ($newMaxBase > $maxBase) { $maxBase = $newMaxBase; //更新基数倍数 } } } $baseOdds = $maxBase ? $baseOdds * $maxBase : $baseOdds; //更新概率基数 $start = 1; $end = 0; $luckyCompare = $tickets = []; //为每个奖品生成一个幸运数区间 foreach ($goods as $key => $good) { $newOdds = $good['odds'] * $maxBase; $end = $end + $newOdds; $luckyCompare[$good['id']] = [$start, $end]; $tick = mt_rand($start, $end); $start = $start + $newOdds; $tickets[$good['id']] = $tick; } $luckyNumber = mt_rand(1, $baseOdds); var_dump($luckyNumber); var_dump($luckyCompare); foreach ($luckyCompare as $goodId => $compare) { if ($compare[0] <= $luckyNumber && $compare[1] >= $luckyNumber) { $luckyGood = $goodId; //最终的奖品 break; } } var_dump($luckyGood);</code>
There is a bad algorithm on the Internet, please see the link for details
The general principle is:
1, generate a random number;
2, circularly compare the probability of the Nth prize;
3, determine the prize;
If you follow this algorithm, subjectively you draw one prize, but objectively, each prize is drawn once in a cycle. In fact, it is drawn N times. I don’t know if my understanding is correct.
The following is the algorithm I wrote. The specific principles are:
1. First determine the range of random numbers (lucky numbers);
2. Determine the number range for each prize to ensure that only one draw can correspond to a certain prize;
3. Generate a lucky number based on the range;
4. Determine the prize based on the range;
Please ask the experts, do you have any better algorithms or ideas?
<code>$goods = [ 0 => [ 'id' => 1, 'name' => '苹果电脑', 'odds' => '0.01' //概率 ], 1 => [ 'id' => 2, 'name' => 'Iphone', 'odds' => '10.99' ], 2 => [ 'id' => 3, 'name' => '200元红包', 'odds' => '19' ], 3 => [ 'id' => 4, 'name' => '安慰奖', 'odds' => '30' ], 4 => [ 'id' => 5, 'name' => '什么都没抽到', 'odds' => '40' ], ]; $baseOdds = 100; //抽奖概率基数,默认100% $maxBase = 1; //抽奖概率基数倍数,默认1,如果奖品概率有小数位,该倍数为10的小数位数平方,具体看下面 foreach ($goods as $good) { $decimal = strpbrk($good['odds'], '.'); //获取小数点后面的内容 if ($decimal !== false) { $decimalCount = strlen($decimal) - 1;//获取小数点后面的位数 $newMaxBase = pow(10, $decimalCount); //例如概率如果是0.01,则全局的抽奖概率基数需要以10的平方倍数上涨 if ($newMaxBase > $maxBase) { $maxBase = $newMaxBase; //更新基数倍数 } } } $baseOdds = $maxBase ? $baseOdds * $maxBase : $baseOdds; //更新概率基数 $start = 1; $end = 0; $luckyCompare = $tickets = []; //为每个奖品生成一个幸运数区间 foreach ($goods as $key => $good) { $newOdds = $good['odds'] * $maxBase; $end = $end + $newOdds; $luckyCompare[$good['id']] = [$start, $end]; $tick = mt_rand($start, $end); $start = $start + $newOdds; $tickets[$good['id']] = $tick; } $luckyNumber = mt_rand(1, $baseOdds); var_dump($luckyNumber); var_dump($luckyCompare); foreach ($luckyCompare as $goodId => $compare) { if ($compare[0] <= $luckyNumber && $compare[1] >= $luckyNumber) { $luckyGood = $goodId; //最终的奖品 break; } } var_dump($luckyGood);</code>
All I can say is hehe. The decision-making power of the lottery algorithm does not lie with the programmer, that is the point.
Usually lottery activities are initiated, planned, evaluated, and operated by the marketing department, and the role of programmers is only to implement them. The marketing action plan should include prize settings, event duration, promotion strategy, cold/hot time, prize distribution batches, etc. To put it simply, this is a scene directed by the marketing department, and the developer is the on-site conductor. The program is responsible for scheduling, and the lottery winner is the actor.
So, the lottery algorithm is useless. As long as the prizes you give out do not exceed the prize pool, nothing else matters.
Some people may say, how can we reflect the fairness and justice of the lottery? In fact, there is almost no need to consider this issue, because the program is automatically executed after it is written. At this time, it is an equal environment for all participants, and there is no unfair problem.
Typical pseudo-algorithms are as follows:
Rain and Dew Award: 5 yuan consumption discount coupons, winning rate 100%;
Puddle Award: 10 yuan consumption discount coupons, winning rate 50%;
Ben Lei Award: 100 consumption discount coupons Yuan, winning rate is 5%;
Thunderbolt Prize: One iPad, 6 in total.
The activity time is 12 hours, and there is no upper limit for lottery tickets.
Algorithm: The microsecond part of the lottery timestamp is a multiple of 20 = thunder, and it is an odd number = puddle, otherwise it is rain and dew. Every two hours is a cycle, and the first lottery winner at the beginning of the next cycle will win the lightning prize of the previous cycle. The entire event will be completely over when the first lottery ticket is received after the duration expires.
Are there any unfair questions? So, hehe. In the end, you still have to write programs according to your needs.
<code>$arr = array(10000,1000,100,10,1); for ($i=0;$i<5;$i++){ if(rand(1,$arr[$i])==1){ echo "恭喜你中了".$i."奖";//这个描述自己写 } }</code>