floor, ceil and random
Often on the GMC, a poster is interested in obtaining a random integer within a certain range.
IE.
How can I get a random number in the range 1-10?
Responses, typically will be:
r_number=floor(random(10)) + 1;
or
r_number=ceil(random(10));
The problem is many do not recognise the dangers of using ceil(), in that context.
The problem being, random(x) will occasionally return exactly 0, applying ceil() to 0, results in the value remaining at 0, therefore the random number will be 0. Clearly outside of the desired range of 1-10.
This has been explained numerous times, but many fail to listen, or do not believe that random() can return exactly 0.
I sought out to definitively prove that random() can, and will return exactly 0. With Game Maker 7.0, two new functions were included; random_set_seed(seed) and random_get_seed(). Respectively setting the seed to Game Makers Pseudo Random Number Generator, and returning the current seed to the PRNG.
I wrote a program to repeatedly get the current seed, get a random number and compare it to exactly 0, if it was display the seed. Having the seed, I could definitively prove that random() can return exactly 0.
The magic number is 649090867, NakedPaulToast’s Number.
The following code will always return a random number of 0.00000000000000
seed=649090867;
random_set_seed(seed);
r_no=random(100);
by the way, so will:
seed=649090867;
random_set_seed(seed);
r_no=random(102378);
It doesn’t matter what argument is supplied to random(). If the seed is 649090867, the number returned will be exactly 0.00000000000000000…….
Try it yourself. Then, quit telling people to use ceil(random(x));
June 14th, 2008 at 12:03 pm
Just out of curiosity, how long did it take that program to find the number? I know that the running time would be extremely dependent on the original seed, but I have to wonder.
June 14th, 2008 at 3:30 pm
@Mnementh: Well, for my own amusement, I did a quick run of this test program in GM:
repeat (100000) {
random_set_seed(seed);
rand = random(10);
if (rand == 0) break;
seed += 1;
}
It ran at 3 fps on my computer and took 5 minutes to run 100,000,000 tests. The counter stopped, as expected, on 649090867. The whole batch of 649 million samples took 33 minutes and 10.07 seconds. Not too bad.
June 14th, 2008 at 4:45 pm
I used a different method than Soleil. I’m not sure if Soleil is aware of it, perhaps it doesn’t matter, but the seed is a 32 bit signed integer. Some of the seeds are negative.
This might not be a problem when GM converts from float to integer.
The approach I took was:
if got_zero exit;repeat (100) {
seed=random_get_seed();
r_number=random(2);
iterations+=1;
if r_number=0 {
got_zero=true;
exit;
}
}
Running at a room_speed of 500.
It was effectively checking 2,658,000 numbers a minute.
The seed was discovered after 2,969,401,000 iterations or about 18 hours.
June 17th, 2008 at 1:03 am
[...] Naked Paul Toast’s Insights Naked and out there « floor, ceil and random [...]