Heim >Backend-Entwicklung >PHP-Tutorial >WeChat generiert zufällig einen roten Umschlagbetragsalgorithmus. PHP-Version_php-Beispiel

WeChat generiert zufällig einen roten Umschlagbetragsalgorithmus. PHP-Version_php-Beispiel

WBOY
WBOYOriginal
2016-08-04 08:56:47965Durchsuche

Kürzlich habe ich die Funktion des Versendens roter Umschläge untersucht und daher einen Algorithmus zur Generierung roter Umschläge geschrieben.

Anforderungen für den Algorithmus zur Generierung roter Umschläge
Generieren Sie alle roten Umschläge im Voraus oder generieren Sie zufällig einen roten Umschlag mit einer Anfrage
Vereinfacht ausgedrückt handelt es sich dabei um den Prozess der Zerlegung einer großen ganzen Zahl m (direkt in Einheiten unterteilt, z. B. 1 Yuan ist 100). Der Bereich kleiner ganzer Zahlen beträgt [min, max]. Die einfachste Idee besteht darin, zuerst das Minimum zu garantieren und dann bei jeder Anfrage eine Ganzzahl im Bereich von 0 bis (Max-Min) zu generieren.
Obwohl dieser Algorithmus einfach ist, hat er einen Nachteil: Der letztendlich generierte rote Umschlag kann Min-Geld sein. Mit anderen Worten: Der endgültige rote Umschlag könnte 0,01 Yuan betragen.
Eine andere Möglichkeit besteht darin, alle roten Umschläge im Voraus zu generieren, was einfacher zu steuern ist. Ich habe mich dafür entschieden, alle roten Umschläge im Voraus zu generieren.

Idealer Algorithmus zur Generierung roter Umschläge
Das ideale Ergebnis der Erzeugung roter Umschläge besteht darin, dass es mehr rote Umschläge in der Nähe des Durchschnittswerts gibt und die Anzahl großer roter Umschläge und kleiner roter Umschläge relativ gering ist.
Wie Sie sich vorstellen können, ähnelt die Verteilung der Anzahl der erzeugten roten Umschläge einer Normalverteilung.

Wie kann also diese Anforderung erfüllt werden, mehr Werte in der Nähe der Durchschnittslinie zu haben?
Es geht darum, einen Algorithmus zu finden, der die Wahrscheinlichkeit nahe dem Durchschnittswert verbessern kann. Verwenden Sie dann eine Methode der „Expansion“ und „Kontraktion“, um diesen Effekt zu erzielen.
Zuerst quadrieren, dann Zufallszahlen innerhalb des Quadratbereichs generieren und dann die Quadratwurzel ziehen, dann ist die Wahrscheinlichkeit nicht mehr durchschnittlich.
Spezifischer Algorithmus: (Der Gesamtbetrag, die Gesamtzahl der Personen sowie die festgelegten Höchst- und Mindestwerte müssen angemessen sein)
PHP-Code

/** 
 * 求一个数的平方 
 * @param $n 
 */ 
function sqr($n){ 
  return $n*$n; 
} 
 
/** 
* 生产min和max之间的随机数,但是概率不是平均的,从min到max方向概率逐渐加大。 
* 先平方,然后产生一个平方值范围内的随机数,再开方,这样就产生了一种“膨胀”再“收缩”的效果。 
*/  
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 红包总额 
 * @param $bonus_count 红包个数 
 * @param $bonus_max 每个小红包的最大额 
 * @param $bonus_min 每个小红包的最小额 
 * @return 存放生成的每个小红包的值的一维数组 
 */  
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;  
 
  //  
  //这样的随机数的概率实际改变了,产生大数的可能性要比产生小数的概率要小。  
  //这样就实现了大部分红包的值在平均数附近。大红包和小红包比较少。  
  $range1 = sqr($average - $bonus_min);  
  $range2 = sqr($bonus_max - $average);  
 
  for ($i = 0; $i < $bonus_count; $i++) {  
    //因为小红包的数量通常是要比大红包的数量要多的,因为这里的概率要调换过来。  
    //当随机数>平均值,则产生小红包  
    //当随机数<平均值,则产生大红包  
    if (rand($bonus_min, $bonus_max) > $average) {  
      // 在平均线上减钱  
      $temp = $bonus_min + xRandom($bonus_min, $average);  
      $result[$i] = $temp;  
      $bonus_total -= $temp;  
    } else {  
      // 在平均线上加钱  
      $temp = $bonus_max - xRandom($average, $bonus_max);  
      $result[$i] = $temp;  
      $bonus_total -= $temp;  
    }  
  }  
  // 如果还有余钱,则尝试加到小红包里,如果加不进去,则尝试下一个。  
  while ($bonus_total > 0) {  
    for ($i = 0; $i < $bonus_count; $i++) {  
      if ($bonus_total > 0 && $result[$i] < $bonus_max) {  
        $result[$i]++;  
        $bonus_total--;  
      }  
    }  
  }  
  // 如果钱是负数了,还得从已生成的小红包中抽取回来  
  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;//此算法要求设置的最大值要大于平均值 
$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; 
  } 
   
} 
//输出总钱数,查看是否与设置的总数相同 
echo $total_money; 
//输出所有随机红包值 
var_dump($result_bonus); 
//统计每个钱数的红包数量,检查是否接近正态分布 
ksort($arr); 
var_dump($arr);
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er für das Studium aller hilfreich sein wird. Ich hoffe auch, dass jeder Script House unterstützt.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn