I am trying to get a uniform random number between 0 and 1 in C++ without using boost. I do not want to depend on the library.
Whenever I start my program, I seed with: srand( time(NULL) );
Then I print 8 random numbers. I separate different runs of the program with a blank line:
Random number: 0.226063
Random number: 0.449186
Random number: 0.474514
Random number: 0.160779
Random number: 0.220868
Random number: 0.136685
Random number: 0.260120
Random number: 0.843334
Random number: 0.226181
Random number: 0.422253
Random number: 0.808594
Random number: 0.040531
Random number: 0.212377
Random number: 0.421073
Random number: 0.965790
Random number: 0.026305
Random number: 0.226306
Random number: 0.526858
Random number: 0.898279
Random number: 0.378934
Random number: 0.736653
Random number: 0.924420
Random number: 0.718503
Random number: 0.888140
Random number: 0.226463
Random number: 0.157614
Random number: 0.010386
Random number: 0.551936
Random number: 0.391998
Random number: 0.303603
Random number: 0.659396
Random number: 0.465434
Why is the first number almost exactly the same every time? I don't get it. Should I toss the first number out or something?
Sample code:
#include <iostream>
int main() {
srand( time(NULL) );
printf("%f\n", (float)rand()/RAND_MAX);
printf("%f\n", (float)rand()/RAND_MAX);
printf("%f\n", (float)rand()/RAND_MAX);
printf("%f\n", (float)rand()/RAND_MAX);
printf("%f\n", (float)rand()/RAND_MAX);
printf("%f\n", (float)rand()/RAND_MAX);
printf("%f\n", (float)rand()/RAND_MAX);
printf("%f\n", (float)rand()/RAND_MAX);
}
You can use the standard library, which provides both high-quality PRNG engines as well as the appropriate distribution adapters:
Maybe the delay between program executions is too short, thus the time function may be returning seeds that are too similar to each other.
It is hard to be sure without knowing how the srand function is implemented, but it is a pseudo-random generator, it will output the same sequence for the same seed for multiple executions. Try to feed seeds with a larger delay betweem each other, or add a variable padding to the time returned by the time function, and see if this affects the output enough. However, be aware that they are not real random numbers.
No, don't throw out the first one. That skews the results. The sequence
{1,1,1,1,1,1,1}
is exactly as likely to appear as any other arbitrary seven-number sequence despite the propensity of humans trying to find meaning in everything :-)Trying to fiddle with it because you don't like the sequence makes the random number generation worse, not better.
For what it's worth, you should make sure that your runs are at least a second apart so you don't use the same seed (that doesn't appear to be the case here). Other than that, use the results that the PRNG gives you as-is or find a better generator.
Either you're a statistician/cryptographer where you wouldn't be using a normal random function, or it really doesn't matter! For the vast majority of situations, it's the latter.
If you don't want a fancy one (or one involving a large amount of extra stuff) and you're just not happy with the one provided with your implementation, it's easy to implement one based on the
gcc
version, something like:And keep in mind the initial seed value is calculated on the argument supplied to
srand
with a modulus of231-1
to minimise the sequence having a linear dependence on the initial seed (there's still linearity for the sequence, just not from the initial seed value).The following code may make your life easier if you're just looking for a quick solution without depending on external libraries or spending time implementing the more complex generators:
The following program will actually give you an idea as to what that algorithm will do with small changes to the seed value provided to
mySRand
.It gets the initial seed from
time (NULL)
then shows you what the initial values are out ofmyRand
for twenty sequential seed values, along with the percentage changes.The percentage changes are based on the difference between the current value and the average between the current and the previous so as to hopefully not introduce bias. Sample output is:
so you can see there's actually a large difference in starting values based on initial seeds that are close together.
That's perfectly normal. PRNG's must be warmed up. The number I have in the back of my head is something about 1000. That means, after seeding your PRNG, get 1000 numbers and throw them away.
The reason is how most generators are implemented. They are typically something like
x = a*x+b
, wherea
andb
are constants. So, if you're unlucky, your seeds (which are in your case pretty close!) are chosen so that the first part of the equation does not have much relevance to the outcome (i.e. close to 0 (mod MAX_RAND)). That's why you have to warm up: It irons the similarity of your chosen seeds out. It sounds stupid, but that's how PRNG's work (you might get away with throwing out 50 instead of 1000, YMMV).Btw., using
rand
is a terrible idea in general. Not only that (for reasons that honestly escape me) it is quite slow compared to other PRNG's, also the numbers it generates are quite poor (in terms of entropy, periodicity and so forth). If you don't want to use boost, maybe you can use gsl which has pretty much everything you could need (regarding random numbers).When I slightly tweaked your sample to run when compiled as C (I don't know C++ well enough to fix the compile errors without cursing) I saw nothing but random-looking first lines: