Creating two random arrays
-
This bug took me ages to find. I create several instances of a class that includes a random path class that specifies the path the object should follow on screen. Trouble is, every instance of the object follows the same random path. Pretty obvious, I thought; each instance of the class pointed at the same path object - somewhere I was overwriting the reference. This was sort of confirmed when I stuck a breakpoint in the constructor - they were clearly created pointing at different paths. I just couldn't see where it was being overwritten. It wasn't. I declared Random myRand in the constructor itself. This uses the system clock as a seed. When the program was running it was fast enough to use the same time as the seed in every new random path; so they were all different paths but with the same values. If I breakpointed in the constructor, the time was different and hence the random path was different. I moved Random myRand up a few lines and the problem disappeared. Peter Webb
-
This bug took me ages to find. I create several instances of a class that includes a random path class that specifies the path the object should follow on screen. Trouble is, every instance of the object follows the same random path. Pretty obvious, I thought; each instance of the class pointed at the same path object - somewhere I was overwriting the reference. This was sort of confirmed when I stuck a breakpoint in the constructor - they were clearly created pointing at different paths. I just couldn't see where it was being overwritten. It wasn't. I declared Random myRand in the constructor itself. This uses the system clock as a seed. When the program was running it was fast enough to use the same time as the seed in every new random path; so they were all different paths but with the same values. If I breakpointed in the constructor, the time was different and hence the random path was different. I moved Random myRand up a few lines and the problem disappeared. Peter Webb
Peter Webb wrote:
Trouble is, every instance of the object follows the same random path.
Yeah, we just had a discussion about getting the Same Random Numbers[^] from two different calls. I pointed out why it is a bad idea to have two separate random number generators. From the original post:
Robert C. Cartaino:
Random number generators use some formula to generate a sequence numbers that provide the appearance of randomness with a good distribution (i.e. pseudorandom). As you found out, a random number generator starting with the same seed will always produce the same sequence of numbers. Even with different seeds, there is a maximum length before the sequence begins to repeat (yes, it is a very long time but...). If you run two instances of the same formula with different entry points (seeds) in parallel, there is always a possibility that they are running sufficiently close in the sequence that the distribution between the two sets of numbers is no longer sufficiently random. Why mess with it? Just use one random number generator.
In C#, I always instantiate Random() using
static Random randomNumber = new Random();
outside of any class. I guess if you want to stay a little more object oriented, you could use a Singleton or a Factory pattern. Enjoy, Robert C. Cartaino -
Peter Webb wrote:
Trouble is, every instance of the object follows the same random path.
Yeah, we just had a discussion about getting the Same Random Numbers[^] from two different calls. I pointed out why it is a bad idea to have two separate random number generators. From the original post:
Robert C. Cartaino:
Random number generators use some formula to generate a sequence numbers that provide the appearance of randomness with a good distribution (i.e. pseudorandom). As you found out, a random number generator starting with the same seed will always produce the same sequence of numbers. Even with different seeds, there is a maximum length before the sequence begins to repeat (yes, it is a very long time but...). If you run two instances of the same formula with different entry points (seeds) in parallel, there is always a possibility that they are running sufficiently close in the sequence that the distribution between the two sets of numbers is no longer sufficiently random. Why mess with it? Just use one random number generator.
In C#, I always instantiate Random() using
static Random randomNumber = new Random();
outside of any class. I guess if you want to stay a little more object oriented, you could use a Singleton or a Factory pattern. Enjoy, Robert C. CartainoIndeed. I wrote a static class to house my one instance of Random; I guess that qualifies as Singleton.
-
Peter Webb wrote:
Trouble is, every instance of the object follows the same random path.
Yeah, we just had a discussion about getting the Same Random Numbers[^] from two different calls. I pointed out why it is a bad idea to have two separate random number generators. From the original post:
Robert C. Cartaino:
Random number generators use some formula to generate a sequence numbers that provide the appearance of randomness with a good distribution (i.e. pseudorandom). As you found out, a random number generator starting with the same seed will always produce the same sequence of numbers. Even with different seeds, there is a maximum length before the sequence begins to repeat (yes, it is a very long time but...). If you run two instances of the same formula with different entry points (seeds) in parallel, there is always a possibility that they are running sufficiently close in the sequence that the distribution between the two sets of numbers is no longer sufficiently random. Why mess with it? Just use one random number generator.
In C#, I always instantiate Random() using
static Random randomNumber = new Random();
outside of any class. I guess if you want to stay a little more object oriented, you could use a Singleton or a Factory pattern. Enjoy, Robert C. CartainoRobert.C.Cartaino wrote:
I pointed out why it is a bad idea to have two separate random number generators.
While different applications will have different requirements, I would suggest that having separate seeded random number generators is generally the right approach, though seeding each one with the clock is probably a bad idea. I would suggest that a better approach would be to have a main seed generator which can be initialized with either a hash of the clock and some other stuff, or a preloaded constant; during debugging and testing, the initialization values should be logged. Each object that will need a sequence of random numbers should initialize its own seed with a deterministic hash of the main generator and some other values that will be predictable and reproduceable, but different for each object. If the hash functions are sufficiently long and of good quality, then if the clock and other values used at initialization are unknown, the results will be indistinguishable from random. On the other hand, if some bizarre one-in-a-million behavior is observed, it will be possible to reproduce it by specifying one seed. Note that using separate random number generators in different objects may help minimize timing interactions that could result if one generator was used to supply "random" numbers to multiple threads. It won't eliminate all such interactions, but it will likely make them more manageable.
-
Robert.C.Cartaino wrote:
I pointed out why it is a bad idea to have two separate random number generators.
While different applications will have different requirements, I would suggest that having separate seeded random number generators is generally the right approach, though seeding each one with the clock is probably a bad idea. I would suggest that a better approach would be to have a main seed generator which can be initialized with either a hash of the clock and some other stuff, or a preloaded constant; during debugging and testing, the initialization values should be logged. Each object that will need a sequence of random numbers should initialize its own seed with a deterministic hash of the main generator and some other values that will be predictable and reproduceable, but different for each object. If the hash functions are sufficiently long and of good quality, then if the clock and other values used at initialization are unknown, the results will be indistinguishable from random. On the other hand, if some bizarre one-in-a-million behavior is observed, it will be possible to reproduce it by specifying one seed. Note that using separate random number generators in different objects may help minimize timing interactions that could result if one generator was used to supply "random" numbers to multiple threads. It won't eliminate all such interactions, but it will likely make them more manageable.
I don't know the details of the random number algorithms, but might it be convenient/adequate to use the clock as the seed for the first generator, and a random value from that generator for the seed of the second clock?
-
Indeed. I wrote a static class to house my one instance of Random; I guess that qualifies as Singleton.
AFAIK, technically not. But it maybe used for the same purpose. :)
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
I don't know the details of the random number algorithms, but might it be convenient/adequate to use the clock as the seed for the first generator, and a random value from that generator for the seed of the second clock?
-
This bug took me ages to find. I create several instances of a class that includes a random path class that specifies the path the object should follow on screen. Trouble is, every instance of the object follows the same random path. Pretty obvious, I thought; each instance of the class pointed at the same path object - somewhere I was overwriting the reference. This was sort of confirmed when I stuck a breakpoint in the constructor - they were clearly created pointing at different paths. I just couldn't see where it was being overwritten. It wasn't. I declared Random myRand in the constructor itself. This uses the system clock as a seed. When the program was running it was fast enough to use the same time as the seed in every new random path; so they were all different paths but with the same values. If I breakpointed in the constructor, the time was different and hence the random path was different. I moved Random myRand up a few lines and the problem disappeared. Peter Webb
Peter Webb wrote:
moved Random myRand up a few lines and the problem disappeared.
Bottom line is to choose wisely where to put the seed in.
"The clue train passed his station without stopping." - John Simmons / outlaw programmer "Real programmers just throw a bunch of 1s and 0s at the computer to see what sticks" - Pete O'Hanlon
-
AFAIK, technically not. But it maybe used for the same purpose. :)
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles]...and there's a whole school of thought that Singletons are evil... i.e. they are just glorified, object-oriented window dressing posing as an excuse to use global variables again.
-
nope. RNGs use the last value they generated to seed the next value.
Today's lesson is brought to you by the word "niggardly". Remember kids, don't attribute to racism what can be explained by Scandinavian language roots. -- Robert Royall
Ahh right, makes sense :doh:
-
Robert.C.Cartaino wrote:
I pointed out why it is a bad idea to have two separate random number generators.
While different applications will have different requirements, I would suggest that having separate seeded random number generators is generally the right approach, though seeding each one with the clock is probably a bad idea. I would suggest that a better approach would be to have a main seed generator which can be initialized with either a hash of the clock and some other stuff, or a preloaded constant; during debugging and testing, the initialization values should be logged. Each object that will need a sequence of random numbers should initialize its own seed with a deterministic hash of the main generator and some other values that will be predictable and reproduceable, but different for each object. If the hash functions are sufficiently long and of good quality, then if the clock and other values used at initialization are unknown, the results will be indistinguishable from random. On the other hand, if some bizarre one-in-a-million behavior is observed, it will be possible to reproduce it by specifying one seed. Note that using separate random number generators in different objects may help minimize timing interactions that could result if one generator was used to supply "random" numbers to multiple threads. It won't eliminate all such interactions, but it will likely make them more manageable.
Have a look at the C run-time library source code sometime. There is one seed value for each thread and it is held in the _tiddata structure. Also - the seed is an unsigned long but the rand() function returns a value less than 32767 (RAND_MAX.) Of course, there are alternative RNG libraries available - that is just what visual studio's C RTL does.
-
...and there's a whole school of thought that Singletons are evil... i.e. they are just glorified, object-oriented window dressing posing as an excuse to use global variables again.
-
This bug took me ages to find. I create several instances of a class that includes a random path class that specifies the path the object should follow on screen. Trouble is, every instance of the object follows the same random path. Pretty obvious, I thought; each instance of the class pointed at the same path object - somewhere I was overwriting the reference. This was sort of confirmed when I stuck a breakpoint in the constructor - they were clearly created pointing at different paths. I just couldn't see where it was being overwritten. It wasn't. I declared Random myRand in the constructor itself. This uses the system clock as a seed. When the program was running it was fast enough to use the same time as the seed in every new random path; so they were all different paths but with the same values. If I breakpointed in the constructor, the time was different and hence the random path was different. I moved Random myRand up a few lines and the problem disappeared. Peter Webb
This behavior of random number generators can also be benificial. A friend is working on an online game and needs a large map of solar systems with planets and moons. He already had code to generate the solar systems. But instead of generating the systems and then storing them in a file or in a database, we did this: The map consists of fields, each with a certain chance of containing a solar system. When details of a field are needed, we seeded a random number generator with the coordinates of the field. Then we used the random number generator to determine the presence of the solar system and, if one was there, created it on the fly with the existing code. The coordinates (x and y) were normal 32 bit integers, so the map contained roughly 4000.000.000 ^2 fields with a chance of 10% of a solar system for each field. This way the game has more unique solar systems than the real galaxy. By seeding the random number generator with the coordinates it also was ensured that the system always was generated the same way. File size or space in the database: 0 The downside is, that you don't have much influence on the appearance of the generated map. You can tweak the seeds of the random number generator a little to change the general result, but that's all.
A while ago he asked me what he should have printed on my business cards. I said 'Wizard'. I read books which nobody else understand. Then I do something which nobody understands. After that the computer does something which nobody understands. When asked, I say things about the results which nobody understand. But everybody expects miracles from me on a regular basis. Looks to me like the classical definition of a wizard.
-
This behavior of random number generators can also be benificial. A friend is working on an online game and needs a large map of solar systems with planets and moons. He already had code to generate the solar systems. But instead of generating the systems and then storing them in a file or in a database, we did this: The map consists of fields, each with a certain chance of containing a solar system. When details of a field are needed, we seeded a random number generator with the coordinates of the field. Then we used the random number generator to determine the presence of the solar system and, if one was there, created it on the fly with the existing code. The coordinates (x and y) were normal 32 bit integers, so the map contained roughly 4000.000.000 ^2 fields with a chance of 10% of a solar system for each field. This way the game has more unique solar systems than the real galaxy. By seeding the random number generator with the coordinates it also was ensured that the system always was generated the same way. File size or space in the database: 0 The downside is, that you don't have much influence on the appearance of the generated map. You can tweak the seeds of the random number generator a little to change the general result, but that's all.
A while ago he asked me what he should have printed on my business cards. I said 'Wizard'. I read books which nobody else understand. Then I do something which nobody understands. After that the computer does something which nobody understands. When asked, I say things about the results which nobody understand. But everybody expects miracles from me on a regular basis. Looks to me like the classical definition of a wizard.
CDP1802 wrote:
The coordinates (x and y) were normal 32 bit integers, so the map contained roughly 4000.000.000 ^2 fields with a chance of 10% of a solar system for each field. This way the game has more unique solar systems than the real galaxy. By seeding the random number generator with the coordinates it also was ensured that the system always was generated the same way. File size or space in the database: 0
:cool:
Today's lesson is brought to you by the word "niggardly". Remember kids, don't attribute to racism what can be explained by Scandinavian language roots. -- Robert Royall
-
This bug took me ages to find. I create several instances of a class that includes a random path class that specifies the path the object should follow on screen. Trouble is, every instance of the object follows the same random path. Pretty obvious, I thought; each instance of the class pointed at the same path object - somewhere I was overwriting the reference. This was sort of confirmed when I stuck a breakpoint in the constructor - they were clearly created pointing at different paths. I just couldn't see where it was being overwritten. It wasn't. I declared Random myRand in the constructor itself. This uses the system clock as a seed. When the program was running it was fast enough to use the same time as the seed in every new random path; so they were all different paths but with the same values. If I breakpointed in the constructor, the time was different and hence the random path was different. I moved Random myRand up a few lines and the problem disappeared. Peter Webb
This issue is interesting since one can not assume that different instruction move forward in time even though they do occur one after the other. However the ever going argument about singletons is annoying and consumed enough time. I would use a static random in the default constructor and have an override that accepts a random for later use (and anti singleton whiners). A good singleton implementation is to create a a static constructor (in this case you can make a static readonly member and solve it). My opinion about singletons: I would like to see an application written by one of the "anti singleton" people and I assure you that they have problems, OO issues and other static / non static junk yards that create a problem much much larger than singletons and require years of refactoring. Everybody have problematic and non harmonic code you just need minimize it to keep it contained.
Natza Mitzi
-
This issue is interesting since one can not assume that different instruction move forward in time even though they do occur one after the other. However the ever going argument about singletons is annoying and consumed enough time. I would use a static random in the default constructor and have an override that accepts a random for later use (and anti singleton whiners). A good singleton implementation is to create a a static constructor (in this case you can make a static readonly member and solve it). My opinion about singletons: I would like to see an application written by one of the "anti singleton" people and I assure you that they have problems, OO issues and other static / non static junk yards that create a problem much much larger than singletons and require years of refactoring. Everybody have problematic and non harmonic code you just need minimize it to keep it contained.
Natza Mitzi
I often use singletons and have made good experiences with them. Treating things like religious dogmas never is useful. Everything can be beneficial, just as everything can be misused. Frequently I use Singletons for objects which may be needed anywhere at any time in an application. For example I always have an object which processes and logs exceptions. Passing a reference to this object to each and every function or creating and destroying instances all over the code would be much more of an issue than the Singleton could ever be. Only few things offer only disadvantages, just as few only offer advantages without any 'unless' attached. So it would be better to replace dogmatic do this and don't do that with good judgement of the task which is to be accomplished. If something helps then use it. If it causes more problems than enything else then leave it.
A while ago he asked me what he should have printed on my business cards. I said 'Wizard'. I read books which nobody else understand. Then I do something which nobody understands. After that the computer does something which nobody understands. When asked, I say things about the results which nobody understand. But everybody expects miracles from me on a regular basis. Looks to me like the classical definition of a wizard.
-
...and there's a whole school of thought that Singletons are evil... i.e. they are just glorified, object-oriented window dressing posing as an excuse to use global variables again.
Singletons started out as a workaround for a C++ issue: that you can't control the order that static objects are initialised in that environment. .NET static constructors are guaranteed to be run at the first access to any static or instance field of the type, or the first invocation of any static, instance, or virtual method of the type (that's nearly a direct quote from the CLI spec). To all intents, singletons are global variables. Make life easier on your clients: use a static class with a static constructor and static methods to implement your 'singleton'.
DoEvents: Generating unexpected recursion since 1991