C++ Question Generating "random" numbers

N_Molson

Addon Developer
Addon Developer
Donator
Joined
Mar 5, 2010
Messages
10,002
Reaction score
4,418
Points
203
Location
Toulouse
Hello, :hello:

I'm searching a way to generate a random number. After a search about this, I've tried this, including time.h :

Code:
srand ( (unsigned int) time(NULL) );
r = rand();

I put it in ClbkSetClassCaps, but I'm not sure it matters a lot.

The problem is that, while I should get a number from 0 to 65535, I get a very narrow array of numbers, like 7200-7500.

From what I understood, this isn't a big surprise since this method relies on the time that it took to reach the line of code. I'm not surprised that the variations are limited, because the clock of my CPU is steady enough.

So it really isn't a random number at all, it will just give different results on different systems. Not what I want to simulate things like system failures.

So I'm taking any advice to generate "reasonably random" numbers. I know that computer can't generate "genuinely random" numbers, but there is a way to do a lot better than what I get (as there are good roulette or other casino games simulations)...

Thanks in advance, :tiphat:

Edit : and using what follows, I always get "38" ! What a randomness !

srand((unsigned)time(0));
int lowest=1, highest=100;
int range=(highest-lowest)+1;
int r = lowest+int(range*rand()/(RAND_MAX + 1.0));
 
Last edited:
rand() is usually not a very good random number generator, but for your purposes it should be sufficient. However, you are slightly abusing it. rand is supposed to generate a pseudorandom sequence of numbers after a single seed, while you are repeatedly seeding it and then only take the first number. These numbers will only be as random as the seed, and you have already identified the problem with that.

At the least, try to "burn in" the sequence by generating, say, 100 numbers and throwing them away, before picking one you actually want to use.

The other possibility would be to store the last number you got in a log file, and then use that as the seed for the next run of your addon, so that you use a continuous sequence across individual simulation sessions.
 
Thanks. I got something that seems to work much better and should do it :

Code:
#include <ctime>
#include <cstdlib>

srand(time(0));
r = (rand() % 100) + 1;
 
Also, there are better random number generators around, depending on the system you work on.
 
Now, I'm not a programmer (yet) but an idea has just poped into my head. What if you use the time of day as the seed to get a random number, then use that random number as the seed to generate all other numbers. Then, 'burn in' the sequence, as martins suggested, but use another random number to get how many you discard, rather than 100.
 
Thanks. I got something that seems to work much better and should do it :

Code:
#include <ctime>
#include <cstdlib>

srand(time(0));
r = (rand() % 100) + 1;
You should only seed the random number generator once for the lifetime of your program--ModuleLoad would probably be a better idea than ClbkSetClassCaps.

Now, I'm not a programmer (yet) but an idea has just poped into my head. What if you use the time of day as the seed to get a random number, then use that random number as the seed to generate all other numbers. Then, 'burn in' the sequence, as martins suggested, but use another random number to get how many you discard, rather than 100.
The problem with this is that if for some reason you input the same time of day, the resulting numbers will all be the same. You might as well just stick to the time of day, since adding all the extra random numbers and re-seeding doesn't actually do anything for you. If you've got a graphic calculator that lets you seed the random number generator, this is fairly easy to prove on your own.
 
Now, I'm not a programmer (yet) but an idea has just poped into my head. What if you use the time of day as the seed to get a random number, then use that random number as the seed to generate all other numbers. Then, 'burn in' the sequence, as martins suggested, but use another random number to get how many you discard, rather than 100.

The problem is, that beginning with the TOD (which is received by "time(NULL)"), you use always the same numbers for initializing your random number generator.

Better use: Time of day, Mouse cursor X position, Mouse Cursor Y position, Euro-Dollar exchange course, geomagnetic activity index, the number of google results for "Angela Merkel Sex Video" (About 39.100.000 results) and the sum of the file sizes in the systems temporary file directory.
 
Last edited:
You should only seed the random number generator once for the lifetime of your program--ModuleLoad would probably be a better idea than ClbkSetClassCaps.

I was thinking than ClbkSetClassCaps was running only one time. Should the constructor (it's a VESSEL3) be an appropriated place ?

the number of google results for "Angela Merkel Sex Video" (About 39.100.000 results)

:rofl: Crazy !

I got the point, but of course variable inside the Orbiter environnement would be better, to be sure every user has them (the exemple above is interesting, but what if the user has his modem offline, he gets a NULL ?). Mouse position could work, since Orbiter uses it in 2D/3D panels methods...
 
Last edited:
I was thinking than ClbkSetClassCaps was running only one time. Should the constructor (it's a VESSEL3) be an appropriated place ?
The VESSEL3 constructor is called for each instance of your vessel, so like Hielor noted, a better place is InitModule, which is called only once when the DLL is loaded.
 
You mean this part ?

Code:
// --------------------------------------------------------------
// Vessel initialisation
// --------------------------------------------------------------
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
	return new ShuttlePB (hvessel, flightmodel);
}
 
And if you ever need real random numbers for some reason, radioactive decay is an accessible and reliable source. Services like hotbits will handle the radioactive material for you and deliver the resulting random sequence in a format you can specify.
 
You mean this part ?

Code:
// --------------------------------------------------------------
// Vessel initialisation
// --------------------------------------------------------------
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
	return new ShuttlePB (hvessel, flightmodel);
}
No, ovcInit is called for each instance of the vessel too.

I meant:
Code:
DLLCLBK void InitModule (HINSTANCE hDLL) {
}
 
I don't even have this :shifty:

Oh, I just found it in the Deltaglider sample... I didn't even knew it had to be included in the code ! :facepalm:
 
didn't even knew it had to be included in the code ! :facepalm:
This function doesn't need to be included in the code if it isn't needed. If it's however included, it's called upon module initialization.
 
So it really isn't a random number at all, it will just give different results on different systems. Not what I want to simulate things like system failures.
Incidently, if you want to model system failures or similar events, take care to use a proper statistical model. It would be wrong, for example, to use a random number drawn from a uniform distribution, and interpret that as the time to the next failure.

A more reasonable model would be to assume that the probability of failure in the interval [t, t+dt] is independent of t. This leads to an exponentially decaying function for the probability that the system hasn't failed until t.

A simple way to implement this would be to draw a random number once a second, and interpret this as the probability that the system will fail this second. In other words,

if rand() < RAND_MAX * failure_probability_per_second then fail

Of course you could make this more sophisticated to include material fatigue etc.

Edit: If failure_probability_per_second is so small that (int)(RAND_MAX * failure_probability_per_second) == 0 then the above code won't work because of the granularity of the random numbers. Even if it's slightly greater than 1 it won't work very well. I that case you can simply increase the testing interval.

Edit2: Another advantage of this approach is that you can include temporally varying failure parameters, like

Code:
if rand() < RAND_MAX * failure_probability_per_second*solar_radiation_level then fail
or, to model permanent damage

Code:
failure_probability_per_second += (1-failure_probability_per_second)*solar_radiation_level
 
Time of day, Mouse cursor X position, Mouse Cursor Y position, Euro-Dollar exchange course, geomagnetic activity index, the number of google results for "Angela Merkel Sex Video" (About 39.100.000 results) and the sum of the file sizes in the systems temporary file directory.
Well, that certainly is random... But best not rely too much on the user's internet connection or (worse) the German parliament to keep Orbiter modules running nominally...
 
To get true randomness, use cryptographically strong generators from libraries like CRYPTLIB by Peter Gutmann. They take all kinds of in-computer random stuff, process it with hash functions and even do FIPS testing to see if the amount of entropy is large enough. Of course it may be overkill, but reading the manuals for them is quite enlightening.
 
I wouldn't imagine there being 1 result! Yucks! :lol:


the number of google results for "Angela Merkel Sex Video

Its never that trivial....

N.
 
Back
Top