Generate random red envelope amount algorithm php version, red envelope php
I recently studied the function of sending red packets, so I wrote a red packet generation algorithm.
Requirements for red packet generation algorithms
Whether to generate all red packets in advance or randomly generate a red packet in one request
To put it simply, it refers to the process of decomposing a large integer m (directly "into units, for example, 1 yuan or 100) into n small integers. The range of small integers is [min, max].
The simplest idea is to protect the bottom. Each small red packet must have min, and then each request generates a random integer ranging from 0 to (max-min, plus min is the amount of money in red packets.
This algorithm is simple, but there is a drawback: The final red packets may be generated in minutes. That is to say, the last red packet may be 0.01 yuan.
Another method is to generate all the red packets in advance, which makes it easier to control. I chose to generate all red packets in advance.
Ideal red packet generation algorithm
The ideal red packet generation result is that there are more red packets near the average value, and the number of red packets and small red packets is relatively small.
As you can imagine, the distribution of the number of red packets generated is a bit like a normal distribution.
So how can we meet the requirements of a large number of values near the average line?
It is to find an algorithm that can increase the probability near the average. So we can use a "expansion" and "contraction" method to achieve this effect.
Square first, then a random number within the Square range is generated, and then the square is opened, then the probability is no longer average.
Specific algorithm: (set the total number of money, total number, maximum value, minimum value should be reasonable)
Php code
/*** Calculate the square of a number * @ param $ n */function sqr ($ n) {return $ n * $ n ;} /*** generate a random number between min and max, but the probability is not average. The probability increases gradually from min to max. * Square first, then a random number within the square value range is generated, and then the square is opened. This produces an effect of "expansion" and "contraction. */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 packets * @ param $ bonus_count number of red packets * @ param $ bonus_max maximum amount of each small red packet * @ param $ bonus_min the minimum amount of each small red packet * @ return: one-dimensional array that stores the value of each small red packet generated */function getBonus ($ bonus_total, $ bonus_count, $ bonus_max, $ bonus_min) {$ result = array (); $ avera Ge = $ bonus_total/$ bonus_count; $ a = $ average-$ bonus_min; $ B = $ bonus_max-$ bonus_min; // the probability of such random numbers actually changes, the probability of generating a large number is smaller than that of generating a decimal number. // In this way, the value of most red packets is near the average. Red envelopes and small red envelopes are relatively small. $ Range1 = sqr ($ average-$ bonus_min); $ range2 = sqr ($ bonus_max-$ average); for ($ I = 0; $ I <$ bonus_count; $ I ++) {// because the number of small red packets is usually larger than the number of large red packets, because the probability here needs to be changed. // When the random number> average value, a small red packet is generated // when the random number <average value, a large red packet if (rand ($ bonus_min, $ bonus_max)> $ average) is generated) {// deduct money on average online $ temp = $ bonus_min + xRandom ($ bonus_min, $ average); $ result [$ I] = $ temp; $ bonus_total-= $ temp;} else {// Add money on the average online $ temp = $ bonus_max-xRandom ($ average, $ bonus_max ); $ result [$ I] = $ temp; $ bonus_total-= $ temp;} // if there is any balance, add it to the red bag. If not, try the next one. 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, you have to extract it from the generated small red packet. 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 be greater than the average value $ 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_money + = $ value; if (isset ($ arr [$ value]) {$ arr [$ value] + = 1;} else {$ arr [$ value] = 1 ;}// total output amount, check whether it is the same as the set total number. echo $ total_money; // output all random red packet values var_dump ($ result_bonus); // count the number of red packets for each sum, check whether it is close to the normal distribution ksort ($ arr); var_dump ($ arr );
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.