473,486 Members | 1,733 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Problem using rand() function

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?

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?
--
Chris Gordon-Smith
London
http://www.simsoup.info

Oct 9 '05 #1
7 3227
"Chris Gordon-Smith" <us*********@my.homepage> wrote in message
news:3q************@individual.net...
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?

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?
--
Chris Gordon-Smith
London
http://www.simsoup.info


I don't know why you are having this problem, but it is never a bad idea to
use a good third party number generator rather than rand(). I suggest you
look at www.boost.org for better alternatives.

--
Cy
http://home.rochester.rr.com/cyhome/
Oct 9 '05 #2
Cy Edmunds wrote:

I don't know why you are having this problem, but it is never a bad idea
to use a good third party number generator rather than rand(). I suggest
you look at www.boost.org for better alternatives.


That's certainly an option. My initial thought however is that my
requirement is very simple and I'm reluctant to start using another fairly
sophisticated library (in addition to the STL).

This is partly because it may be a sledgehammer to crack a nut, and partly
because the Boost licence is not the same as the GPL, so that it will
complicate things when I release my code under the GPL.

--
Chris Gordon-Smith
London
http://www.simsoup.info

Oct 9 '05 #3
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
Oct 9 '05 #4
Kai-Uwe Bux wrote:
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.
*/

[snip]
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.
instances.

Best

Kai-Uwe Bux


Thanks for this.

How about this as an alternative:-

Create a class that has an internal cache of random numbers. Initialise the
cache at construction time by calling rand() repeatedly. Then use a class
method to supply random numbers as and when they are required. When the
last random number in the cache is reached, re-initialise the cache using
the last random number in the cache as the seed for srand(seed).

I think that this approach should enable my simulation code to be isolated
from the effects of other parts of the program (eg library code) calling
rand(), and it does not need a new random number generator to be
implemented.

--
Chris Gordon-Smith
London
http://www.simsoup.info

Oct 9 '05 #5
Chris Gordon-Smith wrote:
[snip]
How about this as an alternative:-

Create a class that has an internal cache of random numbers. Initialise
the cache at construction time by calling rand() repeatedly. Then use a
class method to supply random numbers as and when they are required. When
the last random number in the cache is reached, re-initialise the cache
using the last random number in the cache as the seed for srand(seed).

I think that this approach should enable my simulation code to be isolated
from the effects of other parts of the program (eg library code) calling
rand(), and it does not need a new random number generator to be
implemented.


The rule of thumb is to seed once and only once.

Therefore, I would be worried about the quality of the RNG resulting from
your method. Let me illustrate this using the period as a rough measure of
quality. Assuming that your library comes with a good RNG, its internal
state is very likely much more than just some 32 bits from a seed. Since
the internal state is finite, the sequence of random number eventually will
cycle. The internal state can be considered as the current position within
that cycle. What you suggest is to reseed periodically. Now, you construct
a new internal state from the 32-bit seed (I am assuming here that unsigned
long is 32 bits, but in any case it is probably much less than the internal
state of your libraries RNG). That means that at the reseeding points not
all possible positions in the cycle are possible targets for your jump.
Thus, your operation will very likely reduce the period of the RNG quite a
bit. I would guess you ca get at most a period of length:

cache_size * 2^bitlength(seed)

This period is very likely much smaller than the original period. And, the
actual period you get could be much smaller than the upper bound given
above.

Also, keep in mind D. Knuth's warning: "... random number should not be
generated with a method chosen at random. Some theory should be used." Very
likely, the RNG in your library was designed using some reasonable
mathematics to make sure that the results are decent. Your proposed method
will break the theory and can result in poor quality. My understanding is
that examples of such side-effects abound.

For more qualified answers, you might try:

sci.crypt.random-numbers

or some other more appropriate source.
Best

Kai-Uwe Bux

ps.: I still think you would be better off looking into boost.
Oct 9 '05 #6
Kai-Uwe Bux wrote:
Chris Gordon-Smith wrote:
[snip]
How about this as an alternative:-

Create a class that has an internal cache of random numbers. Initialise
the cache at construction time by calling rand() repeatedly. Then use a
class method to supply random numbers as and when they are required. When
the last random number in the cache is reached, re-initialise the cache
using the last random number in the cache as the seed for srand(seed).

I think that this approach should enable my simulation code to be
isolated from the effects of other parts of the program (eg library code)
calling rand(), and it does not need a new random number generator to be
implemented.


The rule of thumb is to seed once and only once.

Therefore, I would be worried about the quality of the RNG resulting from
your method. Let me illustrate this using the period as a rough measure of
quality. Assuming that your library comes with a good RNG, its internal
state is very likely much more than just some 32 bits from a seed. Since
the internal state is finite, the sequence of random number eventually
will cycle. The internal state can be considered as the current position
within that cycle. What you suggest is to reseed periodically. Now, you
construct a new internal state from the 32-bit seed (I am assuming here
that unsigned long is 32 bits, but in any case it is probably much less
than the internal state of your libraries RNG). That means that at the
reseeding points not all possible positions in the cycle are possible
targets for your jump. Thus, your operation will very likely reduce the
period of the RNG quite a bit. I would guess you ca get at most a period
of length:

cache_size * 2^bitlength(seed)

This period is very likely much smaller than the original period. And, the
actual period you get could be much smaller than the upper bound given
above.

Also, keep in mind D. Knuth's warning: "... random number should not be
generated with a method chosen at random. Some theory should be used."
Very likely, the RNG in your library was designed using some reasonable
mathematics to make sure that the results are decent. Your proposed method
will break the theory and can result in poor quality. My understanding is
that examples of such side-effects abound.

For more qualified answers, you might try:

sci.crypt.random-numbers

or some other more appropriate source.
Best

Kai-Uwe Bux

ps.: I still think you would be better off looking into boost.


Thanks for this comprehensive answer. Despite my reluctance to start using a
new library, I suspect that you and Cy Edmunds are probably right. If the
cycle time is at the theoretical maximum you mention above that is probably
good enough for my purposes. The worry is that it could perhaps be much
less.
--
Chris Gordon-Smith
London
http://www.simsoup.info

Oct 9 '05 #7
Chris Gordon-Smith wrote:
Kai-Uwe Bux wrote:
Chris Gordon-Smith wrote:
[snip]
How about this as an alternative:-

Create a class that has an internal cache of random numbers. Initialise
the cache at construction time by calling rand() repeatedly. Then use a
class method to supply random numbers as and when they are required.
When the last random number in the cache is reached, re-initialise the
cache using the last random number in the cache as the seed for
srand(seed).

I think that this approach should enable my simulation code to be
isolated from the effects of other parts of the program (eg library
code) calling rand(), and it does not need a new random number generator
to be implemented.


The rule of thumb is to seed once and only once.

Therefore, I would be worried about the quality of the RNG resulting from
your method. Let me illustrate this using the period as a rough measure
of quality. Assuming that your library comes with a good RNG, its
internal state is very likely much more than just some 32 bits from a
seed. Since the internal state is finite, the sequence of random number
eventually will cycle. The internal state can be considered as the
current position within that cycle. What you suggest is to reseed
periodically. Now, you construct a new internal state from the 32-bit
seed (I am assuming here that unsigned long is 32 bits, but in any case
it is probably much less than the internal state of your libraries RNG).
That means that at the reseeding points not all possible positions in the
cycle are possible targets for your jump. Thus, your operation will very
likely reduce the period of the RNG quite a bit. I would guess you ca get
at most a period of length:

cache_size * 2^bitlength(seed)

This period is very likely much smaller than the original period. And,
the actual period you get could be much smaller than the upper bound
given above.

Also, keep in mind D. Knuth's warning: "... random number should not be
generated with a method chosen at random. Some theory should be used."
Very likely, the RNG in your library was designed using some reasonable
mathematics to make sure that the results are decent. Your proposed
method will break the theory and can result in poor quality. My
understanding is that examples of such side-effects abound.

For more qualified answers, you might try:

sci.crypt.random-numbers

or some other more appropriate source.
Best

Kai-Uwe Bux

ps.: I still think you would be better off looking into boost.


Thanks for this comprehensive answer. Despite my reluctance to start using
a new library, I suspect that you and Cy Edmunds are probably right. If
the cycle time is at the theoretical maximum you mention above that is
probably good enough for my purposes. The worry is that it could perhaps
be much less.


I've now implemented my own version of rand(), based on the idea of holding
a cache of 10,000 random numbers as described above.

I've tested it by calling it one thousand million times and writing out the
value of the random number taken from the cache whenever it lies in the
range 100000000 to 100000050.

I have included the output below. As you can see, the sequence repeats
itself four times, which means that the sequence repeats roughly every 250
million calls to my random function.

This is good enough for my purposes.

Current_Seq_Val = 100000028
Current_Seq_Val = 100000026
Current_Seq_Val = 100000038
Current_Seq_Val = 100000034
Current_Seq_Val = 100000003
Current_Seq_Val = 100000003
Current_Seq_Val = 100000028
Current_Seq_Val = 100000026
Current_Seq_Val = 100000038
Current_Seq_Val = 100000034
Current_Seq_Val = 100000003
Current_Seq_Val = 100000003
Current_Seq_Val = 100000028
Current_Seq_Val = 100000026
Current_Seq_Val = 100000038
Current_Seq_Val = 100000034
Current_Seq_Val = 100000003
Current_Seq_Val = 100000003
Current_Seq_Val = 100000028
Current_Seq_Val = 100000026
Current_Seq_Val = 100000038
Current_Seq_Val = 100000034
Current_Seq_Val = 100000003
Current_Seq_Val = 100000003
Current_Seq_Val = 100000028
Current_Seq_Val = 100000026
Current_Seq_Val = 100000038
--
Chris Gordon-Smith
London
http://www.simsoup.info

Oct 11 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
10717
by: August1 | last post by:
A handful of articles have been posted requesting information on how to use these functions in addition to the time() function as the seed to generate unique groups (sets) of numbers - each group...
10
1380
by: sam | last post by:
hi, i am new to C/C++ and have just finished a program based on the UK national lottery, where you enter 6 numbers, six are generated by the computer and there are appropriate messages and a...
4
2232
by: Andre Paim Lemos | last post by:
Hi, I'm having some compiler problems when I try to use make_heap(), push_heap() and pop_heap(). I am compiling my code on gcc version 3.3.1 (SuSE Linux). I am using the heap related methods to...
41
3012
by: AngleWyrm | last post by:
I have created a new container class, called the hat. It provides random selection of user objects, both with and without replacement, with non-uniform probabilities. Uniform probabilities are a...
6
1758
by: Sen-Lung Chen | last post by:
Dear All: I have a question about this below function.The purpose of this function is to generate one number between a and b. -------------------------- int gennum(int a, int b) {...
7
2539
by: Fernando Barsoba | last post by:
Hi, After following the advice received in this list, I have isolated the memory leak problem I am having. I am also using MEMWATCH and I think it is working properly. The program does some...
52
5305
by: celerysoup16 | last post by:
I've written this coin toss program, and can't figure out why it isn't giving accurate results... cheers, Ben #include <stdlib.h> #include <stdio.h> #define H 1 #define T 0 #define SENTINEL...
10
2994
by: Rafael Cunha de Almeida | last post by:
Hi, I've found several sites on google telling me that I shouldn't use rand() % range+1 and I should, instead, use something like: lowest+int(range*rand()/(RAND_MAX + 1.0))
10
7820
by: jeddiki | last post by:
Hi, I have a captcha script which should pick up a background image and add some random letters to it and re-display This is the part of the form that the captcha image is part of: <span...
0
7094
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
6964
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7123
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7173
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
4863
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4559
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3066
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3070
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
259
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.