{"id":1081,"date":"2015-04-08T09:48:22","date_gmt":"2015-04-08T16:48:22","guid":{"rendered":"http:\/\/www.elbeno.com\/blog\/?p=1081"},"modified":"2025-06-03T07:34:41","modified_gmt":"2025-06-03T13:34:41","slug":"rules-for-using-random","status":"publish","type":"post","link":"https:\/\/www.elbeno.com\/blog\/?p=1081","title":{"rendered":"Rules for using &lt;random&gt;"},"content":{"rendered":"<p>These days, it&#8217;s easy to do the right thing.<\/p>\n<p>Don&#8217;t do this:<\/p>\n<ul>\n<li>Don&#8217;t use <code>std::rand()<\/code>. Ever.<\/li>\n<li>Don&#8217;t use <code>std::random_shuffle()<\/code> to permute containers. (Too easy to misuse; can use <code>std::rand()<\/code> under the hood.)<\/li>\n<li>Don&#8217;t use any kind of clock for a seed.<\/li>\n<li>Don&#8217;t use mod (<code>%<\/code>) to get a random value into a range. It introduces bias.<\/li>\n<li>Don&#8217;t use <code>std::default_random_engine<\/code> &#8211; it&#8217;s probably not the best choice and can vary by implementation.<\/li>\n<\/ul>\n<p>Do this:<\/p>\n<ul>\n<li>Use <code>std::random_device()<\/code> as a source of entropy. It should be the best randomness your OS can supply.<\/li>\n<li>Use <code>std::shuffle()<\/code> to permute containers. Its interface doesn&#8217;t permit misuse like <code>std::random_shuffle()<\/code>.<\/li>\n<li>Use <code>std::mt19937<\/code> (or <code>std::mt19937_64<\/code>) as an RNG engine. (Or consider PCG, but that&#8217;s not standard &#8211; yet.)<\/li>\n<li>Seed the engine with as much seed data as it requires for its internal state (using its <code>state_size<\/code> member), otherwise you&#8217;re throwing away entropy. For <code>std::mt19937<\/code> this is <em>624<\/em> 32-bit values (<em>not<\/em> just a single 32-bit value). Use <code>std::seed_seq<\/code> to help with initialization.<\/li>\n<li>RNG engines (particularly <code>std::mt19937<\/code>) can be expensive to initialize (and have large amounts of internal state), so don&#8217;t put them on the stack unnecessarily. Consider using <code>thread_local<\/code>.<\/li>\n<li>Use <code>std::uniform_int_distribution<\/code> (and the other distributions) to get your random number into the required range. The distributions are carefully crafted to be unbiased (why you shouldn&#8217;t use <code>%<\/code>). Note that they work on closed (inclusive) ranges, not half-open ranges &#8211; otherwise the max value would be unreachable.<\/li>\n<\/ul>\n<p>Wrong:<\/p>\n<pre lang=\"cpp\">\/\/ init RNG\nsrand(time(NULL));\n\n\/\/ get random number\nint n = rand() % 100;\n<\/pre>\n<p>Right:<\/p>\n<pre lang=\"cpp\">\/\/ init RNG\nstd::array&lt;int, std::mt19937::state_size&gt; seed_data;\nstd::random_device r;\nstd::generate_n(seed_data.data(), seed_data.size(), std::ref(r));\nstd::seed_seq seq(std::begin(seed_data), std::end(seed_data));\nstd::mt19937 gen(seq);\n\n\/\/ get random number\nstd::uniform_int_distribution dis(0,99);\nint n = dis(gen);\n<\/pre>\n<p>Edit: Alternatively, <a href=\"http:\/\/www.cs.hmc.edu\/~oneill\/\">Melissa O&#8217;Neill<\/a> has produced <a href=\"http:\/\/www.reddit.com\/r\/cpp\/comments\/34yqxa\/announcing_randutils_a_single_portable\/\">randutils<\/a> which wraps C++11 random number generation in a nice interface, and does the right thing. She knows what she&#8217;s talking about: her work on randomness is worth your time.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>These days, it&#8217;s easy to do the right thing. Don&#8217;t do this: Don&#8217;t use std::rand(). Ever. Don&#8217;t use std::random_shuffle() to permute containers. (Too easy to misuse; can use std::rand() under the hood.) Don&#8217;t use any kind of clock for a seed. Don&#8217;t use mod (%) to get a random value&#8230;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,8],"tags":[],"class_list":["post-1081","post","type-post","status-publish","format-standard","hentry","category-cpp","category-programming"],"_links":{"self":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1081","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1081"}],"version-history":[{"count":7,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1081\/revisions"}],"predecessor-version":[{"id":1793,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1081\/revisions\/1793"}],"wp:attachment":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1081"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1081"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1081"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}