根据划分比例生成随机数。
如想生成10个 1到100直接的随机数,并且平均分配在 1-50 51-100直间各5个随机数,下边的例子仍有瑕疵可继续改进。
/**
* 生成抽奖随机数组
* @param int $num 生成的数量
* @param int $min 最小值
* @param int $max 最大值
* @param int $piecewise 分段参数 数据会根据此值划分区间
* @return array|null
*/
function generate_unique_rand($num = 1, $min = 1, $max = 100, $piecewise = 1)
{
$return_arr = [];
$val = 1;
switch (true){
//no break
case ($max-$min) < $piecewise: //区间值不足以平均拆分
case ($max-$min) < $num: //区间值不足以取到需求总量
case $max < $min: //最大值小于最小值
return [];
break;
default:
}
//每一段数据的区间值
$interval = bcdiv(($max-$min), $piecewise);
//每一段区间生成的随机个数,并向上取整(使得数量平均在前面,并且不会超过最大值)
$segments_num = ceil(bcdiv($num, $piecewise, 2));
//单个区间最大值
$_max = $interval+$min;
//计算区间值
for ($i = 1; $i <= $piecewise; $i++) {
$_min = $min;
//不是第一次循环的时候+1 避免最小值是上一次的最大值
if($i != 1) $_min = $_min+1;
$_arr = [];
//每次生成数量
while (count($_arr) < $segments_num) {
//数量满足跳出循环
if (count($return_arr) >= $num) {
break;
}
$rand_n = mt_rand($_min, $_max);
//用于单次区间值循环排重
$_arr[$rand_n] = $val++;
$return_arr[$rand_n] = $val;
}
$min = $min + $interval;
$_max = $_max + $interval;
}
return array_keys($return_arr);
}