The random number generator in C plays a crucial role in various applications, from gaming to security. Whether you’re creating dice rolls, lottery games, or encryption keys, understanding how randomness works in C is essential. In addition, random number generator in C is so important, that every top-tier software development course focus on this particular topic.
In this guide, we'll also explore different ways to generate random numbers in C, covering everything from the basics to advanced techniques. You'll also find unique code examples, their outputs, and a detailed breakdown of each one.
How Random Number Generator in C Works
C does not have a true random number generator—instead, it provides functions to generate pseudo-random numbers. This means the numbers appear random but follow a predictable sequence based on a starting value (seed).
The most common functions used in C for generating random numbers are:
- rand() – Generates a pseudo-random integer.
- srand(seed) – Sets the seed for rand().
- time(NULL) – Often used as a seed for better randomness.
By default, rand() produces the same sequence of numbers each time you run the program unless you seed it with a unique value. Let’s see this in action.
Generating Random Numbers Using rand() and srand()
You can try and test this code on any of your machine with the compatible IDEs. However, for Linux-based system, you need to follow specialized C compiling instructions, otherwise it can create additional complexities.
Once, you’re ready with your IDE, just copy and paste the code to see its functionality in real-time. Rest, go through the explanation to understand how random number generator in C is working at its core.
Code Example 1: Generating Random Numbers Without srand()
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Random numbers without seeding:\n");
for(int i = 0; i < 5; i++) {
printf("%d\n", rand());
}
return 0;
}
Output: (Same every time you run it)
1804289383
846930886
1681692777
1714636915
1957747793
Explanation:
- This program generates five random numbers using rand().
- Since we haven't used srand(), the sequence remains the same each time the program runs.
- rand() pulls numbers from an internal sequence determined by the compiler’s implementation of the C standard library.
- Without a changing seed, the output sequence is predictable.
Code Example 2: Using srand() for Different Outputs
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL));
printf("Random numbers with seeding:\n");
for(int i = 0; i < 5; i++) {
printf("%d\n", rand());
}
return 0;
}
Output: (Different every time you run it)
1289473104
987343102
1348172312
874902347
2039481258
Explanation:
- srand(time(NULL)) seeds the random number generator with the current timestamp.
- Since time changes every second, running the program at different times results in different sequences.
- time(NULL) fetches the number of seconds elapsed since January 1, 1970 (Unix epoch).
- The seed modifies the starting point of the pseudo-random sequence, making the numbers appear more random.
Code Example 3: Generating Random Numbers in a Range
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL));
int lower = 10, upper = 50;
printf("Random numbers between %d and %d:\n", lower, upper);
for(int i = 0; i < 5; i++) {
printf("%d\n", (rand() % (upper - lower + 1)) + lower);
}
return 0;
}
Output:
23
49
34
17
42
Explanation:
- rand() % (upper - lower + 1) generates numbers within a given range.
- % (upper - lower + 1) ensures the value never exceeds the upper limit.
- Adding lower shifts the result to start at the desired minimum value.
- The range logic works because rand() produces numbers between 0 and RAND_MAX.
Code Example 4: Generating Random Floating-Point Numbers
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL));
printf("Random floating-point numbers between 0 and 1:\n");
for(int i = 0; i < 5; i++) {
printf("%.4f\n", (double)rand() / RAND_MAX);
}
return 0;
}
Output:
0.4573
0.8291
0.2156
0.9823
0.3728
Explanation:
- rand() / RAND_MAX normalizes values between 0.0 and 1.0.
- The division ensures the output remains within a floating-point range.
- Using %.4f limits the decimal precision to four places.
Random Number Generator in C: rand() vs srand()
Feature | rand() | srand() |
Purpose | Generates a pseudo-random number | Sets the seed for rand() |
Needs Seeding? | No (but will always give the same numbers) | Yes (to change output each run) |
Affects Random Sequence? | No | Yes |
Output Consistency | Same sequence every execution | Different sequence if seeded uniquely |
Default Seed Value | System-dependent, often set to 1 | Needs to be explicitly defined |
Usage Frequency | Can be used multiple times | Typically used once per program execution |
Works Alone? | Yes | No, needs rand() to generate numbers |
Used in Cryptography? | No, not secure | No, but can improve randomness slightly |
Requires Additional Libraries? | No, included in <stdlib.h> | No, but <time.h> is often needed for time(NULL) seeding |
Suitable for Games? | Yes, but should be seeded | Yes, as it ensures varying outputs |
Suitable for Machine Learning? | No, lacks sufficient randomness | No, better alternatives like random() exist |
Best Practices for Using Random Number Generator in C
To ensure optimal randomness and avoid common pitfalls, follow these best practices when using random number generator in C.
1. Always Seed the Random Number Generator in C
- The rand() function produces the same sequence of numbers unless seeded.
- Use srand(time(NULL)) to initialize the seed with the current time for different outputs on each execution.
- Example:
srand(time(NULL));
2. Avoid Using rand() for Cryptographic Applications
- rand() is not cryptographically secure.
- Use specialized libraries like OpenSSL or libsodium for security-sensitive applications.
- Example (Using OpenSSL for secure random bytes):
#include <openssl/rand.h>
unsigned char buffer[16];
RAND_bytes(buffer, sizeof(buffer));
3. Use Modulo Carefully When Generating a Range
- The common approach (rand() % (max - min + 1)) + min can introduce bias.
- Prefer floating-point scaling for better uniformity.
- Example:
int randomInRange = min + (int)((double)rand() / (RAND_MAX + 1) * (max - min + 1));
4. Use RAND_MAX for Normalization
- RAND_MAX is the maximum value rand() can return (often 32767).
- Normalize values between 0 and 1 for more predictable results.
- Example:
double randomValue = (double)rand() / RAND_MAX;
5. Be Aware of Thread Safety Issues
- rand() is not thread-safe.
- Use rand_r() (on some systems) or better alternatives like mt19937 for multi-threaded programs.
6. Prefer Mersenne Twister for High-Quality Random Numbers
- rand() has known limitations in randomness distribution.
- The Mersenne Twister (mt19937) is a better alternative with a longer period and better randomness.
- Example:
#include <random>
std::mt19937 rng(time(NULL));
int randomNum = rng() % 100;
7. Use Different Seeds for Multiple Runs
If running a simulation multiple times, ensure that different seeds are used for each run to avoid identical outputs.
8. Avoid Over-Seeding in Loops
- Calling srand(time(NULL)) inside a loop can result in the same values being generated in quick iterations.
- Seed once at the beginning of the program instead.
Conclusion
The random number generator in C is a powerful tool when used correctly. By understanding rand(), srand(), and how to scale values, you can generate numbers for various applications efficiently. Always follow best practices and avoid common pitfalls to ensure better randomness.
Now you know how to use the random number generator in C effectively. Try the code snippets and see the randomness in action.
FAQs
1. What is a random number generator in C, and why is it called pseudo-random?
A random number generator in C refers to functions like rand() that generate pseudo-random numbers—numbers that appear random but are actually determined by an algorithm. Since rand() follows a predictable sequence based on a seed value, the numbers aren’t truly random but pseudo-random. A random number generator in C refers to functions like rand() that generate pseudo-random numbers —numbers that appear random but are actually determined by an algorithm. Since rand() follows a predictable sequence based on a seed value, the numbers aren’t truly random but pseudo-random .
2. What is the purpose of srand() in C?
srand() sets the seed value for rand(). Without srand(), rand() generates the same sequence every time the program runs. srand() sets the seed value for rand(). Without srand(), rand() generates the same sequence every time the program runs. Example: #include #include #include int main() { srand(time(NULL)); // Seed based on current time printf("Random Number: %d\n", rand()); return 0;} #include < stdio . h > #include < stdlib . h > #include < time . h > int main ( ) { srand ( time ( NULL ) ; // Seed based on current time printf ( "Random Number: %d\n" , rand ( ) ; return 0 ; } Output (varies on each run): Random Number: 1736257313 Random Number : 1736257313
3. What is RAND_MAX, and why is it important?
RAND_MAX is a constant that represents the maximum value rand() can return, typically 32767. RAND_MAX is a constant that represents the maximum value rand() can return, typically 32767 . Example: #include #include int main() { printf("RAND_MAX value: %d\n", RAND_MAX); return 0;} #include < stdio . h > #include < stdlib . h > int main ( ) { printf ( "RAND_MAX value: %d\n" , RAND_MAX ) ; return 0 ; } Output: RAND_MAX value: 32767 RAND_MAX value : 32767
4. How can I generate random numbers within a specific range in C?
Example: Generating a random number between min and max #include #include #include int main() { int min = 10, max = 50; srand(time(NULL)); int randomNum = min + rand() % (max - min + 1); printf("Random Number in range %d-%d: %d\n", min, max, randomNum); return 0;} #include < stdio . h > #include < stdlib . h > #include < time . h > int main ( ) { int min = 10 , max = 50 ; srand ( time ( NULL ) ; int randomNum = min + rand ( ) % ( max - min + 1 ) ; printf ( "Random Number in range %d-%d: %d\n" , min , max , randomNum ) ; return 0 ; } Output (varies on each run): Random Number in range 10-50: 27 Random Number in range 10 - 50 : 27
5. Why should I avoid using rand() for security-sensitive applications?
rand() is not cryptographically secure. Instead, use OpenSSL’s RAND_bytes(). rand() is not cryptographically secure . Instead, use OpenSSL’s RAND_bytes(). Example (Secure random number using OpenSSL): #include #include int main() { unsigned char buffer[4]; // 4 random bytes RAND_bytes(buffer, sizeof(buffer)); printf("Secure Random Number: %u\n", *(unsigned int*)buffer); return 0;} #include < openssl / rand . h > #include < stdio . h > int main ( ) { unsigned char buffer [ 4 ] ; // 4 random bytes RAND_bytes ( buffer , sizeof ( buffer ) ; printf ( "Secure Random Number: %u\n" , * ( unsigned int * ) buffer ) ; return 0 ; } Output (varies on each run): Secure Random Number: 312485239 Secure Random Number : 312485239
6. What are the limitations of rand() in multi-threaded programs?
rand() is not thread-safe. Instead, use rand_r() or Mersenne Twister. rand() is not thread-safe . Instead, use rand_r() or Mersenne Twister . Example (Using rand_r() in a multi-threaded environment): #include #include #include void *generateRandom(void *seed) { unsigned int *threadSeed = (unsigned int *)seed; printf("Thread-safe Random Number: %d\n", rand_r(threadSeed)); return NULL;}int main() { pthread_t thread1, thread2; unsigned int seed = time(NULL); pthread_create(&thread1, NULL, generateRandom, &seed); pthread_create(&thread2, NULL, generateRandom, &seed); pthread_join(thread1, NULL); pthread_join(thread2, NULL); return 0;} #include < stdio . h > #include < stdlib . h > #include < pthread . h > void * generateRandom ( void * seed ) { unsigned int * threadSeed = ( unsigned int * ) seed ; printf ( "Thread-safe Random Number: %d\n" , rand_r ( threadSeed ) ; return NULL ; } int main ( ) { pthread_t thread1 , thread2 ; unsigned int seed = time ( NULL ) ; pthread_create ( & thread1 , NULL , generateRandom , & seed ) ; pthread_create ( & thread2 , NULL , generateRandom , & seed ) ; pthread_join ( thread1 , NULL ) ; pthread_join ( thread2 , NULL ) ; return 0 ; } Output (varies on each run): Thread-safe Random Number: 106761346Thread-safe Random Number: 1763517814 Thread - safe Random Number : 106761346 Thread - safe Random Number : 1763517814
7. What is the Mersenne Twister algorithm, and why is it better than rand()?
The Mersenne Twister (mt19937) provides better randomness and a longer period (2¹⁹⁹³⁷-1). The Mersenne Twister (mt19937) provides better randomness and a longer period ( 2¹⁹⁹³⁷-1 ). Example (Using Mersenne Twister in C++): #include #include using namespace std;int main() { mt19937 rng(time(NULL)); // Mersenne Twister cout << "Mersenne Twister Random Number: " << rng() % 100 << endl; return 0;} #include < iostream > #include < random > using namespace std ; int main ( ) { mt19937 rng ( time ( NULL ) ; // Mersenne Twister cout << "Mersenne Twister Random Number: " << rng ( ) % 100 << endl ; return 0 ; } Output (varies on each run): Mersenne Twister Random Number: 83 Mersenne Twister Random Number : 83
8. Can I generate floating-point random numbers in C?
Example: Generating a float between 0 and 1 #include #include int main() { printf("Random Float: %f\n", (double)rand() / RAND_MAX); return 0;} #include < stdio . h > #include < stdlib . h > int main ( ) { printf ( "Random Float: %f\n" , ( double ) rand ( ) / RAND_MAX ) ; return 0 ; } Output (varies on each run): Random Float: 0.692547 Random Float : 0.692547
9. What happens if I call srand() multiple times in a loop?
Calling srand(time(NULL)) inside a loop may result in repeating values. Calling srand(time(NULL)) inside a loop may result in repeating values . Incorrect Example (Repetitive values): #include #include #include int main() { for (int i = 0; i < 5; i++) { srand(time(NULL)); // Reseeding too frequently printf("%d\n", rand()); } return 0;} #include < stdio . h > #include < stdlib . h > #include < time . h > int main ( ) { for ( int i = 0 ; i < 5 ; i ++ ) { srand ( time ( NULL ) ; // Reseeding too frequently printf ( "%d\n" , rand ( ) ; } return 0 ; } Output (Same number repeated): 1357913579135791357913579 13579 Correct Approach: #include #include #include int main() { srand(time(NULL)); for (int i = 0; i < 5; i++) { printf("%d\n", rand()); } return 0;} #include < stdio . h > #include < stdlib . h > #include < time . h > int main ( ) { srand ( time ( NULL ) ; for ( int i = 0 ; i < 5 ; i ++ ) { printf ( "%d\n" , rand ( ) ; } return 0 ; } Output (Varies on each run): 1357924680987655432112345 13579 24680 98765 54321 12345
10. How do I generate random numbers without using rand()?
Use /dev/random or /dev/urandom on Linux. Use /dev/random or /dev/urandom on Linux . Example: #include #include int main() { FILE *fp = fopen("/dev/urandom", "r"); int num; fread(&num, sizeof(int), 1, fp); fclose(fp); printf("Random Number from /dev/urandom: %d\n", num); return 0;} #include < stdio . h > #include < stdlib . h > int main ( ) { FILE * fp = fopen ( "/dev/urandom" , "r" ) ; int num ; fread ( & num , sizeof ( int ) , 1 , fp ) ; fclose ( fp ) ; printf ( "Random Number from /dev/urandom: %d\n" , num ) ; return 0 ; } Output (varies on each run): Random Number from /dev/urandom: 1947238491 Random Number from / dev / urandom : 1947238491
11. Why do some random number sequences repeat after restarting the program?
This happens when srand() is not used or the seed is constant. This happens when srand() is not used or the seed is constant. Example (No seed, repetitive sequence): #include #include int main() { printf("Random Number: %d\n", rand()); return 0;} #include < stdio . h > #include < stdlib . h > int main ( ) { printf ( "Random Number: %d\n" , rand ( ) ; return 0 ; } Output (same every run): Random Number: 41 Random Number : 41 Correct Approach: #include #include #include int main() { srand(time(NULL)); // Different sequence each run printf("Random Number: %d\n", rand()); return 0;} #include < stdio . h > #include < stdlib . h > #include < time . h > int main ( ) { srand ( time ( NULL ) ; // Different sequence each run printf ( "Random Number: %d\n" , rand ( ) ; return 0 ; } Output : Output : Random Number: 98347561 Random Number : 98347561
Take a Free C Programming Quiz
Answer quick questions and assess your C programming knowledge
