生成具有对数分布和自定义斜率的随机数
Generate random numbers with logarithmic distribution and custom slope
我正在尝试生成具有对数分布的随机整数。我使用以下公式:
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]
我现在正在尝试调整此分布的斜率,使其不会下降得那么快并产生如下内容:
[150, 120, 100, 80, 60, ...]
盲目地玩弄系数并没有给我想要的东西。任何想法如何实现它?
您提到了对数分布,但看起来您的代码旨在生成截断的几何分布,尽管它存在缺陷。有不止一种分布称为对数分布,其中 none 很常见。请澄清你是否真的指的是其中之一。
您计算 floor[log_2 U],其中 U 从 1 到 (2^max)+1 均匀分布。这有 1/2^max 的机会产生最大值,但您将其限制为 max-1。所以,你有 1/2^max 的机会产生 0,2/2^max 的机会产生 1,4/2^max 的机会产生 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 的评论是,您可以通过将两个 2.0 替换为更接近 1.0 的值来获得更平坦的分布,这很好。它对较小的 max 值产生不令人满意的结果的原因是您从 [1,1.3^max+1] 而不是 [1,1.3^max] 均匀采样。当 max 较小且 base 较小时,额外的 +1 会产生更大的差异。请尝试以下操作:
var zmii = 1.3;
idx = Math.floor(Math.log((Math.random()*(Math.pow(zmii, max)-1.0))+1.0) / Math.log(zmii));
我正在尝试生成具有对数分布的随机整数。我使用以下公式:
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]
我现在正在尝试调整此分布的斜率,使其不会下降得那么快并产生如下内容:
[150, 120, 100, 80, 60, ...]
盲目地玩弄系数并没有给我想要的东西。任何想法如何实现它?
您提到了对数分布,但看起来您的代码旨在生成截断的几何分布,尽管它存在缺陷。有不止一种分布称为对数分布,其中 none 很常见。请澄清你是否真的指的是其中之一。
您计算 floor[log_2 U],其中 U 从 1 到 (2^max)+1 均匀分布。这有 1/2^max 的机会产生最大值,但您将其限制为 max-1。所以,你有 1/2^max 的机会产生 0,2/2^max 的机会产生 1,4/2^max 的机会产生 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 的评论是,您可以通过将两个 2.0 替换为更接近 1.0 的值来获得更平坦的分布,这很好。它对较小的 max 值产生不令人满意的结果的原因是您从 [1,1.3^max+1] 而不是 [1,1.3^max] 均匀采样。当 max 较小且 base 较小时,额外的 +1 会产生更大的差异。请尝试以下操作:
var zmii = 1.3;
idx = Math.floor(Math.log((Math.random()*(Math.pow(zmii, max)-1.0))+1.0) / Math.log(zmii));