Skip to main content
← Gists
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 by Math.imul destroy the sequential structure of the Weyl counter and spread bit dependencies across the full word.
  • | 0 coercions — 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.