1. 程式人生 > 其它 >微信隨機紅包演算法

微信隨機紅包演算法

  /*
  * 平分紅包
  * $sum_money 紅包總金額
  * $num 紅包個數
  */
  function randBonus($sum_money = 100, $num = 10){
    $list = []; // 將要瓜分的結果
    $bonus_balance = $sum_money; // 每次分完之後的餘額
    $bonus_avg = number_format($sum_money / $num, 2); // 平均每個紅包多少錢
    $i = 0;
    while($i < $num){
      if($i < $num-1){
        $rand = $bonus_avg; // 根據紅包型別計算當前紅包的金額
        $list[] = $rand;
        $bonus_balance -= $rand;
      }else{
        $list[] = $bonus_balance; // 最後一個紅包直接承包最後所有的金額,保證發出的總金額正確
      }
      $i++;
    }
    return $list;
  }

  /*
  * 微信隨機紅包模擬演算法
  * $sum_money 紅包總金額
  * $num 紅包個數
  * $min_money 紅包最小值
  */
  function lottery($sum_money = 100, $num = 10, $min_money = 0.01)
  {
    if ($sum_money < $num * $min_money) {
      return '紅包金額不足夠瓜分';
    }
    $list = [];
    for ($i = 1; $i <= $num; $i++) {
      // 剩餘的可分配金額,需要確保剩下的人每人都至少可以拿到保底的錢
      $remain = $sum_money - array_sum($list) - ($num - $i + 1) * $min_money;
      if ($i < $num) {  // 前面的人隨機獲得
        // 每輪抽取的金額範圍:0 至 剩餘金額平均值的兩倍
        $get = $this -> random_float(0, $remain / ($num - $i + 1) * 2);
      } else {  // 最後一個人拿全部剩下的
        $get = $remain;
      }
      // 最後再將每個人保底的錢加上
      $list[] = round(round($get, 2) + $min_money, 2);
    }

    // 校驗紅包金額是否有為0或負數,
    foreach ($list as $item) {
      if ($item <= 0.01) {
        $this-> randBonus($sum_money , $num, $min_money);
      }
    }

    // 校驗總金額是否正確
    $array_sum = array_sum($list);
    if ($sum_money != $array_sum) {
      $this-> randBonus($sum_money , $num, $min_money);
    }
    return $list;
  }
  // 產生一個隨機浮點數
  function random_float($min = 0, $max = 1)
  {
    return round($min + mt_rand() / mt_getrandmax() * ($max - $min), 2);
  }