生成具有非均匀分布的随机数

时间:2013-04-19 17:56:48

标签: javascript random distribution

Javascript的Math.random()返回带有“统一”分布的伪随机数。

我需要生成一个偏向任一侧的[0,1]范围内的随机数。 (意思是,在0或1旁边获得更多数字的机会更高)

理想情况下,我希望有一个参数来设置此曲线。

我认为我可以Math.random^2来获得这样的结果,但是有什么更复杂的方法来实现这一目标?

4 个答案:

答案 0 :(得分:15)

我想你想要beta distribution with alpha=beta=0.5

可以使用逆累积分布将均匀随机数转换为β分布。

unif = Math.random()

我不熟悉javascript,但这应该是明确的:

beta = sin(unif*pi/2)^2

PS:你可以生成许多这样的数字并绘制直方图 enter image description here

修改

如果偏向0,则将beta值转换为 -

beta_left = (beta < 0.5) ? 2*beta : 2*(1-beta);

enter image description here

对于倾斜1,转换为 -

beta_right = (beta > 0.5) ? 2*beta-1 : 2*(1-beta)-1;

enter image description here

答案 1 :(得分:3)

我认为你需要重新考虑你的问题。泊松是根据速率指定的计数分布,例如每个时间段平均看到的事物的出现次数。它产生正整数,因此结果不能只在[0,1]范围内。你能澄清一下你想要的吗?

无论如何,要生成具有速率λ的泊松,一个算法是:

threshold = Math.exp(-lambda)
count = 0
product = 1.0
while (product *= rand) >= threshold {
      count += 1
}
return count

其中“rand”是Uniform(0,1)的函数调用。我不知道javascript,但这应该足够简单,你可以实现。

回复已修改的问题:

有几种分布在有界范围内产生结果,但其中许多不适合胆小的人,例如Johnson家族或Beta分布。

一个简单的就是三角形分布。 Sqrt(rand)将三角形分布为1,而(1-Sqrt(1-rand))将三角形分布为零。

可以使用

生成m(其中0 <= m <= 1)的模式(最常见值)的更一般的三角形
if rand <= m
    return m * Sqrt(rand)
else
    return 1 - ((1 - m) * Sqrt(1 - rand))

请注意,每次调用rand都是一个单独的Uniform随机数,如果为rand生成一个值并在整个过程中使用它,这将不正确。

答案 2 :(得分:3)

我想出了一种更简单的方法,可以将随机数倾斜到每一侧,并且没有任何依赖关系。

此方法使用两个Javascript的常规随机数。第一个与自身相乘(指数越大,偏斜效应越大),第二个选择偏向分布的哪一侧。

function skewedRandom() {
    const a = Math.pow(Math.random(), 2);
    if (Math.random() < 0.5) {
        return a;
    }
    return 1 - a;
}

在此代码中,指数设置为2.来自10,000次执行的样本直方图,指数为2,如上所述:

Histogram with exponent 2

使用指数3:

Histogram with exponent 3

用指数10: Histogram with exponent 10

答案 3 :(得分:2)

您可以在可用的情况下使用window.crypto.getRandomValues

<div id="result"></div>

var randVal = new Uint8Array(1);

window.crypto.getRandomValues(randVal);

document.getElementById("result").textContent = randVal[0] / 255;

jsfiddle

(如果这是你要求的,我不确定)

或者也许就是这个

<div id="result"></div>

function poissonRandomNumber(lambda) {
    var L = Math.exp(-lambda),
        k = 0,
        p = 1;

    do {
        k = k + 1;
        p = p * Math.random();
    } while (p > L);

    return k - 1;
}

document.getElementById("result").textContent = poissonRandomNumber(100);

也在jsfiddle