views:

2100

answers:

11

I need to generate random numbers with in specified interval [max,min]

Also the random numbers should be uniformly distributed over interval, not located to particular point

Currenly I am generating as:

for(int i=0;i<6;i++)
{
DWORD random= rand()%(max-min+1) + min;
}

From my tests random numbers are generated around one point only

Example
min= 3604607;
max= 7654607;

Random numbers generated:

3631594
3609293
3630000
3628441
3636376
3621404

Edit (added from answers below): Ok RAND_MAX is 32767. I am on C++ windows platform.. Is there any other method to generate random numbers with uniform distribution?

+2  A: 

If you want numbers to be uniformly distributed over the range, you should break your range up into a number of equal sections that represent the number of points you need. Then get a random number with a min/max for each section.

As another note, you should probably not use rand() as it's not very good at actually generating random numbers. I don't know what platform you're running on, but there is probably a better function you can call like random().

Jason Coco
+2  A: 

Check what RAND_MAX is on your system -- I'm guessing it is only 16 bits, and your range is too big for it.

Beyond that see this discussion on: Generating Random Integers within a Desired Range and the notes on using (or not) the C rand() function.

Rob Walker
Ok RAND_MAX is 32767. I am on C++ windows platform..Is there any other method to generate random numbers with uniform distribution?
Alien01
+5  A: 

If you are concerned about randomness and not about speed, you should use a secure random number generation method. There are several ways to do this... the easiest one being to use OpenSSL's Random Number Generator.

You can also write your own using an encryption algorithm (like AES). By picking a seed and an IV and then continuously re-encrypting the output of the encryption function. Using openssl is easier, but less manly.

SoapBox
I cannot use any third party library?I am restricted to C++ only.
Alien01
Then go the manly route, implement AES or some other encryption algorithm.
SoapBox
RC4 is trivial to code, and random enough for all practical purposes (except WEP, but that's not entirely RC4's fault). I mean it, it's incredibly trivial code. Like, 20 lines or so. The Wikipedia entry has pseudo-code.
Steve Jessop
Why can you not use third party code? If this is a homework question, you should say so, because many people would rather give helpful hints instead of providing complete solutions in this case. If it ain't a homework, go kick the guy who says "no 3rd party code", because he's a moron.
DevSolar
More direct link to the OpenSSL rand() function docs: http://www.openssl.org/docs/crypto/rand.html#
DevSolar
+5  A: 

You should look at RAND_MAX for your particular compiler/environment. I think you would see these results if rand() is producing a random 16-bit number. (you seem to be assuming it will be a 32-bit number).

I can't promise this is the answer, but please post your value of RAND_MAX, and a little more detail on your environment.

abelenky
A: 

Ok RAND_MAX is 32767. I am on C++ windows platform.. Is there any other method to generate random numbers with uniform distribution?

Alien01
See my answer, that's how you would do a uniform distribution.
Jason Coco
I'll edit this into the question text.
Alex B
A: 

By their nature, a small sample of random numbers doesn't have to be uniformly distributed. They're random, after all. I agree that if a random number generator is generating numbers that consistently appear to be grouped, then there is probably something wrong with it.

But keep in mind that randomness isn't necessarily uniform.

Edit: I added "small sample" to clarify.

Kluge
"uniformly distributed" has a well defined meaning, and the standard random generators usually come close.
peterchen
Yes, you are right, random number generators should produce output that *over time* is generally uniform in its distribution. I guess my point is that over a small number of instances (6 as shown in the example) the output won't always be uniform.
Kluge
Kluge is right. Uniform distribution in a small sample indicates that the sample is definitely *not* random.
Bill the Lizard
Bill, it indicates no such thing. Small samples are mostly meaningless, but if the RNG is supposed to be uniform and the output is uniform, why is that any worse than an non-uniform small sample?
Dan Dyer
Significant distributions either way indicate non-randomness: I think Bill just means that 6 equally-spaced results would also be suspect. In the OP, 6 values lie in a range of 32k/4M, or <1% of the desired range. The probability of this being a false positive is too small to argue over.
Steve Jessop
+3  A: 

If RAND_MAX is 32767, you can double the number of bits easily.

int BigRand()
{
    assert(INT_MAX/(RAND_MAX+1) > RAND_MAX);
    return rand() * (RAND_MAX+1) + rand();
}
Mark Ransom
A: 

I just found on net

This should work

DWORD random = ((min) + rand()/(RAND_MAX + 1.0) * ((max) - (min) + 1));

Alien01
Please clarify what you need them for, there are tons of algorithms for PRNG's out there. Also, it would be easier if you edit your main question instead of posting replies.
peterchen
This works best for me...I am able to get better distributed random numbers with this formula..
Alien01
If your range exceeds RAND_MAX, the results may be *won't* be uniform. That is, there are values in the range that won't be represented no matter how many times in call your function.
dmckee
Also, if max and min are both unsigned int, and min is 0, and max is MAX_UINT, then ((max)-(min)+1) will be 0, and the result will be 0 always. Watch out for overflow doing this type of math! As noted by dmckee, this stretches the distribution over destination range, but doesn't guarantee more than RAND_MAX unique values.
jesup
+1  A: 

Solution given by man 3 rand for a number between 1 and 10 inclusive:

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

In your case, it would be:

j = min + (int) ((max-min+1) * (rand() / (RAND_MAX + 1.0)));

Of course this is not perfect randomness or uniformity as some other messages are pointing out, but this is enough for most cases.

calandoa
+12  A: 

Generally, the high bits show a better distribution than the low bits, so the recommended way to generate random numbers of a range for simple purposes is:

((double) rand() / (RAND_MAX+1)) * (max-min+1) + min

Note: make sure RAND_MAX+1 does not overflow! (Thanks Demi)

the division generates a random number from the interval [0, 1), "stretch" this to the required range. Only when max-min+1 gets close to RAND_MAX you need a "BigRand()" function like posted by Mark Ransom.

This also avoids some slicing problems due to the modulo, which can worsen your numbers even more.


The built-in random number generator isn't guaranteed to have a the quality required for statistical simulations. It is ok for numbers to "look random" to a human, but for a serious application, you should take something better - or at least check its properties (uniform distribution is usually good, but values tend to correlate, and the sequence is deterministic.) Knuth has an excellent (if hard to read) treatise on random number generators, and I recently found LFSR to be excellent and darn simple to implement, given its properties are ok for you.

If you want more information, please describe your application, and I/we can dig up some more concrete implementations.

peterchen
BigRand can give better results even when the desired range doesn't exceed RAND_MAX. Consider when RAND_MAX is 32767 and you want 32767 possible values - two of those 32768 random numbers (including zero) are going to map to the same output, and will be twice as likely to occur as the others. Hardly an ideal random property!
Mark Ransom
@Mark: You are right, good example. Still, if that's a real problem, I'd avoid built-in `rand()` completely, since the standard doesn't have any quality guarantees.
peterchen
(RAND_MAX + 1) is a bad idea. This can rollover and give you a negative value. Better to do something like: ((double)RAND_MAX) + 1.0
Demi
good point, Demi
peterchen
+7  A: 

If you are able to use boost, I have had good luck with their random library.

uniform_int should do what you want.

Jeff Thomas
I've done some work on uniform_int with a merseinne twister and unfortunately for certain ranges the values returned by uniform_int are not as uniform as I'd expect. For instance uniform_int<>( 0, 3 ) tends to produce more 0's than 1's or 2's
ScaryAardvark