>백엔드 개발 >PHP 튜토리얼 >PHP 난수 WeChat은 빨간 봉투 금액 알고리즘을 무작위로 생성합니다. PHP 버전

PHP 난수 WeChat은 빨간 봉투 금액 알고리즘을 무작위로 생성합니다. PHP 버전

WBOY
WBOY원래의
2016-07-27 16:56:221612검색

최근에 빨간 봉투 보내기 기능을 연구하다가 빨간 봉투 생성 알고리즘을 작성했습니다.

빨간 봉투 생성 알고리즘 요구 사항
빨간 봉투를 모두 미리 생성하거나 요청에 따라 무작위로 빨간색 봉투를 생성
간단히 말하면 큰 정수 m( 1위안은 100과 같이 단위로 직접 나누는 것은 작은 정수의 범위는 [최소, 최대]로 분해되는 과정이며, 각각의 작은 빨간 봉투는 min이 보장되고 각 요청마다 0에서 (max-min) 사이의 정수가 무작위로 생성되며 min은 빨간색 봉투의 양입니다.
이 알고리즘은 간단하지만 단점이 있습니다. 최종 생성된 빨간 봉투는 최소 금액일 수 있습니다. 즉, 최종 빨간 봉투는 0.01위안일 수 있습니다.
또 다른 방법은 모든 빨간 봉투를 미리 생성하는 것인데, 저는 모든 빨간색을 생성하는 것을 선택합니다. 🎜>이상적인 빨간 봉투 생성 알고리즘
이상적인 빨간 봉투 생성 결과는 평균에 가까운 빨간 봉투가 많고, 큰 빨간 봉투와 작은 빨간 봉투의 수가 상대적으로 적다는 것입니다. 상상할 수 있듯이, 생성된 빨간 봉투 수의 분포는 상태 분포와 다소 비슷합니다.

그러면 평균에 가까운 더 많은 값을 갖는 요구 사항을 어떻게 달성할 수 있을까요? 평균에 가까운 확률을 높일 수 있는 알고리즘을 찾아보세요. 그런 다음 일종의 "축소" 방법을 사용하여 이 효과를 얻으세요.

첫 번째 정사각형을 만든 다음 정사각형 범위 내에서 난수를 생성하세요. 제곱근을 취하면 확률은 더 이상 평균이 아닙니다.
총 금액, 총 인원수, 최대값과 최소값이 합리적이어야 합니다.)
PHP 코드




위 내용은 모든 분들의 공부에 도움이 되길 바랍니다
.

위 내용은 PHP 난수 콘텐츠를 포함하여 빨간 봉투 금액을 무작위로 생성하는 WeChat용 PHP 난수 알고리즘의 PHP 버전을 소개합니다. PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.

/** 
 * 求一个数的平方 
 * @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);
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.