views:

474

answers:

5

The code is

return min + static_cast<int>(static_cast<double>(max - min + 1.0) *
  (number / (UINT_MAX + 1.0)));

number is a random number obtained by rand_s. min and max are ints and represent minimum and maximum values (inclusive).

If you provide a solution not using unsigned int as a number, please also explain how to make it be random.

Please do not submit solutions using rand().

+1  A: 

How about Boost:Random

Martin York
Randandandom is even better ;)
VVS
It isn't allowed in some projects.
phjr
A: 

Something like

min + number % (max - min + 1)

Check the end-cases

Andrew Stein
NB. If (max - min + 1) is not an exact multiple of MAX_RAND then the number are not evenly distributed.
Martin York
Agreed. I did presume that max-min is relatively small
Andrew Stein
@Martin York: that's OK, they aren't in the original code, either. And of course there's no way to make them be, short of using multiple inputs to generate multiple outputs,
Steve Jessop
This fails miserably when min is INT_MIN and max is INT_MAX. Then max - min + 1 equals 0, resulting in division by zero.
phjr
Like I said, presume that max - min is small. Say max is 1 and min is 6 for a dice roll...
Andrew Stein
As said in another answer, this is not a good general approach because the low order bits of many RNGs are less random than the high order bits.
Artelius
+3  A: 

@Andrew Stein

In Numerical Recipes in C: The Art of Scientific Computing (William H. Press, Brian P. Flannery, Saul A. Teukolsky, William T. Vetterling; New York: Cambridge University Press, 1992 (2nd ed., p. 277)), the following comments are made:

"If you want to generate a random integer between 1 and 10, you should always do it by using high-order bits, as in

j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));

and never by anything resembling

j = 1 + (rand() % 10);

(which uses lower-order bits)."

From man 3 rand

jk
How about bit-reversing the input and then using the low-order bits ;-)
Steve Jessop
full bit-reversal is slow, he can just switch upper and lower halves of a 32-bit unsigned word w, as in ((w >> 16) | (w << 16))
zvrba
The "don't use low bits" advice, as far as I know, applies mostly to linear congruential generators (such as rand()), where low bits are not very random. rand_s(), from what I understand, is not an LCG, and this doesn't apply.
Chris Jester-Young
Oh, I always assumed it was so that the over-represented outputs were almost-evenly spread through the range, rather than being clustered at the bottom and affecting the expected value...
Steve Jessop
+3  A: 

The static_cast<double> is redundant because the "+1.0"s will cause promotion to double anyway.

Hugh Allen
A: 

You could do the arithmetic in an unsigned long long instead of a double, but only if ULONGLONG_MAX >= UINT_MAX*UINT_MAX, which is probably implementation defined. But if you're worried about that, you'd be worried about potential loss of precision in the original code in the case where (max - min) or RAND_MAX is large.

Whether the long long is actually faster might depend how good your platform's hardware float is. But integer arithmetic arguably is inherently simpler than floating-point.

Steve Jessop