Generate random numbers from various statistical distributions for data visualization and scientific computing.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Utilities for creating reproducible random number sequences and using custom random sources. Essential for testing, simulations requiring reproducibility, and integrating with other random number generators.
A deterministic pseudorandom number generator that produces reproducible sequences when given the same seed.
/**
* Returns a linear congruential generator function
* @param seed - Seed value (number in [0,1) or integer), defaults to Math.random()
* @returns Generator function compatible with Math.random interface
*/
function randomLcg(seed?: number): () => number;Usage Examples:
import { randomLcg } from "d3-random";
// Create seeded generator for reproducible results
const seeded = randomLcg(0.44871573888282423);
console.log(seeded()); // Always produces the same sequence
console.log(seeded()); // Next value in the deterministic sequence
// Integer seed (uses lower 32 bits)
const intSeeded = randomLcg(12345);
console.log(intSeeded()); // Deterministic sequence based on 12345
// Auto-seeded (uses Math.random)
const autoSeeded = randomLcg();
console.log(autoSeeded()); // Different sequence each time
// Two generators with same seed produce identical sequences
const gen1 = randomLcg(42);
const gen2 = randomLcg(42);
console.log(gen1() === gen2()); // trueAll distribution functions support the .source() method for using custom random number generators instead of Math.random.
/**
* Creates a new distribution function using a custom random source
* @param source - Random number generator function returning values in [0, 1)
* @returns New distribution function using the custom source
*/
interface DistributionFunction {
source(source: () => number): DistributionFunction;
}
// Example signatures for common distributions
randomUniform.source(source: () => number): typeof randomUniform;
randomNormal.source(source: () => number): typeof randomNormal;
randomGamma.source(source: () => number): typeof randomGamma;
// ... (all distribution functions have this method)Usage Examples:
import { randomNormal, randomUniform, randomLcg, randomGamma } from "d3-random";
// Using seeded generator with normal distribution
const seed = 0.123456789;
const seededNormal = randomNormal.source(randomLcg(seed))(100, 15);
console.log(seededNormal()); // Reproducible normal distribution
// Chain seeded generators for complex reproducible simulations
const masterSeed = 0.987654321;
const seededUniform = randomUniform.source(randomLcg(masterSeed))(0, 10);
const seededGamma = randomGamma.source(randomLcg(masterSeed + 1))(2, 1);
console.log(seededUniform()); // Reproducible uniform
console.log(seededGamma()); // Reproducible gamma
// Custom random source (e.g., from another library)
function customRandom() {
// Your custom implementation
return Math.random(); // Placeholder
}
const customNormal = randomNormal.source(customRandom)(0, 1);
console.log(customNormal()); // Uses your custom random sourceComplete example showing how to create reproducible statistical simulations:
import { randomNormal, randomLcg, randomPoisson } from "d3-random";
/**
* Reproducible Monte Carlo simulation
* @param seed - Master seed for reproducibility
* @param iterations - Number of simulation iterations
* @returns Simulation results
*/
function runSimulation(seed, iterations = 10000) {
// Create seeded generators
const normalGen = randomNormal.source(randomLcg(seed))(50, 10);
const poissonGen = randomPoisson.source(randomLcg(seed + 1))(5);
let results = [];
for (let i = 0; i < iterations; i++) {
const normalValue = normalGen();
const poissonValue = poissonGen();
results.push({
normal: normalValue,
poisson: poissonValue,
combined: normalValue + poissonValue
});
}
return results;
}
// Run simulation with fixed seed - always produces same results
const simulation1 = runSimulation(0.42);
const simulation2 = runSimulation(0.42);
console.log(simulation1[0].normal === simulation2[0].normal); // true
// Different seed produces different but still reproducible results
const simulation3 = runSimulation(0.84);
console.log(simulation1[0].normal === simulation3[0].normal); // falseExamples of how to use seeded generators in testing scenarios:
import { randomUniform, randomLcg } from "d3-random";
// Test function that depends on randomness
function processRandomData(count) {
const random = randomUniform(1, 100);
return Array.from({length: count}, () => Math.round(random()));
}
// Test with seeded randomness for reproducible tests
function testProcessRandomData() {
// Override Math.random temporarily for testing
const originalRandom = Math.random;
Math.random = randomLcg(0.5);
const result = processRandomData(5);
console.log(result); // Always [67, 37, 85, 12, 41] with this seed
// Restore original Math.random
Math.random = originalRandom;
}
// Better approach: modify function to accept custom random source
function processRandomDataWithSource(count, randomSource = randomUniform()) {
return Array.from({length: count}, () => Math.round(randomSource()));
}
// Test with explicit seeded source
function testWithExplicitSource() {
const seededRandom = randomUniform.source(randomLcg(0.5))(1, 100);
const result = processRandomDataWithSource(5, seededRandom);
console.log(result); // Reproducible results
}Important notes about reproducibility across different environments:
import { randomLcg, randomNormal } from "d3-random";
// randomLcg provides consistent results across platforms
const seed = 0.44871573888282423;
const lcg = randomLcg(seed);
// These values will be identical on all platforms
console.log(lcg()); // Always: 0.6678668977692723
console.log(lcg()); // Always: 0.15307576954364777
console.log(lcg()); // Always: 0.29501388501375914
// Distribution functions using seeded sources are also reproducible
const seededNormal = randomNormal.source(randomLcg(seed))(0, 1);
console.log(seededNormal()); // Always: -0.6253955998897069
// Important: Only d3-random's own generators guarantee cross-platform consistency
// Using Math.random or other sources may vary between JavaScript engines// Random source function type (compatible with Math.random)
type RandomSource = () => number;
// All distribution functions implement this interface
interface SeededDistribution<T extends Function> {
source(source: RandomSource): T;
}
// Linear congruential generator type
type LcgGenerator = RandomSource;Install with Tessl CLI
npx tessl i tessl/npm-d3-random