Unifying and simplifying some of the samples already provided I will summarize to:
// Good random seed, good engine auto rnd1 = std::mt19937(std::random_device{}()); // Good random seed, default engine auto rnd2 = std::default_random_engine(std::random_device{}()); // like rnd1, but force distribution to int32_t range auto rnd3 = std::bind(std::uniform_int_distribution<int32_t>{}, std::mt19937(std::random_device{}())); // like rnd3, but force distribution across negative numbers as well auto rnd4 = std::bind(std::uniform_int_distribution<int32_t>{std::numeric_limits<int32_t>::min(),std::numeric_limits<int32_t>::max()}, std::mt19937(std::random_device{}()));
Then I ran some tests to see what the defaults look like:
#include <random> #include <functional> #include <limits> #include <iostream> template<class Func> void print_min_mean_max(Func f) { typedef decltype(f()) ret_t; ret_t min = std::numeric_limits<ret_t>::max(), max = std::numeric_limits<ret_t>::min(); uint64_t total = 0, count = 10000000; for (uint64_t i = 0; i < count; ++i) { auto res = f(); min = std::min(min,res); max = std::max(max,res); total += res; } std::cout << "min: " << min << " mean: " << (total/count) << " max: " << max << std::endl; } int main() { auto rnd1 = std::mt19937(std::random_device{}()); auto rnd2 = std::default_random_engine(std::random_device{}()); auto rnd3 = std::bind(std::uniform_int_distribution<int32_t>{}, std::mt19937(std::random_device{}())); auto rnd4 = std::bind(std::uniform_int_distribution<int32_t>{std::numeric_limits<int32_t>::min(),std::numeric_limits<int32_t>::max()}, std::mt19937(std::random_device{}())); print_min_mean_max(rnd1); print_min_mean_max(rnd2); print_min_mean_max(rnd3); print_min_mean_max(rnd4); }
Produces the output:
min: 234 mean: 2147328297 max: 4294966759 min: 349 mean: 1073305503 max: 2147483423 min: 601 mean: 1073779123 max: 2147483022 min: -2147481965 mean: 178496 max: 2147482978
So as we can see, mt19937 and default_random_engine have a different default range, so use of uniform_int_distribution is advised.
Also, default uniform_int_distribution is [0, max_int] (non-negative), even when using a signed integer type. Must provide range explicitly if you want full range.
Finally, its important to remember this at times like these.
randis part of standard C, andrandomis part of POSIX andarc4randomis provided in BSD.