关于以n/m概率返回true的随机算法合理性的技术问询
实现精确n/m概率返回结果的方法分析
需求与现有实现
我需要实现一个方法,使其以n/m的概率返回true,剩余概率返回false。比如要达成7/10000的概率返回true。
我原本计划通过getRandomIntUnderN函数生成小于10000的随机整数,判断该整数是否小于8(即7+1)时返回true,但实际代码中判断的是整数是否小于7,代码如下:
// 生成包含0但不包含n的随机整数 const getRandomIntUnderN = (n) => { const rn = Math.random() * n return Math.trunc(rn) } // 以n/m的概率返回true const goAtChance = (n, m) => { return getRandomIntUnderN(m) < n } // 测试7/10000概率返回true console.log(goAtChance(7, 10000))
核心问题
仅通过判断随机整数是否小于指定数值的方式,能否得到符合预期的精确概率?
我有两种矛盾的观点:
- 观点1:1-7在1-10000范围内分布不够离散,会导致返回
true的概率存在偏差; - 观点2:如果
getRandomIntUnderN能生成纯随机数,选择任意7个小于10000的数作为判断条件都不影响概率,比如[0,1,2,3,4,5,6](对应代码中的<7)。
结论
观点2是正确的。
只要getRandomIntUnderN能等概率生成0到m-1之间的每个整数(也就是纯随机、无偏差的均匀分布),那么:
- 总共有m个可能的整数结果,每个结果出现的概率都是
1/m; - 选择其中任意n个不同的整数作为触发
true的条件,总概率就是n*(1/m) = n/m,完全符合预期; - 代码中判断
<n,本质就是选择了0,1,...,n-1这n个连续整数,和选择任意n个离散整数的概率完全一致,不存在分布离散性导致的偏差。
需要注意的是,前提是getRandomIntUnderN的实现是无偏差的。当前代码中Math.random()本身是伪随机数,但在工程场景下的均匀性足够满足需求;Math.trunc(Math.random()*m)也能正确生成0到m-1的整数,每个数的概率近似相等。
内容的提问来源于stack exchange,提问作者zzzgoo
相关产品推荐
相关产品推荐

