min = $data['min']; $this->max = $data['max']; $this->num = $data['num']; $this->total = $data['total']; } /** * Execute the job. * * @return void */ public function handle() { $min = $this->min; $max = $this->max; $num = $this->num; $total = $this->total; if ($max) { $packet_arr = $this->rand_section($min, $max, $num, $total); }else{ $packet_arr = $this->demo($total, $num, $min); } ParticipantRedPacket::insert($packet_arr); } public function rand_section($min,$max,$num,$total){ $data = array(); if ($min * $num > $total) { return array(); } if($max*$num < $total){ return array(); } while ($num >= 1) { $num--; $kmix = max($min, $total - $num * $max); $kmax = min($max, $total - $num * $min); $kAvg = $total / ($num + 1); //获取最大值和最小值的距离之间的最小值 $kDis = min($kAvg - $kmix, $kmax - $kAvg); //获取0到1之间的随机数与距离最小值相乘得出浮动区间,这使得浮动区间不会超出范围 $r = ((float)(rand(1, 10000) / 10000) - 0.5) * $kDis * 2; $k = sprintf("%.2f", $kAvg + $r); $total -= $k; // $data[] = $k; $arr = []; $arr['price'] = $k; $arr['created_at']=date('Y-m-d H:i:s'); $arr['updated_at']=date('Y-m-d H:i:s'); $data[] = $arr; } return $data; } function demo($total, $num, $min = 0.01) { $overPlus = $total - $num * $min; // 剩余待发钱数 $base = 0; // 总基数 // 存放所有人数据 $container = array(); // 每个人保底 for ($i = 0; $i < $num; $i++) { // 计算比重 $weight = round(lcg_value() * 1000); $container[$i]['weight'] = $weight; // 权重 $container[$i]['money'] = $min; // 最小值都塞进去 $base += $weight; // 总基数 } $len = $num - 1; // 下面要计算总人数-1的数据, for ($i = 0; $i < $len; $i++) { $money = floor($container[$i]['weight'] / $base * $overPlus * 100) / 100; // 向下取整,否则会超出 $container[$i]['money'] += $money; } // 弹出最后一个元素 array_pop($container); $result = array_column($container, 'money'); $last_one = round($total - array_sum($result), 2); array_push($result, $last_one); $data = []; foreach ($result as $res) { $arr = []; $arr['price'] = $res; $arr['created_at']=date('Y-m-d H:i:s'); $arr['updated_at']=date('Y-m-d H:i:s'); $data[] = $arr; } return $data; } }