Chris Gordon-Smith wrote:
I have a simulation program that calls the rand() function at various
points while it executes.
For the user interface that displays statistics etc. while the program
runs, I use the Lazarus GUI library, which is based on GTK. Depending on
which libraries I link in, I can have either a GTK1 or GTK2 user
interface.
I'm finding that the simulation behaves differently depending on whether I
link with GTK1 or GTK2.
I think the reason for this may be that one or both of the graphics
libraries (GTK1 / 2) is calling rand(), and they call it in different ways
so that when my own program calls rand() it sees a different sequence of
random numbers depending on how GTK1 / 2 have been calling rand().
Firstly, can anyone comment. Is this likely to be the problem?
Yes, that is the obvious guess.
Secondly, what can I do about it? Can I somehow put together my own
version of rand() that is not disrupted by calls to the random number
generator being made by the graphics software?
It appears that you need a RNG that allows you to create independent
instances so that calls to one RNG object do not affect the sequences
produced by other instances. For the reason you mentioned, rand() will not
be useful here.
RNGs are tricky. You may want to have a look into boost.
If your requirements are really low, or you just want to try out something,
you can use a *very* simple linear congruence RNG like this one:
class SimpleRandomNumberGenerator {
/*
| This is a simple linear congruence random number generator.
| It is *not* meant to be a good generator. (However, the
| multiplier chosen is not too bad.)
|
| The whole point of this class is that you can have several
| independend instances of SimpleRandomNumberGenerator.
*/
private:
static
const unsigned long lower_bound = 0;
static
const unsigned long upper_bound = 0xffffffff;
public:
/*
| The modulus of this generator is 2^32. The multiplier is taken
| from Knuth [line 16 in table 1 of section 3.3.4]. This shift is
| a bad guess.
*/
SimpleRandomNumberGenerator ( unsigned long _seed ) :
seed( _seed )
{}
unsigned long lower ( void ) const {
return ( lower_bound );
}
unsigned long upper ( void ) const {
return ( upper_bound );
}
unsigned long operator() ( void ) {
// return a random number in [lower(),upper()]
seed = ( seed * a + c ) & upper_bound;
return( seed );
}
unsigned long operator() ( unsigned long bound ) {
// return a random number in [0,bound)
unsigned long int_width = upper_bound / bound;
unsigned long max_valid = int_width * bound;
do {
seed = ( seed * a + c ) & upper_bound;
} while ( seed >= max_valid );
return( seed / int_width );
}
private:
mutable unsigned long seed;
static const unsigned long a = 1664525U;
static const unsigned long c = 31415927U;
}; // class SimpleRandomNumberGenerator
You use this like so:
SimpleRandomNumberGenerator RNG ( 1234 );
...
if ( RNG(2) ) { // unbiased coin
}
...
std::random_shuffle( v.begin(), v.end, RNG );
...
g = RNG(200) // random number below 200
and RNG() can be used as a substitute for rand().
Beware that simple linear congruence RNGs have not-quite-that-random lower
order bits. The operator()(bound) tries its best to work around that
limitation. Also, it produces evenly distributed results even if bound is
not a power of 2. As a price it might change the internal state several
times. However, the loop will be traversed at most twice (on the average).
This code at least illustrates how one can go about implementing a RNG that
allows for independent instances each of which keeps its own internal
state. For production code, however, I would recommend using a solution
from boost.
Best
Kai-Uwe Bux