tags:

views:

563

answers:

12
srand(time(null));

printf("%d", rand());

Gives a high-range random number (0-32000ish), but I only need about 0-63 or 0-127, though I'm not sure how to go about it. Any help?

+2  A: 

If you don't overly care about the 'randomness' of the low-order bits, just rand() % HI_VAL.

Also:

(double)rand() / (double)RAND_MAX;  // lazy way to get [0.0, 1.0)
genpfault
So that would give either 0 or 1? Is there anyway I could chain that together and convert the resulting number from binary into decimal? That would add a lot of randomness... I think.
akway
@akway: No. The division gives a floating-point number between 0.0 and 1.0. `(int)(HI_VAL * ( (double)rand() / (double)RAND_MAX ))` generally does what you want.
S.Lott
Tip: Any time you do something to "add" randomness to a pseudo-random number generator, expect a high chance that you're inadvertently subtracting it...or at least not changing it.
Brian
(double)rand() / (double)RAND_MAX gives you a double between zero and one, not either 0 or 1. You can chain these, of sorts, but remember that not all generators work well that way. Some have dependencies between adjacent values.
David Thornley
Oh ok, that makes more sense.
akway
+1  A: 

The naive way to do it is:

int myRand = rand() % 66; // for 0-65

This will likely be a very slightly non-uniform distribution (depending on your maximum value), but it's pretty close.

To explain why it's not quite uniform, consider this very simplified example:
Suppose RAND_MAX is 4 and you want a number from 0-2. The possible values you can get are shown in this table:

rand()   |  rand() % 3
---------+------------
0        |  0
1        |  1
2        |  2
3        |  0

See the problem? If your maximum value is not an even divisor of RAND_MAX, you'll be more likely to choose small values. However, since RAND_MAX is generally 32767, the bias is likely to be small enough to get away with for most purposes.

There are various ways to get around this problem; see here for an explanation of how Java's Random handles it.

Michael Myers
Needs to be rand() % 66 for 0-65....
Reed Copsey
I edited it *twice* in the time it took you guys to leave comments. ;)
Michael Myers
How biased is it?
akway
@akway - it's biased towards low values. Depending on the range, it can be very skewed. See the article I reference in my answer for details on alternatives.
Reed Copsey
From your examples it looks like I could just discard all results that end in 0 and I would be okay... or am I wrong?
akway
@akway: What happens if RAND_MAX is 5 in the example?
Michael Myers
3->3, 4->0? Not sure to be honest.
akway
The % operator gives the remainder. So 3 still yields 0, and 4 yields 1. So 0 and 1 are *both* twice as likely to appear as 2 is.
Michael Myers
+1  A: 

rand() will return numbers between 0 and RAND_MAX, which is at least 32767.

If you want to get a number within a range, you can just use modulo.

int value = rand() % 66; // 0-65

For more accuracy, check out this article. It discusses why modulo is not necessarily good (bad distributions, particularly on the high end), and provides various options.

Reed Copsey
+4  A: 
rand() % number_of_numbers + minimum_number

So, for 0-65:

rand() % 66 + 0

(obviously you can leave the 0 off, but it's there for completeness).

Note that this will bias the randomness slightly, but probably not anything to be concerned about if you're not doing something particularly sensitive.

Tyler McHenry
number_of_numbers+1. Your code will give 0-64.
Fred Larson
no, it's still number_of_numbers, but the number of numbers in the inclusive range 0-65 is 66 not 65.
Tyler McHenry
I think that said "rand() % 65 + 0" when I posted my comment. It looks right now.
Fred Larson
@Tyler, you're right. 0-65 would be 66 numbers.
Fred Larson
It did say that. I meant that I was mistaken about the number I wrote in the second code snippet, but not mistaken about the name I gave to the variable in the first code snippet.
Tyler McHenry
Modulo relies on the low-order bits which aren't as random as the high-order bits. Convert to float and multiply works better.
S.Lott
As I (and others) mentioned, there is a bias. But this bias is usually insignificant, especially if the range of numbers you are generating within is significantly smaller than RAND_MAX.
Tyler McHenry
Also, since RAND_MAX is almost definitely 2^n-1, if you are always looking for a range that is a power of two (as in both of the OPs examples), there is no bias at all.
Brian Postow
Unless the low-order bits are less random than the high-order bits. Then there would still be a bias (or perhaps a correlation), even when taking modulo a power of 2, by definition of "less random".
Steve Jessop
The low-order bits ARE less random. Further, the smaller the value of of `number_of_numbers`, the more apparent the bias is. Nothing to do with RAND_MAX. If `number_of_numbers` is 2, for example, you'll see the bias in the lowest-order bit.
S.Lott
@S.Lott: is `rand()` guaranteed by the standard to be implemented such that the low-order bits are less random, or is it merely convention?
Steve Jessop
Wait, so it's not that the lower order bits are less random because when you use mod, you end up with some remainder, and 0-R get an extra value going to them? The algorithm itself is more biased in thelower bits? You'd think that they could fix that by flipping the number before returning it or something...
Brian Postow
+2  A: 

Updated to not use a #define

double RAND(double min, double max)
{
    return (double)rand()/(double)RAND_MAX * (max - min) + min;
}
Mark Synowiec
bad idea, due to all the caveats of macros. That macro fails in a number of cases because the arguments are not properly parenthesized, and even if you did do so properly, it would still evaluate the min argument twice, which would be bad if min were a function with side-effects.
Tyler McHenry
Lose the macro approach and convert to double. rand()/RAND_MAX is normally 0.
David Thornley
A: 

Or you can use this:

rand() / RAND_MAX * 65

But I'm not sure if it's the most random or fastest of all the answers here.

Petruza
Won't this always give 0?
Brian
@Brian You can solve that problem with (rand() * 1.0)/RAND_MAX * 65, but still...
Brian Postow
+3  A: 

Taking the modulo of the result, as the other posters have asserted will give you something that's nearly random, but not perfectly so.

Consider this extreme example, suppose you wanted to simulate a coin toss, returning either 0 or 1. You might do this:

isHeads = ( rand() % 2 ) == 1;

Looks harmless enough, right? Suppose that RAND_MAX is only 3. It's much higher of course, but the point here is that there's a bias when you use a modulus that doesn't evenly divide RAND_MAX. If you want high quality random numbers, you're going to have a problem.

Consider my example. The possible outcomes are:

rand()  freq. rand() % 2
0       1/3   0
1       1/3   1
2       1/3   0

Hence, "tails" will happen twice as often as "heads"!

Mr. Atwood discusses this matter in this Coding Horror Article

Bob Kaufman
So a better solution is... ?
Sean Bright
There *is* a better answer. I'm investigating now. I think that Mr. Atwood discussed this in Coding Horror a year or so back.
Bob Kaufman
Better options here: http://www.azillionmonkeys.com/qed/random.html
Reed Copsey
@Sean: Store value of rand() in a temporary value. If it's high enough to have be in the error range, reroll. For the example mmyers gives, you would reroll if rand() is 3.
Brian
I wasn't asking for me, but thanks for the clarification.
Sean Bright
The better solution is if(rand() > .5) return 1; else return 0;
James
A better solution is here: http://stackoverflow.com/questions/137783/given-a-function-which-produces-a-random-integer-in-the-range-1-to-5-write-a-fun. It was there the last time akway asked about random number generation, and it will still be there the next time someone asks this exact question or one which is mathematically equivalent ;-)
Steve Jessop
@James: that returns 1 with probability RAND_MAX/(RAND_MAX+1), and 0 with probability 1/(RAND_MAX+1). Not sure what that's supposed to achieve.
Steve Jessop
A: 

I think the following does it semi right. It's been awhile since I've touched C. The idea is to use division since modulus doesn't always give random results. I added 1 to RAND_MAX since there are that many possible values coming from rand including 0. And since the range is also 0 inclusive, I added 1 there too. I think the math is arranged correctly avoid integer math problems.

#define MK_DIVISOR(max) ((int)((unsigned int)RAND_MAX+1/(max+1)))

num = rand()/MK_DIVISOR(65);
+5  A: 

check here

http://c-faq.com/lib/randrange.html

For any of these techniques, it's straightforward to shift the range, if necessary; numbers in the range [M, N] could be generated with something like

M + rand() / (RAND_MAX / (N - M + 1) + 1)
tr3
You want one of those 1s to be 1.0 to ensure a float, otherwise you just get 0 + M...
Brian Postow
+2  A: 
double scale = 1.0 / ((double) RAND_MAX + 1.0);
int min, max;
...
rval = (int)(rand() * scale * (max - min + 1) + min);
John Bode
+1  A: 

As others have noted, simply using a modulus will skew the probabilities for individual numbers so that smaller numbers are preferred.

A very ingenious and good solution to that problem is used in Java's java.util.Random class:

public int nextInt(int n) {
    if (n <= 0)
        throw new IllegalArgumentException("n must be positive");

    if ((n & -n) == n)  // i.e., n is a power of 2
        return (int)((n * (long)next(31)) >> 31);

    int bits, val;
    do {
        bits = next(31);
        val = bits % n;
    } while (bits - val + (n-1) < 0);
    return val;
}

It took me a while to understand why it works and I leave that as an exercise for the reader but it's a pretty concise solution which will ensure that numbers have equal probabilities.

The important part in that piece of code is the condition for the while loop, which rejects numbers that fall in the range of numbers which otherwise would result in an uneven distribution.

Joey
A: 

if you care about the quality of your random numbers don't use rand()

use some other prng like http://en.wikipedia.org/wiki/Mersenne_twister or one of the other high quality prng's out there

then just go with the modulus.

Spudd86