前倾随机数的概率分布

6

假设我每秒从1到50中伪随机地选择一个数字,持续100秒,随着时间的推移,所选数字更可能是较大的数字。如何构建这样的算法?

例如:在99秒后,选择接近50的数字的概率比选择接近1的数字的概率更大。

或者:在10秒后选择的数字比在9秒后选择的数字更可能是较大的数字。

4个回答

5
选择任何凹的单调函数,如平方根,将0映射到0,1映射到1。生成一个[0,1]之间的随机数,应用该函数,然后将[0,1]拉伸到所需的区间([1,50])。
现在,如果你从线性变换f(x)=x变形成为上述变换函数,例如使用简单的加权,就可以得到期望的效果。

@yi_H 不太确定我是否完全理解了。但是你的函数需要每秒钟更改一次。举个例子,让我们看一下函数序列f(i,x) = pow(x,1/i),它从f(x)=x开始,然后变成f(x)=sqrt(x)...并且它会做你想要的事情。你不能在所有秒钟都坚持一个函数(否则概率就没有增加的理由)。对吧? - Ricky Bobby
是的,你可以采用一系列函数或者像我写的那样在它们之间进行变形。f(x) = (1-i)x + i sqrt(x),其中i从0到1变化。 - Karoly Horvath

4

我有一个简单的解决方案。不要使用 rand(1, 50)(假设此函数生成均匀随机数1..50),而是使用以下表达式:

power(rand(1, power(50, exp)), 1/exp)

这将仍然给你所有的数字1到50。对于exp = 1,分布将是均匀的。当你稍微增加exp(例如1.1左右),获得更大数字的概率将会增加。exp越高,它就会更向50增长。

所以你可以做如下操作:

factor = 1 /* finetune this for your needs */
for second = 0..100
    exp = 1 + (second / 100) * factor
    rand_num = power(rand(1, power(50, exp)), 1/exp)
endfor

1

伪代码:

let i = 0
let n = 50 // Adjust for your needs
for i goes to 100 {
  randomnum = int(sqrt(rand(1, 50*n)));
}

这可能会非常前卫,但这是一种处理方式。

感谢Ricky Bobby指出了我旧方法中的一个根本性问题。这受到yi_H建议使用像sqrt这样的函数的启发。


不确定它是否适用于任何rand函数。如果每步rand是均匀的,则概率仍然是均匀的(选择1的概率与51相同,即使您消除了50以上的数字也是如此)。或者我错过了什么? - Ricky Bobby
我认为凹函数需要随着i的变化而演化,否则概率分布在所有时间上都是相同的。您可以使用randomnum int(50*pow(rand(),1/i))。 - Ricky Bobby
我给你一个加一的赞,因为我真的觉得你的第一种方法很有趣,即使它是错误的。Tomas Telensky 给出了正确的答案。 - Ricky Bobby

0

你正在做的事情可能有更简单的方法,但一般的解决方案是使用反变换抽样

本质上,如果您想要生成具有给定概率密度函数(PDF)p(x)的随机数,您首先需要计算反累积分布函数(CDF)P'(x)。 然后,您可以生成0到1之间的均匀随机数,然后将其应用于P'(x)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接