I need to generate random numbers from JavaScript within the Beta probability distribution. I've Googled but can't find any libraries that appear to support this.
Can anyone suggest where I can find a library or code snippet that will do this?
Javascript creates pseudo-random numbers with the function Math. random() . This function takes no parameters and creates a random decimal number between 0 and 1. The returned value may be 0, but it will never be 1.
Perhaps the most generic way to do so is called inverse transform sampling: Generate a uniform random number in [0, 1]. Run the quantile function (also known as the inverse CDF or the PPF) on the uniform random number. The result is a random number that fits the distribution.
Math.random() The Math.random() function returns a floating-point, pseudo-random number that's greater than or equal to 0 and less than 1, with approximately uniform distribution over that range — which you can then scale to your desired range.
In JavaScript, you can generate a random number with the Math. random() function.
The jStat library has functions to sample from a beta distribution, as well as many other distributions.
var random_num = jStat.beta.sample( alpha, beta );
My translation. It's pretty much word for word, so it's probably not the most idiomatic javascript.
// javascript shim for Python's built-in 'sum'
function sum(nums) {
var accumulator = 0;
for (var i = 0, l = nums.length; i < l; i++)
accumulator += nums[i];
return accumulator;
}
// In case you were wondering, the nice functional version is slower.
// function sum_slow(nums) {
// return nums.reduce(function(a, b) { return a + b; }, 0);
// }
// var tenmil = _.range(1e7); sum(tenmil); sum_slow(tenmil);
// like betavariate, but more like R's name
function rbeta(alpha, beta) {
var alpha_gamma = rgamma(alpha, 1);
return alpha_gamma / (alpha_gamma + rgamma(beta, 1));
}
// From Python source, so I guess it's PSF Licensed
var SG_MAGICCONST = 1 + Math.log(4.5);
var LOG4 = Math.log(4.0);
function rgamma(alpha, beta) {
// does not check that alpha > 0 && beta > 0
if (alpha > 1) {
// Uses R.C.H. Cheng, "The generation of Gamma variables with non-integral
// shape parameters", Applied Statistics, (1977), 26, No. 1, p71-74
var ainv = Math.sqrt(2.0 * alpha - 1.0);
var bbb = alpha - LOG4;
var ccc = alpha + ainv;
while (true) {
var u1 = Math.random();
if (!((1e-7 < u1) && (u1 < 0.9999999))) {
continue;
}
var u2 = 1.0 - Math.random();
v = Math.log(u1/(1.0-u1))/ainv;
x = alpha*Math.exp(v);
var z = u1*u1*u2;
var r = bbb+ccc*v-x;
if (r + SG_MAGICCONST - 4.5*z >= 0.0 || r >= Math.log(z)) {
return x * beta;
}
}
}
else if (alpha == 1.0) {
var u = Math.random();
while (u <= 1e-7) {
u = Math.random();
}
return -Math.log(u) * beta;
}
else { // 0 < alpha < 1
// Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
while (true) {
var u3 = Math.random();
var b = (Math.E + alpha)/Math.E;
var p = b*u3;
if (p <= 1.0) {
x = Math.pow(p, (1.0/alpha));
}
else {
x = -Math.log((b-p)/alpha);
}
var u4 = Math.random();
if (p > 1.0) {
if (u4 <= Math.pow(x, (alpha - 1.0))) {
break;
}
}
else if (u4 <= Math.exp(-x)) {
break;
}
}
return x * beta;
}
}
Partially testable with means, which are easily calculated:
function testbeta(a, b, N) {
var sample_mean = sum(_.range(N).map(function() { return rbeta(a, b); })) / N;
var analytic_mean = a / (a + b);
console.log(sample_mean, "~", analytic_mean);
}
testbeta(5, 1, 100000);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With