兄弟们写了个取当前出现未达到占比且相差最大的类型的算法,但感觉不是很好

        $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的,按最大占比的返回,否则算首个相乘求出期望值和实际值,还没优化和严格验证,就先跑了几个测试,感觉是不是写的麻烦了,算法不好:sob:

需求如下:分类会有多种,每种分类都有对应的占比,比如ABC三类对应为2:4:6,每种分类出现过的次数会有记录,比如A,B,C各出现过2,4,6次那么认为当前是平衡状态,下一次预计出现的分类则为B类,因为平衡状态下,B类占比最大。当然一开始肯定不是平衡的,所以需要计算当前各类出现过的次数,根据占比返回每次应该出现的分类

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 10

你先说清楚你的需求, 我们才好判断写的到底好不好。

5个月前 评论
伽蓝幻梦 (楼主) 5个月前
keyboby 5个月前
徵羽宫 (作者) 5个月前
徵羽宫 (作者) 5个月前
徵羽宫 (作者) 5个月前
徵羽宫 (作者) 5个月前
伽蓝幻梦 (楼主) 5个月前

感觉是你想的复杂了
其实直接加权重随机即可,只要数据大这个数就是平均,你不能一组两组数据看。
还有一种每次按照最小单位制比如你的ABC三类对应位2:4:6 就是A:B:C就是1:2:3 就是1A2B3C累计6个 打乱扔到缓冲里一个一个取 没有再在按照比例往里面扔

5个月前 评论
伽蓝幻梦 (楼主) 5个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!