std::mt19937


Engine: std::mt19937

std::mt19937 is a Mersenne Twister random number engine defined in the C++ Standard Library. It's part of the random number generation facilities introduced in C++11. The Mersenne Twister is a pseudorandom number generator (PRNG) that provides high-quality random numbers with a long period, making it suitable for a wide range of applications.

Key Characteristics

Example 1: Basic Usage of std::mt19937

#include <iostream>
#include <random>
#include <ctime>

int main() {
    // Seed with current time
    std::mt19937 gen(static_cast<unsigned int>(std::time(0)));

    // Generate and print a few random numbers
    for (int i = 0; i < 5; ++i) {
        std::cout << "Random number: " << gen() << std::endl;
    }

    // Print the range of generated numbers
    std::cout << "Min value: " << gen.min() << std::endl;
    std::cout << "Max value: " << gen.max() << std::endl;

    return 0;
}

Explanation:

2. Using std::mt19937 with Distributions

#include <iostream>
#include <random>
#include <vector>
#include <algorithm>

int main() {
    std::random_device rd;  // Used to obtain a seed for the random number engine
    std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()

    // Uniform distribution for integers between 1 and 100
    std::uniform_int_distribution<> uniform_dist(1, 100);

    // Normal distribution with mean 50 and standard deviation 10
    std::normal_distribution<> normal_dist(50.0, 10.0);

    std::vector<int> uniform_numbers;
    std::vector<double> normal_numbers;

    // Generate numbers
    for (int i = 0; i < 10; ++i) {
        uniform_numbers.push_back(uniform_dist(gen));
        normal_numbers.push_back(normal_dist(gen));
    }

    // Print uniform distribution results
    std::cout << "Uniform distribution (1-100): ";
    for (int num : uniform_numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Print normal distribution results
    std::cout << "Normal distribution (mean=50, std_dev=10): ";
    for (double num : normal_numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

Explanation:

Example 3: Generating a Random Shuffle

#include <iostream>
#include <random>
#include <algorithm>
#include <vector>
#include <chrono>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // Seed with a time-based value
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::mt19937 gen(seed);

    std::cout << "Original vector: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Shuffle the vector
    std::shuffle(numbers.begin(), numbers.end(), gen);

    std::cout << "Shuffled vector: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

Explanation:

Example 4: Reproducible Random Numbers

#include <iostream>
#include <random>
#include <vector>

void generateNumbers(std::mt19937& gen, std::vector<int>& numbers, int count) {
    std::uniform_int_distribution<> dis(1, 100);
    for (int i = 0; i < count; ++i) {
        numbers.push_back(dis(gen));
    }
}

int main() {
    const unsigned int SEED = 12345;
    const int COUNT = 5;

    std::mt19937 gen1(SEED);
    std::mt19937 gen2(SEED);

    std::vector<int> numbers1, numbers2;

    generateNumbers(gen1, numbers1, COUNT);
    generateNumbers(gen2, numbers2, COUNT);

    std::cout << "First set:  ";
    for (int num : numbers1) std::cout << num << " ";
    std::cout << std::endl;

    std::cout << "Second set: ";
    for (int num : numbers2) std::cout << num << " ";
    std::cout << std::endl;

    return 0;
}

Explanation:

Additional Considerations

  1. 64-bit Version: std::mt19937_64 is available for generating 64-bit random numbers.

  2. Performance: mt19937 is generally fast and suitable for most applications requiring high-quality random numbers.

  3. State Size: The state size of mt19937 is quite large (2.5 KB), which might be a consideration in memory-constrained environments.

  4. Not Cryptographically Secure: While high-quality, mt19937 is not suitable for cryptographic purposes.

  5. Seeding: Proper seeding is crucial for ensuring randomness across different runs of the program.

Summary

std::mt19937 is a powerful and widely-used random number engine in C++:

  1. It provides high-quality pseudorandom numbers with a very long period.
  2. Suitable for a wide range of applications requiring good statistical properties.
  3. Can be used with various distribution types for different random number patterns.
  4. Deterministic when seeded with the same value, allowing for reproducible results.

Key points to remember:

Best practices:

std::mt19937 is a cornerstone of modern C++ random number generation, offering a good balance of speed, quality, and ease of use for most random number generation needs in non-cryptographic applications.

Related

Previous Page | Course Schedule | Course Content