Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Usefulness of `rand()` - or who should call `srand()`?

Tags:

c++

c

random

srand

Background: I use rand(), std::rand(), std::random_shuffle() and other functions in my code for scientific calculations. To be able to reproduce my results, I always explicitly specify the random seed, and set it via srand(). That worked fine until recently, when I figured out that libxml2 would also call srand() lazily on its first usage - which was after my early srand() call.

I filled in a bug report to libxml2 about its srand() call, but I got the answer:

Initialize libxml2 first then. That's a perfectly legal call to be made from a library. You should not expect that nobody else calls srand(), and the man page nowhere states that using srand() multiple time should be avoided

This is actually my question now. If the general policy is that every lib can/should/will call srand(), and I can/might also call it here and there, I don't really see how that can be useful at all. Or how is rand() useful then?

That is why I thought, the general (unwritten) policy is that no lib should ever call srand() and the application should call it only once in the beginning. (Not taking multi-threading into account. I guess in that case, you anyway should use something different.)

I also tried to research a bit which other libraries actually call srand(), but I didn't find any. Are there any?

My current workaround is this ugly code:

{     // On the first call to xmlDictCreate,     // libxml2 will initialize some internal randomize system,     // which calls srand(time(NULL)).     // So, do that first call here now, so that we can use our     // own random seed.     xmlDictPtr p = xmlDictCreate();     xmlDictFree(p); }  srand(my_own_seed); 

Probably the only clean solution would be to not use that at all and only to use my own random generator (maybe via C++11 <random>). But that is not really the question. The question is, who should call srand(), and if everyone does it, how is rand() useful then?

like image 205
Albert Avatar asked Oct 10 '14 07:10

Albert


People also ask

Why do we use Srand?

srand() is used to initialise random number generators. This function gives a starting point for producing the pseudo-random integer series. The argument is passed as a seed for generating a pseudo-random number.

How do you use rand Srand?

How srand() and rand() are related to each other? srand() sets the seed which is used by rand to generate “random” numbers. If you don't call srand before your first call to rand, it's as if you had called srand(1) to set the seed to one. In short, srand() — Set Seed for rand() Function.

What is Srand time NULL ))?

Using. srand(time(NULL)); makes use of the computer's internal clock to control the choice of the seed. Since time is continually changing, the seed is forever changing. Remember, if the seed number remains the same, the sequence of numbers will be repeated for each run of the program.

How do you pick a random number in C++?

One way to generate these numbers in C++ is to use the function rand(). Rand is defined as: #include <cstdlib> int rand(); The rand function takes no arguments and returns an integer that is a pseudo-random number between 0 and RAND_MAX.

What is the difference between Srand and Rand?

srand () sets the seed which is used by rand to generate “random” numbers. If you don’t call srand before your first call to rand, it’s as if you had called srand (1) to set the seed to one. In short, srand () — Set Seed for rand () Function . This article is contributed by Shivam Pradhan (anuj_charm).

What is the use of Rand in C++?

rand () The rand () function is used in C/C++ to generate random numbers in the range [0, RAND_MAX). Note: If random numbers are generated with rand () without first calling srand (), your program will create the same sequence of numbers each time it runs.

What is the range of Rand () and srand () functions in Python?

The function rand () is used to generate the pseudo random number. It returns an integer value and its range is from 0 to rand_max i.e 32767. The function srand () is used to initialize the generated pseudo random number by rand () function.

How does rand random number work?

Random numbers are actually pseudo random. A seed is set first, from which each call of rand gets a random number, and modifies the internal state and this new state is used in the next rand call to get another number.


2 Answers

Use the new <random> header instead. It allows for multiple engine instances, using different algorithms and more importantly for you, independent seeds.

[edit] To answer the "useful" part, rand generates random numbers. That's what it's good for. If you need fine-grained control, including reproducibility, you should not only have a known seed but a known algorithm. srand at best gives you a fixed seed, so that's not a complete solution anyway.

like image 60
MSalters Avatar answered Oct 09 '22 11:10

MSalters


Well, the obvious thing has been stated a few times by others, use the new C++11 generators. I'm restating it for a different reason, though.
You use the output for scientific calculations, and rand usually implements a rather poor generator (in the mean time, many mainstream implementations use MT19937 which apart from bad state recovery isn't so bad, but you have no guarantee for a particular algorithm, and at least one mainstream compiler still uses a really poor LCG).

Don't do scientific calculations with a poor generator. It doesn't really matter if you have things like hyperplanes in your random numbers if you do some silly game shooting little birds on your mobile phone, but it matters big time for scientific simulations. Don't ever use a bad generator. Don't.

Important note: std::random_shuffle (the version with two parameters) may actually call rand, which is a pitfall to be aware of if you're using that one, even if you otherwise use the new C++11 generators found in <random>.

About the actual issue, calling srand twice (or even more often) is no problem. You can in principle call it as often as you want, all it does is change the seed, and consequentially the pseudorandom sequence that follows. I'm wondering why an XML library would want to call it at all, but they're right in their response, it is not illegitimate for them to do it. But it also doesn't matter.
The only important thing to make sure is that either you don't care about getting any particular pseudorandom sequence (that is, any sequence will do, you're not interested in reproducing an exact sequence), or you are the last one to call srand, which will override any prior calls.

That said, implementing your own generator with good statistical properties and a sufficiently long period in 3-5 lines of code isn't all that hard either, with a little care. The main advantage (apart from speed) is that you control exactly where your state is and who modifies it.
It is unlikely that you will ever need periods much longer than 2128 because of the sheer forbidding time to actually consume that many numbers. A 3GHz computer consuming one number every cycle will run for 1021 years on a 2128 period, so there's not much of an issue for humans with average lifespans. Even assuming that the supercomputer you run your simulation on is a trillion times faster, your grand-grand-grand children won't live to see the end of the period.
Insofar, periods like 219937 which current "state of the art" generators deliver are really ridiculous, that's trying to improve the generator at the wrong end if you ask me (it's better to make sure they're statistically firm and that they recover quickly from a worst-case state, etc.). But of course, opinions may differ here.

This site lists a couple of fast generators with implementations. They're xorshift generators combined with an addition or multiplication step and a small (from 2 to 64 machine words) lag, which results in both fast and high quality generators (there's a test suite as well, and the site's author wrote a couple of papers on the subject, too). I'm using a modification of one of these (the 2-word 128-bit version ported to 64-bits, with shift triples modified accordingly) myself.

like image 33
Damon Avatar answered Oct 09 '22 11:10

Damon