random number generator
36 bit
programming
algorithm
software development

Writing a 36 bit random number generator

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

A 36-bit random number generator means you want outputs in the range 0 through 2^36 - 1. The first design question is whether you need cryptographic randomness or just a deterministic pseudo-random generator for simulation, testing, or games. Those are different problems, and the implementation should reflect that difference immediately.

If you need real unpredictability, do not invent your own PRNG

For security-sensitive use, the answer is simple: ask a cryptographically secure source for 36 random bits.

python
1import secrets
2
3value = secrets.randbits(36)
4print(value)
5print(bin(value))

That gives you a value in the correct 36-bit range without asking you to design your own randomness algorithm.

If you need a deterministic PRNG, generate a wider state and mask

For simulations or reproducible testing, a common pattern is to use a well-behaved generator with a larger internal state and then keep only the low 36 bits of each output.

python
1class XorShift64:
2    def __init__(self, seed: int):
3        if seed == 0:
4            raise ValueError("seed must be non-zero")
5        self.state = seed & ((1 << 64) - 1)
6
7    def next36(self) -> int:
8        x = self.state
9        x ^= (x << 13) & ((1 << 64) - 1)
10        x ^= x >> 7
11        x ^= (x << 17) & ((1 << 64) - 1)
12        self.state = x & ((1 << 64) - 1)
13        return self.state & ((1 << 36) - 1)
14
15rng = XorShift64(seed=123456789)
16for _ in range(3):
17    print(rng.next36())

This gives deterministic 36-bit outputs while keeping a larger internal state than 36 bits.

Why output size and state size are different concerns

Many people hear "36-bit generator" and assume the internal state must also be 36 bits. That is not necessary. The output width can be 36 bits even if the generator internally uses 64 bits, 128 bits, or more.

In practice, using a larger internal state is often the better choice because:

  • periods are usually longer
  • quality is often better
  • implementation can still produce exactly 36-bit values by masking

What matters is that the returned value fits the desired range.

A simple LCG can work, but quality is limited

If you want a very small educational generator, an LCG can produce 36-bit outputs too.

python
1class LCG36:
2    def __init__(self, seed: int):
3        self.modulus = 1 << 36
4        self.a = 6364136223846793005 & (self.modulus - 1)
5        self.c = 1442695040888963407 & (self.modulus - 1)
6        self.state = seed & (self.modulus - 1)
7
8    def next(self) -> int:
9        self.state = (self.a * self.state + self.c) % self.modulus
10        return self.state
11
12rng = LCG36(42)
13print(rng.next())

This satisfies the 36-bit requirement, but statistically it is usually weaker than better modern PRNG designs.

Think about period and bias

A generator that outputs the correct numeric range is not automatically a good generator. Important properties include:

  • period length
  • distribution quality
  • correlation between successive values
  • suitability for the problem domain

For testing or simulation, use a generator with known behavior. For security, use a cryptographic source. Do not judge a generator only by whether the numbers "look random."

Validate the 36-bit range explicitly

Whatever implementation you use, verify that every value stays in the required range.

python
value = rng.next36()
assert 0 <= value < (1 << 36)

That sounds obvious, but range mistakes happen quickly when shifts, masks, and signed integer behavior are mixed carelessly.

Common Pitfalls

  • Writing a custom PRNG for security-sensitive use instead of using a cryptographic source.
  • Confusing 36-bit output width with 36-bit internal state requirements.
  • Assuming a simple LCG is good enough for every simulation problem.
  • Forgetting to mask or bound the output so it really stays in the 36-bit range.
  • Evaluating random quality only by visual inspection of a few numbers.

Summary

  • A 36-bit RNG means outputs must lie in 0 through 2^36 - 1.
  • For security, use a cryptographic source such as secrets.randbits(36).
  • For deterministic pseudo-random output, use a reasonable PRNG and mask to 36 bits.
  • Output width and internal state size are different design choices.
  • Choose the generator based on the job, not just on whether it can emit 36-bit values.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.