如何基于自定义distribution函数创建指定分布的随机数生成函数
自定义分布随机数生成器的优化方案
你的核心需求是根据给定的distribution(x)函数生成随机值,让y值越高的x出现概率越大,现有方案的问题出在固定阈值筛选逻辑和低效的样本生成方式上,以下是更可靠的实现思路和代码:
现有代码的问题
- 用固定的
e值做筛选,没有把每个x对应的y值(概率密度)纳入判断,完全无法准确拟合目标分布 - 每次生成100个样本再排序筛选,不仅效率低,还可能因为运气差陷入无限循环
- 没必要依赖d3的
range方法,纯JS就能完成核心逻辑
推荐方案:接受-拒绝采样(Accept-Reject Sampling)
这是生成自定义分布随机数的标准方法,逻辑完全贴合你的需求,不需要手动调阈值:
- 先确定
distribution(x)在x∈[0,1]范围内的最大值M(确保M大于等于所有x对应的y值) - 生成一个随机x(范围[0,1])
- 生成一个随机u(范围[0,M])
- 如果
u ≤ distribution(x),就返回这个x;否则重复步骤2-4
实现代码
// 先实现一个工具函数,获取distribution的最大值M function getDistributionMax(fn, sampleCount = 1000) { let maxY = 0; for (let i = 0; i < sampleCount; i++) { const x = Math.random(); const y = fn(x); if (y > maxY) maxY = y; } // 留一点余量避免漏判 return maxY * 1.05; } // 最终的distributor函数 function distributor(fn) { const M = getDistributionMax(fn); while (true) { const x = Math.random(); const y = fn(x); const u = Math.random() * M; if (u <= y) { return x; } } }
说明
getDistributionMax通过采样1000个x值找到分布的近似最大值,乘以1.05是为了避免因为采样不够漏过真实最大值- 循环里的逻辑完全基于每个x对应的y值判断:y值越高,
u ≤ y的概率越大,x被选中的概率就越高,完美贴合你的需求 - 不需要再手动调
e参数,所有逻辑都由目标分布本身决定
额外优化建议
如果你的distribution(x)有已知的理论最大值(比如你通过图形编辑器能直接看到峰值),可以直接把M设为这个值,省去采样找最大值的步骤,效率更高。
内容的提问来源于stack exchange,提问作者pernifloss
相关产品推荐
相关产品推荐

