Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>All the answers so far are mathematically wrong. Returning <code>rand() % N</code> does not uniformly give a number in the range <code>[0, N)</code> unless <code>N</code> divides the length of the interval into which <code>rand()</code> returns (i.e. is a power of 2). Furthermore, one has no idea whether the moduli of <code>rand()</code> are independent: it's possible that they go <code>0, 1, 2, ...</code>, which is uniform but not very random. The only assumption it seems reasonable to make is that <code>rand()</code> puts out a Poisson distribution: any two nonoverlapping subintervals of the same size are equally likely and independent. For a finite set of values, this implies a uniform distribution and also ensures that the values of <code>rand()</code> are nicely scattered.</p> <p>This means that the only correct way of changing the range of <code>rand()</code> is to divide it into boxes; for example, if <code>RAND_MAX == 11</code> and you want a range of <code>1..6</code>, you should assign <code>{0,1}</code> to 1, <code>{2,3}</code> to 2, and so on. These are disjoint, equally-sized intervals and thus are uniformly and independently distributed.</p> <p>The suggestion to use floating-point division is mathematically plausible but suffers from rounding issues in principle. Perhaps <code>double</code> is high-enough precision to make it work; perhaps not. I don't know and I don't want to have to figure it out; in any case, the answer is system-dependent.</p> <p>The correct way is to use integer arithmetic. That is, you want something like the following:</p> <pre><code>#include &lt;stdlib.h&gt; // For random(), RAND_MAX // Assumes 0 &lt;= max &lt;= RAND_MAX // Returns in the closed interval [0, max] long random_at_most(long max) { unsigned long // max &lt;= RAND_MAX &lt; ULONG_MAX, so this is okay. num_bins = (unsigned long) max + 1, num_rand = (unsigned long) RAND_MAX + 1, bin_size = num_rand / num_bins, defect = num_rand % num_bins; long x; do { x = random(); } // This is carefully written not to overflow while (num_rand - defect &lt;= (unsigned long)x); // Truncated division is intentional return x/bin_size; } </code></pre> <p>The loop is necessary to get a perfectly uniform distribution. For example, if you are given random numbers from 0 to 2 and you want only ones from 0 to 1, you just keep pulling until you don't get a 2; it's not hard to check that this gives 0 or 1 with equal probability. This method is also described in the link that nos gave in their answer, though coded differently. I'm using <code>random()</code> rather than <code>rand()</code> as it has a better distribution (as noted by the man page for <code>rand()</code>).</p> <p>If you want to get random values outside the default range <code>[0, RAND_MAX]</code>, then you have to do something tricky. Perhaps the most expedient is to define a function <code>random_extended()</code> that pulls <code>n</code> bits (using <code>random_at_most()</code>) and returns in <code>[0, 2**n)</code>, and then apply <code>random_at_most()</code> with <code>random_extended()</code> in place of <code>random()</code> (and <code>2**n - 1</code> in place of <code>RAND_MAX</code>) to pull a random value less than <code>2**n</code>, assuming you have a numerical type that can hold such a value. Finally, of course, you can get values in <code>[min, max]</code> using <code>min + random_at_most(max - min)</code>, including negative values.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload