typescript Feb 24, 2026
Splitmix32: A Fast Seeded PRNG
A 32-bit seeded pseudorandom number generator derived from MurmurHash3's finalizer. Deterministic, fast, and good enough for simulations that need reproducibility, not cryptography.
Math.random() gives you no control over the sequence it produces; you cannot replay it, checkpoint it, or share it across environments. Splitmix32 fills that role in 13 lines of TypeScript: feed in the same seed, get back the same sequence.
Deep dive
Read more about the Weyl sequence, avalanche properties, and mixer constants in my blog post Splitmix32: Beautiful Randomness.
The implementation
splitmix32.ts
export function splitmix32(seed: number):
() => number /* [0, 1) */ {
let state = seed | 0;
return () => {
state |= 0;
state = state + 0x9e3779b9 | 0;
let t = state ^ state >>> 16;
t = Math.imul(t, 0x21f0aaad);
t = t ^ t >>> 15;
t = Math.imul(t, 0x735a2d97);
return ((t = t ^ t >>> 15) >>> 0) / 4294967296;
};
}
How it works
- Weyl sequence (
state + 0x9e3779b9): advances state by a golden-ratio-derived constant each call, visiting every 32-bit value exactly once before repeating. - Xorshift-multiply mixer: three rounds of
x ^ (x >>> n)followed byMath.imuldestroy the sequential structure of the Weyl counter and spread bit dependencies across the full word. | 0coercions: force 32-bit integer semantics. Without them, additions overflow into 64-bit float territory silently.
When to use it
- Deterministic tests that need reproducible random sequences across runs and environments.
- Procedural generation for games, simulations, or visualizations where the same seed should always produce the same output.
- Not cryptography. 32 bits of state can be brute-forced in under a second. Use
crypto.getRandomValues()for anything security-sensitive.