转盘抽奖权重算法用累积整数数组实现:将概率转为整数(如万分比),构建累加边界数组,生成随机数后线性查找首个大于等于该数的索引即中奖项,逻辑清晰、无浮点误差、易维护。
用数组实现转盘抽奖权重算法,核心是把概率转化为可比对的整数区间,再通过一次随机数落点定位中奖项。不依赖复杂库,逻辑透明、易调试、适配各种后端语言。
构建累积权重数组,明确每个奖品的“命中范围”
把各档奖品的概率统一换算为整数(如万分比、百分比取整),然后从前到后累加,生成一个“上限边界数组”。这个数组每个元素代表截止该项的累计权重值。
- 例如奖品配置为:一等奖 0.5%、二等奖 3%、三等奖 15%、安慰奖 81.5%,统一放大 1000 倍得整数权重 [5, 30, 150, 815]
- 累积数组为 [5, 35, 185, 1000] —— 表示一等奖占 0~4,二等奖占 5~34,三等奖占 35~184,安慰奖占 185~999
- 生成 [0, 1000) 的随机整数,逐项比对是否小于当前累积值,第一个满足的即为中奖项
用 for 循环做线性查找,兼顾清晰与兼容性
对中小规模奖品(≤50项),直接用 for 遍历累积数组判断,代码简短、逻辑一目了然,且无需额外排序或预处理。
- Java 示例中用 int[] weightUpperBounds = {5, 35, 185, 1000} 存上限,配合 rand.nextInt(1000) 生成随机数
- 循环中用 if (roll 判断落点,匹配即 break,避免多余计算
- 这种写法天然支持动态增减奖品:只改数组内容,不改控制逻辑;也兼容 Java 6+ 等老环境
按业务需求选择权重单位,规避浮点误差
数据库和代码中一律使用整数表达概率,彻底避开浮点运算的精度丢失问题。
- 推荐用“万分比”(总和为 10000)或“千分比”(总和为 1000),既保留小概率精度,又便于人工核对
- 切勿在数据库字段存 0.005 这类 float/double;也不要用 Math.random() * 100 后四舍五入,会引入统计偏差
- 后端校验时,可强制要求所有权重整数之和等于约定基数(如 10000),不满足则拒绝加载该批次配置
高并发场景下补充事务与幂等保障
数组映射只解决“抽什么”,不解决“能不能抽”和“抽完怎么记”。真实项目必须叠加业务防护。
- 中奖判定后,需在数据库事务中完成三件事:扣减对应奖品库存、插入用户中奖记录、更新用户本次抽奖状态
- 关键操作如 UPDATE prize SET stock = stock - 1 WHERE id = ? AND stock > 0 必须带 stock > 0 条件,防止超发
- 接口需校验用户唯一请求 ID 或签名,防重放、防刷;高频抽奖建议用 Redis + Lua 做原子限频










