If you're not sure what this topic is about, read a little side information here. If you're still not sure what this is about, then I suggest not reading onward.
For a particular project I need a Pseudo Random Number Generator (PRNG). Mark is not going to include a random seed for the random function in Game Maker, so I need to design one myself.
I've been looking around a bit on the Internet for a relatively simple formula that nevertheless has a reasonably good distribution. This is a pretty popular one, and easy to implement:
QUOTE
x1 = ( x0 * a + c ) MOD (2^24)
In this case, x1 is the new random value, and x0 is the old random value. I found information on this page, including the standard values VB uses for a, c and the standard seed. While there are of course better formulae around, this one suffices for my needs. Besides, being implemented in Game Maker script, the simpler the better if you need to call it often.
So, using the suggested values for a and c, I've written the following functions. One called rnd_seed, reading this:
CODE
global.rnd=argument0;
This sets the seed, necessary before calling the function rnd_get:
CODE
global.rnd=(global.rnd*1140671485+12820163) mod 16777216;
return global.rnd/16777216;
return global.rnd/16777216;
The first line calls the formula with the parameters as currently used by visual basic - the second line returns the result divided by 16777216. This should always result in a value between 0 and 1, the latter exclusive. Note that the last division is not applied to global.rnd itself - it would mess up the seed for the next call of the function.
Here's a test script that draws 10000 numbers of 0 through 9, and counts them in an array, using VB's original seed:
CODE
rnd_seed(327680);
for (i=0; i<11; i+=1) res[i]=0;
repeat 10000
res[floor(rnd_get()*10)]+=1;
show_message('Distribution:');
for (i=0; i<10; i+=1)
show_message(string(i)+':'+string(res[i]));
for (i=0; i<11; i+=1) res[i]=0;
repeat 10000
res[floor(rnd_get()*10)]+=1;
show_message('Distribution:');
for (i=0; i<10; i+=1)
show_message(string(i)+':'+string(res[i]));
When displaying the results of the array res, I would expect that each number is drawn around 1000 times.
I get these results:
0:5000
1:0
2:0
3:0
4:0
5:0
6:0
7:5000
8:0
9:0
Of course, the floor() command may cause some bias towards a particular value, but this is ridiculous. I hand-calculated a few random values, and then the results come out as you would expect them.
Now, it says this on the GM To Do list:
QUOTE
Precision of reals is pretty bad (Don't know what causes this, happened between 5.4.7 and 5.4.10). This in particular effects datetime functions.
But I didn't think the numbers would become high enough to influence the formula (seeing the mod division brings it down every time). It seems that especially the multiplication in the formula above doesn't give Game Maker the correct answer.
Now, it turns out you need about 4 or 5 digits less for a to prevent Game Maker running around in the circles above. But my knowledge of random numbers ends here - I don't know what the 'best other' numbers are for a and c. What I've tried turns up with horribly bad distribution.
If anyone can think of good values, or can suggest another simply-to-implement PRNG (haven't found good alternatives yet), I'd be happy to hear.
Smarty





