如何在Lua中实现带权重偏置的小数随机数生成器 避免大量if语句
Lua 带偏随机数生成器实现方案
核心思路
避免大量if判断的核心是预生成权重查找表+前缀和匹配,所有概率规则都提前写到结构化配置中,运行时直接查表返回结果,不需要动态做区间判断。
完整实现代码
步骤1:定义区间概率配置
按照题目要求的优先级分配区间总占比,1.0-2.0区间直接使用题目给定的单值权重:
-- 区间配置:优先级从高到低排列,总概率加和为100% local interval_config = { -- 优先级最高:2.0-4.0区间,总占比40% {min = 2.0, max = 4.0, total_p = 40, step = 0.1, inner_growth = 0.08}, -- 优先级第二:1.0-2.0区间,总占比10%,直接用题目给定的单值权重 {min = 1.0, max = 2.0, total_p = 10, step = 0.1, custom_weights = {1, 1.1, 1.5, 1.7, 2.0, 2.2, 2.5, 2.7, 3.0, 3.3}}, -- 优先级第三:4.0-5.0区间,总占比15% {min = 4.0, max = 5.0, total_p = 15, step = 0.1, inner_growth = 0.05}, -- 优先级第四:5.0-6.0区间,总占比12% {min = 5.0, max = 6.0, total_p = 12, step = 0.1, inner_growth = 0.04}, -- 优先级第五:6.0-7.0区间,总占比8% {min = 6.0, max = 7.0, total_p = 8, step = 0.1, inner_growth = 0.03}, -- 优先级第六:7.0-8.0区间,总占比6% {min = 7.0, max = 8.0, total_p = 6, step = 0.1, inner_growth = 0.025}, -- 优先级第七:8.0-9.0区间,总占比5% {min = 8.0, max = 9.0, total_p = 5, step = 0.1, inner_growth = 0.02}, -- 优先级第八:9.0-10.0区间,总占比4% {min = 9.0, max = 10.1, total_p = 4, step = 0.1, inner_growth = 0.015}, }
步骤2:预构建前缀和查找表
程序启动时一次性生成查找表,不需要每次随机都计算:
local function build_lookup_table() local lookup = {} local current_sum = 0 for _, conf in ipairs(interval_config) do local val = conf.min local idx = 1 while val < conf.max do local p if conf.custom_weights then p = conf.custom_weights[idx] else -- 区间内权重按递增规则生成,总权重归一到区间总占比 local base_p = conf.total_p / ((conf.max - conf.min) / conf.step) p = base_p + (idx - 1) * conf.inner_growth end current_sum = current_sum + p table.insert(lookup, {max_p = current_sum, value = val}) val = val + conf.step idx = idx + 1 end end -- 归一化到100%,消除配置误差 local scale = 100 / current_sum for _, item in ipairs(lookup) do item.max_p = item.max_p * scale end return lookup end local lookup_table = build_lookup_table()
步骤3:实现随机抽取函数
全程无if判断区间,直接匹配前缀和即可:
local function biased_random() local r = math.random() * 100 -- 生成0-100的随机浮点数 for _, item in ipairs(lookup_table) do if r <= item.max_p then return item.value end end return lookup_table[#lookup_table].value -- 兜底返回最大值 end
测试示例
-- 初始化随机种子 math.randomseed(os.time()) -- 测试1000次抽取,验证概率分布 local count = {} for i=1,1000 do local v = biased_random() count[v] = (count[v] or 0) + 1 end -- 输出各值出现概率 for v, c in pairs(count) do print(string.format("%.1f 出现概率: %.2f%%", v, c/10)) end
调整说明
如果需要修改概率规则,只需要调整interval_config中的配置即可,不需要修改核心逻辑:
- 调整
total_p可以修改对应区间的总抽取概率 - 调整
inner_growth可以修改区间内数值的权重递增幅度 - 新增
custom_weights可以给任意区间自定义单值权重
内容的提问来源于stack exchange,提问作者SaviorNoGame
相关产品推荐
相关产品推荐

