概率随机物品

class randomGenerator {
private:

    struct val {
        unsigned int min;
        unsigned int max;

        val(unsigned int a, unsigned int b) : min(a), max(b) {

        }
    };
    std::map<int, val> data;
    typedef std::map<int, val>::iterator dataIter;
    unsigned int increment;

    inline int get_random_value(int max_range) {
        return (int) (double(max_range)*(rand() / (RAND_MAX + 1.0)));
    }
public:

    explicit randomGenerator(std::map<int, unsigned int> & params) {
        if (params.empty()) {
            return;
        }
        increment = 0;
        std::map<int, unsigned int>::iterator it = params.begin();
        while (it != params.end()) {
            unsigned int first = increment;
            unsigned int second = (increment += it->second);
            data.insert(std::make_pair(it->first, val(first, second)));
            ++it;
        }
    }

    int generate() {
        unsigned int randVal = get_random_value(increment);
        dataIter iter = data.begin();
        while (iter != data.end()) {
            if (iter->second.min <= randVal && randVal < iter->second.max) {
                return iter->first;
            }
            ++iter;
        }
        return 0;
    }
};<pre class="cpp" name="code">#define BALLON_HIGH_ITEM_COUNT 2
#define BALLON_MIDDLE_ITEM_COUNT 18
#define BALLON_LOW_ITEM_COUNT 10
<pre class="cpp" name="code">        int typeArr[3] = {BALLON_HIGH_ITEM_COUNT,BALLON_MIDDLE_ITEM_COUNT,BALLON_LOW_ITEM_COUNT};
        std::map<int, uint32_t> probability;
        probability.insert(std::make_pair((int)BALLON_HIGH_ITEM_TYPE,BALLON_HIGH_ITEM_COUNT));
        probability.insert(std::make_pair((int)BALLON_MIDDLE_ITEM_TYPE,BALLON_MIDDLE_ITEM_COUNT));
        probability.insert(std::make_pair((int)BALLON_LOW_ITEM_TYPE,BALLON_LOW_ITEM_COUNT));

        randomGenerator *randObject = NULL;
        while (true)
        {
                if (randObject == NULL) {
                        randObject = new randomGenerator(probability);
                }
                //randomGenerator randObject(probability);
                uint32_t index = randObject->generate();
                --typeArr[index-1];
                if (typeArr[index-1] == 0) {
                        probability.erase(index);
                        delete randObject;
                        randObject = NULL;
                }
                uint32_t rand = get_random_value(allItemConfigByType[index].size());
                pInfo->ballon[at] = allItemConfigByType[index][rand];
                if (BALLON_HIGH_ITEM_TYPE == index) {
                        DEBUG_LOG("randomGenerator random_index:%d|rand:%d|", index, rand );
                        DEBUG_LOG("randomGenerator allItemConfigByType:%d|", allItemConfigByType[index].size() );
                        SBallonRandomItemInfo pTemp = allItemConfig[pInfo->ballon[at]];
                        if (reward_at == 1 && pInfo->show_reward[0].good_id == pTemp.itemid) {
                                pInfo->ballon[at] = allItemConfigByType[index][(rand+1)%allItemConfigByType[index].size()];
                                pTemp = allItemConfig[pInfo->ballon[at]];
                        }
                        pInfo->show_reward[reward_at].good_id = pTemp.itemid;
                        pInfo->show_reward[reward_at].count= pTemp.count;
                        reward_at++;
                }
                if (++at >=BALLON_COUNT_MAX) {
                        break;
                }
        }
        if (randObject) {
                delete randObject;
        }


 


 

<think> 我们已知在Python中,根据概率随机抽取列表元素是一个常见的需求。根据引用内容,我们可以使用random模块中的choices函数来实现这一点。 具体方法:random.choices(population, weights=None, cum_weights=None, k=1) 其中: population:要抽取的列表 weights:与population长度相同的权重列表(概率列表),表示每个元素被抽中的权重(非负) k:抽取的次数(注意:这个函数可以重复抽取同一个元素,因为是有放回的抽取) 另外,引用[3]中直接给出了示例:number_list = random.choices(list, list_probability, k=number) 因此,我们可以按照以下步骤实现: 1. 导入random模块 2. 准备一个待抽取的列表(population) 3. 准备一个概率列表(weights),注意这个概率列表需要和待抽取列表一一对应,且概率之和不一定为1(因为函数内部会自动归一化) 4. 调用random.choices函数,并指定k的值(即抽取次数) 举例说明: 假设我们有一个列表['A', 'B', 'C'],对应概率为[0.1, 0.3, 0.6],现在要抽取5次(有放回)。 注意:如果我们需要无放回的抽取,则可以考虑使用random.sample,但是random.sample不支持按权重抽取。因此,当需要无放回且按权重抽取时,可能需要使用其他方法(例如使用numpy.random.choice,并设置replace=False,但注意numpy的weights参数需要归一化,且无放回时权重的意义会发生变化,因为每次抽取后剩余元素的权重会重新归一化)。不过根据引用,用户似乎只需要按概率抽取(有放回)即可。 因此,我们先给出有放回抽取的代码。 另外,引用[2]提到了random.choice,但它只能等概率随机抽取一个元素,无法指定权重。 所以,我们使用choices方法。 下面给出示例代码: </think> 在Python中,依据概率随机抽取列表元素,推荐使用`random.choices()`函数实现。以下是详细方法和示例代码: ### 📊 方法说明 ```python import random # 语法 sampled_list = random.choices( population=元素列表, weights=概率列表, # 或 cum_weights=累积概率 k=抽取次数 ) ``` - **population**:待抽取的原始列表 - **weights**:每个元素对应概率(长度需与`population`一致) - **k**:抽取的元素数量(可重复抽取) - **函数特性**:自动对概率进行归一化处理(无需概率总和为1) ### ⚙️ 使用示例 ```python import random # 定义水果列表和对应概率 fruits = ["🍎苹果", "🍌香蕉", "🍊橙子", "🍇葡萄"] prob = [0.1, 0.3, 0.4, 0.2] # 概率总和≠1也可 # 按概率抽取3次(可能重复) result = random.choices(fruits, weights=prob, k=3) print("抽取结果:", result) ``` **输出示例**: ``` 抽取结果: ['🍌香蕉', '🍊橙子', '🍊橙子'] # 橙子概率最高,出现频率更高 ``` ### 💡 关键说明 1. **权重归一化** 即使概率总和不为1,系统会自动按比例转换: $$ P_{\text{归一化}}(i) = \frac{\text{weights}[i]}{\sum \text{weights}} $$ 例如权重`[1, 2, 3]`会被转换为`[1/6, 1/3, 1/2]` 2. **无放回抽取替代方案** 若需不重复抽取,可结合`random.sample()`与权重预处理: ```python # 通过概率生成临时列表再抽样 weighted_list = [] for item, p in zip(fruits, prob): weighted_list.extend([item] * int(p * 100)) # 概率放大100倍生成元素池 result = random.sample(weighted_list, k=2) # 无放回抽2次 ``` ### 🌰 应用场景 - 抽奖系统(不同奖品概率不同) - 数据增强(按概率选择样本变换方式) - 游戏道具掉落(稀有物品概率) > 提示:需要精确概率控制时(如科学计算),建议使用`numpy.random.choice(a, p=prob)`,但需确保概率总和严格为1[^1][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值