Recently in the study of the function of red envelopes, so wrote a red envelope generation algorithm.
The demand of red envelope generation algorithm
pre-generated all red envelopes or a request randomly generate a red envelope
In simple terms, it is the process of decomposing a large integer m (directly to "divided into units, such as 1 or 100) into n small integers, and the range of small integers is [min, Max]."
The simplest way of thinking, the first guarantee, each small red envelopes guaranteed to have min, and then each request randomly generated a 0 to (max-min) range of integers, plus min is the amount of red envelopes.
Although this algorithm is simple, but there is a disadvantage: the last generation of red envelopes may be the min money. That is to say, maybe the last red envelopes are 0.01 yuan.
Another way is to generate all the red envelopes beforehand, which makes it easier to control. I chose to generate all the red envelopes beforehand.
An ideal algorithm for red envelope generation
the ideal result of red envelopes is the average number of red envelopes nearby, the amount of large red envelopes and small red envelopes is relatively low.
It can be imagined that the distribution of the number of red envelopes is a bit like a normal distribution.
So how to achieve this average line near the value of more requirements?
is to find an algorithm that can increase the probability near the average. Then use a "swell" and "shrink" way to achieve this effect.
Square first, then generate the square range of random number, and then root, then the probability is no longer the average.
Specific algorithm: (set total amount of money, total number, maximum, minimum value should be reasonable)
PHP code
/** * To find a number of the square * @param $n/function Sqr ($n) {return $n * $n;
/** * produces random numbers between Min and Max, but the probability is not average, and the probability of direction from Min to Max increases.
* Square First, then produce a square value of the range of random number, and then the root, which produces a "swelling" and "contraction" effect.
* * Function Xrandom ($bonus _min, $bonus _max) {$sqr = Intval (Sqr ($bonus _max-$bonus _min));
$rand _num = rand (0, ($SQR-1));
Return Intval (sqrt ($rand _num)); /** * * @param $bonus _total total Red envelope * @param $bonus the number of red envelopes * @param $bonus _max The maximum amount of each small red envelope * @param $bon The us_min of each small red envelope * @return The one-dimensional array of values for each small red envelope generated/function Getbonus ($bonus _total, $bonus _count, $bonus _max, $bonus _min
{$result = array ();
$average = $bonus _total/$bonus _count;
$a = $average-$bonus _min;
$b = $bonus _max-$bonus _min;
The probability of such a random number is actually changed, and the probability of producing a large number is less than that of a decimal. This achieves the value of most red envelopes near the average.
Big red Envelopes and small red envelopes are relatively few.
$range 1 = sqr ($average-$bonus _min);
$range 2 = sqr ($bonus _max-$average);
for ($i = 0; $i < $bonus _count $i + +) {//Because the number of small red envelopes is usually more than the number of large red envelopes, because the probability of the exchange here.When the random number > average, then the small red envelopes//when the random number < mean, then produce large red envelopes if (rand ($bonus _min, $bonus _max) > $average) {//Reduce money on average line
$temp = $bonus _min + xrandom ($bonus _min, $average);
$result [$i] = $temp;
$bonus _total-= $temp;
else {///Add money on the average $temp = $bonus _max-xrandom ($average, $bonus _max);
$result [$i] = $temp;
$bonus _total-= $temp;
If there is any money left, try adding it to the small red envelope and try the next one if you don't add it. while ($bonus _total > 0) {for ($i = 0; $i < $bonus _count; $i + +) {if ($bonus _total > 0 &&
$result [$i] < $bonus _max) {$result [$i]++;
$bonus _total--; }///If the money is negative, it has to be taken back from the generated small red envelopes while ($bonus _total < 0) {for ($i = 0; $i < $bonus _count;
$i + +) {if ($bonus _total < 0 && $result [$i] > $bonus _min) {$result [$i]--;
$bonus _total++;
}} return $result;
} $bonus _total = 200; $bonus _coUNT = 100;
$bonus _max = 10;//This algorithm requires that the maximum value set is greater than the average $bonus _min = 1;
$result _bonus = Getbonus ($bonus _total, $bonus _count, $bonus _max, $bonus _min);
$total _money = 0;
$arr = Array ();
foreach ($result _bonus as $key => $value) {$total + = $value;
if (Isset ($arr [$value])) {$arr [$value] + 1;
}else{$arr [$value] = 1;
///Output total amount of money to see if the total set is the same echo $total _money;
Output all random red envelope value var_dump ($result _bonus);
Statistics the number of red envelopes per amount, check whether close to normal distribution Ksort ($arr);
Var_dump ($arr);
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.