• 9
• 11
• 11
• 9
• 20

# how good is rand() ?

This topic is 713 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

how good is rand()  ?

i kind of get the impression it "rolls low" a lot.

i'm using a lerp type operation to map the result of rand() to the desired range, not modulo.

from MSDN:

"The rand function returns a pseudorandom integer in the range 0 to RAND_MAX (32767). "

so it returns 0 thru 32766, but not 32767, right?

EDIT: that doesn't sound right. that's a typo, correct?

it returns 0 to 32768, or 0 thru 32767, right?

Edited by Norman Barrows

##### Share on other sites

Mersenne Twister is good indeed.

I use it in my simulation software. Wikipedia says it's very popular http://en.wikipedia.org/wiki/Mersenne_Twister

Its home site is in Japan

http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html

and it's free for any use since 2001.

(site doesn't allow inline of this url)

Edited by Alberth

##### Share on other sites

rand is well-known to be notoriously bad (it has a long, long, long history spanning several decades and many architectures). Although I believe that glibc even uses MT under the hood (not 100% sure, but I believe so). Microsoft's implementation, although quite bad, is actually not so bad compared to some other historic implementations (I forgot the name, but there was once an implementation where you could basically only use 4 bits of the output...).

I advise against the general trend to just use Mersenne Twister. It is not a bad generator as such, and once upon a time when there was not much around but using rand or using MT, it certainly was the go-to solution, but it is far from being perfect. It goes way overboard for the average programming problem on the one hand side, but fails to deliver on the other end, which is not optimal.

Unless you do some really, really hefty scientific simulations, you do not need the properties that MT guarantees.  Most people (me included) just shrug if they hear 623-dimensional equidistribution. It's as if someone offered me an elephant for free. I have no use for an elephant, so that offer doesn't impress me! I'm not bothered if my random generator shows patterns in 622-dimensional or 570-dimensional space. I'm rarely using more than 4 dimensions for anything, and I think I've never used anything in conjunction with pseudorandom numbers that had more than 8 dimensions.

On the other hand, if you do care about that stuff then you would rather use WELL instead of MT anyway.

But if you are like almost everybody, you can as well use something simpler and more efficient.

There are alternatives which run faster without polluting caches and without using huge state, and which at the same time pass statistical tests slightly better and have way better recovery from bad state (as the classic textbook example, MT fails catastrophically and takes pretty much forever to recover if you should ever be so careless as to initialize it with an all-zero state).

Sebastiano Vigna has a whole collection of very fast very high quality generators that are one or two lines of C code. Most (all?) of them are based on work by Marsaglia, followed by a nonlinear mix step that improves the quality of the generated numbers. For "anything game", these generators are totally suitable, and they use a fraction of the resources.

##### Share on other sites

"The rand function returns a pseudorandom integer in the range 0 to RAND_MAX (32767). "  so it returns 0 thru 32766, but not 32767, right?

Correct.  In modern math notation this type of function works with [0,x)  meaning it includes zero but stops just short of x.  This is also common in many other systems.  Graphics, for example, typically draw segments in the [A,B) form, starting exactly at A and ending the instant before B.

I tried this in VS2015 and it does return RAND_MAX.. is it not supposed to?

#include <iostream>
int main() {
for(int i = 0; i < 200000; ++i) {
int r = rand();
if(r == RAND_MAX)
std::cout << "MAX\n";
else if(r == (RAND_MAX - 1))
std::cout << "ALMOST\n";
else if(r == 0)
std::cout << "ZERO\n";
}
}


##### Share on other sites

"The rand function returns a pseudorandom integer in the range 0 to RAND_MAX (32767). "  so it returns 0 thru 32766, but not 32767, right?

Correct.  In modern math notation this type of function works with [0,x)  meaning it includes zero but stops just short of x.  This is also common in many other systems.  Graphics, for example, typically draw segments in the [A,B) form, starting exactly at A and ending the instant before B.

I tried this in VS2015 and it does return RAND_MAX.. is it not supposed to?

#include <iostream>
int main() {
for(int i = 0; i < 200000; ++i) {
int r = rand();
if(r == RAND_MAX)
std::cout << "MAX\n";
else if(r == (RAND_MAX - 1))
std::cout << "ALMOST\n";
else if(r == 0)
std::cout << "ZERO\n";
}
}


The range for both rand() and the <random> library (at least the uniform integer distributions when comparing with rand) are inclusive at both ends. The range is therefore [0, RAND_MAX], not [0, RAND_MAX). This is different from, for example, iterator ranges in the standard library which are half-open.

##### Share on other sites

Seems that way, yes. I wrote an edit to my earlier post.

When I started writing the edit there were no replies to that on my screen, I just took a long time to review it carefully so I missed the addition.

The language standard as written is ambiguous, at least to me. Given the nature of the standard it is possible there is another note elsewhere about the range, but I didn't see it.