生成具有对数分布和自定义斜率的随机数

时间:2015-06-08 22:24:01

标签: javascript algorithm math statistics distribution

我试图生成具有对数分布的随机整数。我使用以下公式:

idx = Math.floor(Math.log((Math.random() * Math.pow(2.0, max)) + 1.0) / Math.log(2.0));

这很好用,可以生成1000次迭代这样的序列(每个数字表示生成索引的次数):

[525, 261, 119, 45, 29, 13, 5, 1, 1, 1]

Fiddle

我现在正在尝试调整此分布的斜率,因此它不会快速下降并产生类似的内容:

[150, 120, 100, 80, 60, ...]

盲目地玩系数并没有给我我想要的东西。任何想法如何实现它?

1 个答案:

答案 0 :(得分:4)

你提到了对数分布,但看起来你的代码被设计为生成截断的几何分布,尽管它有缺陷。有一个以上的分布称为对数分布,它们都不常见。请澄清你是否确实是指其中一个。

您计算楼层[log_2 U],其中U从1到(2 ^ max)+1均匀分布。这产生最大值的最大机率为1/2,但是你将其限制为max-1。所以,你有1/2最大机会产生0,2 / 2 ^最大几率产生1,4 / 2 ^最大机会产生2,...最多1/2 + 1/2 ^ max产生max-1的机会。

出现在您的代码中,但问题中的描述中缺少的是您正在使用

翻转计算的索引
idx = (max-idx) - 1

在此之后,你产生0的机会是1/2 + 1/2 ^ max,你产生k值的机会是1/2 ^(k + 1)。

我认为让U在[1,2 ^ max + 1]上统一是错误的。相反,我认为你希望U在[1,2 ^ max]上统一。那么你生成idx = k的机会是2 ^(max-k-1)/((2 ^ max)-1)。

idx = Math.floor(Math.log((Math.random()*(Math.pow(2.0, max)-1.0)) + 1.0) / Math.log(2.0));

zmii评论说,你可以通过用接近1.0的值替换两个2.0来获得更平坦的分布是好的。它对于小的max值产生不令人满意的结果的原因是你从[1,1.3 ^ max + 1]而不是[1,1.3 ^ max]均匀采样。当max较小且基数较小时,额外的+1会产生较大的差异。请尝试以下方法:

var zmii = 1.3;
idx = Math.floor(Math.log((Math.random()*(Math.pow(zmii, max)-1.0))+1.0) / Math.log(zmii));
相关问题