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.