兄弟们写了个取当前出现未达到占比且相差最大的类型的算法,但感觉不是很好
$category_ids = [1,2,3];
$categories_ratio = [3, 6, 1];
$categories_count = [4, 12, 3];
$all_zero = true;
$is_surpass = false;
$categories_zero_count = array();
// 检查出现次数是否有0
foreach ($categories_count as $key => $value) {
if($value == 0){
$categories_zero_count[$key] = $categories_ratio[$key];
}
}
if(!empty($categories_zero_count)){
$max_ratio = max($categories_zero_count);
$max_ratio_key = array_keys($categories_zero_count, $max_ratio)[0];
return $category_ids[$max_ratio_key];
}
// 计算每个元素的期望值
$ratio_expected = array();
foreach ($categories_ratio as $key => $value) {
$ratio_expected[$key] = $value * $categories_count[0];
}
$count_expected = array();
foreach ($categories_count as $key => $value) {
$count_expected[$key] = $value * $categories_ratio[0];
}
// 计算每个元素的误差
$ratio_error = array();
$low_ratio = array();
foreach ($ratio_expected as $key=> $value)
{
$ratio_error[$key] = $value - $count_expected[$key];
if($ratio_error[$key] != 0){
$all_zero = false;
}
$low_ratio[$key] = floor($ratio_error[$key]*100/$value);
if($low_ratio[$key] > 0){
// 存在超出
$is_surpass = true;
}
}
// 相差全为0,取占比最大的
if($all_zero){
$max_ratio = max($categories_ratio);
$max_ratio_key = array_keys($categories_ratio, $max_ratio)[0];
return $category_ids[$max_ratio_key];
}
// 比较,获取应该不足的
if(!empty($low_ratio)){
// 存在超出
if($is_surpass){
$max_error = max($low_ratio);
$max_error_key = array_keys($low_ratio, $max_error)[0];
return $category_ids[$max_error_key];
}else{
// 不存在超出取首个 如0,-12,-123
return $category_ids[0];
}
}
return array_rand( $category_ids );
$category_ids是分类id
$categories_ratio是对应分类的占比
$categories_count是对应分类出现的次数
理论上就是需要计算出当前出现的次数是否符合占比,选出没有达到占比的分类id,比如都没出现时,id 1出现了1次(正常应该是id2,它占比高),那么id1出现次数就为1: 0:0了,根据比例3, 6, 1,先去判断如果有出现次数为0的,按最大占比的返回,否则算首个相乘求出期望值和实际值,还没优化和严格验证,就先跑了几个测试,感觉是不是写的麻烦了,算法不好
需求如下:分类会有多种,每种分类都有对应的占比,比如ABC三类对应为2:4:6,每种分类出现过的次数会有记录,比如A,B,C各出现过2,4,6次那么认为当前是平衡状态,下一次预计出现的分类则为B类,因为平衡状态下,B类占比最大。当然一开始肯定不是平衡的,所以需要计算当前各类出现过的次数,根据占比返回每次应该出现的分类
本作品采用《CC 协议》,转载必须注明作者和本文链接
你先说清楚你的需求, 我们才好判断写的到底好不好。
感觉是你想的复杂了
C就是1
3 就是1A2B3C累计6个 打乱扔到缓冲里一个一个取 没有再在按照比例往里面扔
其实直接加权重随机即可,只要数据大这个数就是平均,你不能一组两组数据看。
还有一种每次按照最小单位制比如你的ABC三类对应位2:4:6 就是A