Understanding Pseudo-Random Number Generators
Linear Congruential Generator Implementation
Building custom random number generators for reproducible results:
class LinearCongruentialGenerator {
constructor(seed = Date.now()) {
this.seed = seed;
this.a = 1664525;
this.c = 1013904223;
this.m = Math.pow(2, 32);
}
next() {
this.seed = (this.a * this.seed + this.c) % this.m;
return this.seed / this.m;
}
nextInt(min, max) {
return Math.floor(this.next() * (max - min + 1)) + min;
}
reset(seed) {
this.seed = seed;
}
}
// Usage with reproducible results
const rng = new LinearCongruentialGenerator(12345);
console.log(rng.next()); // Always same sequence with same seed
Mersenne Twister Algorithm
Implementing a high-quality pseudo-random number generator:
class MersenneTwister {
constructor(seed = Date.now()) {
this.N = 624;
this.M = 397;
this.MATRIX_A = 0x9908b0df;
this.UPPER_MASK = 0x80000000;
this.LOWER_MASK = 0x7fffffff;
this.mt = new Array(this.N);
this.mti = this.N + 1;
this.init(seed);
}
init(seed) {
this.mt[0] = seed >>> 0;
for (this.mti = 1; this.mti < this.N; this.mti++) {
const s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30);
this.mt[this.mti] = (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) +
(s & 0x0000ffff) * 1812433253) + this.mti;
this.mt[this.mti] >>>= 0;
}
}
generateNumbers() {
const mag01 = [0x0, this.MATRIX_A];
let y;
if (this.mti >= this.N) {
let kk;
for (kk = 0; kk < this.N - this.M; kk++) {
y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK);
this.mt[kk] = this.mt[kk + this.M] ^ (y >>> 1) ^ mag01[y & 0x1];
}
for (; kk < this.N - 1; kk++) {
y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK);
this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ (y >>> 1) ^ mag01[y & 0x1];
}
y = (this.mt[this.N - 1] & this.UPPER_MASK) | (this.mt[0] & this.LOWER_MASK);
this.mt[this.N - 1] = this.mt[this.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1];
this.mti = 0;
}
y = this.mt[this.mti++];
y ^= (y >>> 11);
y ^= (y << 7) & 0x9d2c5680;
y ^= (y << 15) & 0xefc60000;
y ^= (y >>> 18);
return (y >>> 0) * (1.0 / 4294967296.0);
}
random() {
return this.generateNumbers();
}
}
Statistical Distribution Generation
Normal Distribution (Box-Muller Transform)
Generating normally distributed random numbers for statistical applications:
class StatisticalDistributions {
static normalDistribution(mean = 0, stdDev = 1) {
let u = 0, v = 0;
while (u === 0) u = Math.random(); // Converting [0,1) to (0,1)
while (v === 0) v = Math.random();
const z0 = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2 * Math.PI * v);
return z0 * stdDev + mean;
}
static exponentialDistribution(lambda = 1) {
return -Math.log(1 - Math.random()) / lambda;
}
static poissonDistribution(lambda) {
const L = Math.exp(-lambda);
let k = 0;
let p = 1;
do {
k++;
p *= Math.random();
} while (p > L);
return k - 1;
}
static betaDistribution(alpha, beta) {
const gamma1 = this.gammaDistribution(alpha);
const gamma2 = this.gammaDistribution(beta);
return gamma1 / (gamma1 + gamma2);
}
static gammaDistribution(shape, scale = 1) {
if (shape < 1) {
return this.gammaDistribution(shape + 1, scale) * Math.pow(Math.random(), 1 / shape);
}
const d = shape - 1/3;
const c = 1 / Math.sqrt(9 * d);
while (true) {
let x, v;
do {
x = this.normalDistribution();
v = 1 + c * x;
} while (v <= 0);
v = v * v * v;
const u = Math.random();
if (u < 1 - 0.0331 * x * x * x * x) {
return d * v * scale;
}
if (Math.log(u) < 0.5 * x * x + d * (1 - v + Math.log(v))) {
return d * v * scale;
}
}
}
}
Monte Carlo Simulation Methods
Pi Estimation Using Random Sampling
Demonstrating Monte Carlo methods for mathematical approximation:
class MonteCarloSimulations {
static estimatePi(iterations = 1000000) {
let insideCircle = 0;
for (let i = 0; i < iterations; i++) {
const x = Math.random() * 2 - 1; // Random point between -1 and 1
const y = Math.random() * 2 - 1;
if (x * x + y * y <= 1) {
insideCircle++;
}
}
return 4 * insideCircle / iterations;
}
static integrateFunction(func, a, b, iterations = 100000) {
let sum = 0;
const range = b - a;
for (let i = 0; i < iterations; i++) {
const x = a + Math.random() * range;
sum += func(x);
}
return (sum / iterations) * range;
}
static portfolioRiskSimulation(assets, correlationMatrix, iterations = 10000) {
const returns = [];
for (let i = 0; i < iterations; i++) {
let portfolioReturn = 0;
const randomReturns = assets.map(() => StatisticalDistributions.normalDistribution());
// Apply correlation matrix (simplified)
for (let j = 0; j < assets.length; j++) {
portfolioReturn += assets[j].weight *
(assets[j].expectedReturn + randomReturns[j] * assets[j].volatility);
}
returns.push(portfolioReturn);
}
returns.sort((a, b) => a - b);
return {
mean: returns.reduce((sum, r) => sum + r, 0) / returns.length,
var5: returns[Math.floor(returns.length * 0.05)], // 5% VaR
var1: returns[Math.floor(returns.length * 0.01)], // 1% VaR
standardDeviation: this.calculateStandardDeviation(returns)
};
}
static calculateStandardDeviation(values) {
const mean = values.reduce((sum, val) => sum + val, 0) / values.length;
const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length;
return Math.sqrt(variance);
}
}
Sampling Algorithms
Reservoir Sampling
Efficiently sampling from large datasets or streams:
class SamplingAlgorithms {
static reservoirSampling(stream, k) {
const reservoir = [];
for (let i = 0; i < stream.length; i++) {
if (i < k) {
reservoir[i] = stream[i];
} else {
const j = Math.floor(Math.