rand
random number generation
programming
C language
algorithms

Should I use rand N or rand / RAND_MAX / N 1?

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

In the realm of programming, generating random numbers is a critical task for numerous applications, ranging from simulations to gaming and cryptography. While languages like C and C++ provide functions like `rand()`, ensuring the randomness and uniformity of the generated numbers requires a good understanding of how to scale and use the output effectively.

This article compares two popular methods to generate random numbers within a specific range using C/C++: `rand() % N` and `rand() / (RAND_MAX / N + 1)`.

Understanding `rand()`

The `rand()` function generates a pseudo-random integer between `0` and `RAND_MAX`, where `RAND_MAX` is a constant defined in the `stdlib.h` header, typically with a value of at least `32767`. Given that `rand()` often has a bounded range determined by `RAND_MAX`, scaling this to any arbitrary range `(0, N-1)` becomes a central question.

Method 1: `rand() % N`

The expression `rand() % N` is perhaps the most straightforward method to generate a number within the range `0` to `N-1`. Here, the modulus operator `%` is used to wrap around the sequence of integers produced by `rand()`.

Pros and Cons

  • Pros:
    • Simplicity: Easy to implement and understand.
    • Efficiency: Performs faster due to minimal computational overhead.
  • Cons:
    • Non-uniform Distribution: If `RAND_MAX + 1` is not an exact multiple of `N`, this method will produce some numbers more frequently than others. This can lead to a bias known as "modulo bias".
    • Limited Range: May not utilize the full precision available in the generated random value.

Example

  • Pros:
    • Uniform Distribution: Reduces or eliminates bias by scaling the numbers more evenly across the range.
  • Cons:
    • Complexity: Slightly more tricky to implement and can be a bit more computationally expensive due to division.
    • Potential Overhead: Requires floating-point operations which might be less performant, especially in systems with limited floating-point computation power.

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.