Search code examples
c++randomc++14

Generating a random uint64_t


Given a random number engine e of arbitrary type E, how can I generate a random uint64_t over the full range?

Something like this, where the needs_random() function wants a random uint64_t and the blah() function is written in the modern <random> style which accepts a random engine of any type E.

void needs_random(uint64_t r);

template <typename E>
void blah(E& engine) {
  // ...
  needs_random(???);
}

Specifically, I am trying to seed an xorshift random number generator from an arbitrary engine e, and the xorshift generator needs two uint64_t values as seeds.


Solution

  • To be portable, just use unsigned long long with std::uniform_int_distribution (or any other distribution you need):

    #include <type_traits>
    #include <cstdint>
    #include <random>
    #include <iostream>
    
    void needs_random(uint64_t r) {
        std::cout << r << "\n";
    }
    
    template <typename E>
    void blah(E& engine) {
        std::uniform_int_distribution<unsigned long long> dis(
            std::numeric_limits<std::uint64_t>::min(),
            std::numeric_limits<std::uint64_t>::max()
        );
        needs_random(dis(engine));
    }
    
    int main() {
        std::random_device rd;
        std::mt19937 gen(rd());
        blah(gen);
        blah(gen);
    }
    

    The type unsigned long long is guaranteed to be at least 64-bits wide. The implicit integer conversion from unsigned long long to uint64_t should extract only the least significant 64 bits of the number.

    This code will only be sub-optimal on platforms where like sizeof(unsigned long long) * CHAR_BIT > 64, cause the higher bits will just be unused. But the code will still be portable to such platforms and will still work.