C++ QuestionGenerating "random" numbers

garyw

Moderator
Tutorial Publisher
A friend of mine (ex programmer type) just made a suggestion - Generate your random number using the MJD as a seed. As the MJD is always changing in theory your resulting numbers should have some more randomness to them.

agentgonzo

Grounded since '09
A friend of mine (ex programmer type) just made a suggestion - Generate your random number using the MJD as a seed. As the MJD is always changing in theory your resulting numbers should have some more randomness to them.
We're back to the beginning of the topic. Seed the random number generator with the current time (normally and easiest with just the time() function - using MJD will have the same effect but is overkill and does not provide you with anything more random):
Code:
srand(time(NULL));
time() returns the number of seconds since epoch, so you don't need to worry about running it at the same time the next day. Only seed the random number generator once in your code (otherwise it defeats the point of pseudo-random number generation)

rand() is a good-enough-for-most random number generator. If you're not getting random numbers from it then you're using it incorrectly. If you want a random integers in the range a-b, then use:
Code:
int random = a + rand() % (b - a + 1);

rand() is good enough for most uses. If you do not know whether it is good enough for you then either:

1. It is good enough for you
2. You do not know your subject matter well enough.
Don't worry about using other methods of random number generation unless you thoroughly understand statistics and know that you need a better random number generator (basically, unless you are doing crypto).

RisingFury

OBSP developer
A friend of mine (ex programmer type) just made a suggestion - Generate your random number using the MJD as a seed. As the MJD is always changing in theory your resulting numbers should have some more randomness to them.

There's also a function that returns the time your computer has been running in milliseconds. That's also a good seed.

agentgonzo

Grounded since '09
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));
As an explanation, here is what is going on. The first 3 lines are fairly simple:
Code:
<seed the randomness>
lowest=1
highest = 100
range = 99
The last one is messy. I've added some extra braces to help you understand the order of precedence:
Code:
int r = lowest+int([B]([/B]range*rand()[B])[/B]/(RAND_MAX + 1.0));
So Let's start putting in some numbers (I'm working on a 64-bit system, so YMMV).
Code:
int r = 1 + int([COLOR=Red][B]([/B][/COLOR]99*rand()[COLOR=Red][B])[/B][/COLOR]/(2147483647 + 1.0));
The important thing to notice here is that rand() returns an int (which is in the range 0 - RAND_MAX (inclusive). It is then multiplied by 99. However, 99 is also an int and one int multiplied by an int returns another int. In this situation, you can get rollover, where the 8-byte integer runs out of space to store it and just wraps around. So in C code (when dealing with 64-bit ints), 2147483647 + 1 = -2147483648. So that means that (99 * rand()) will always be in the range (-2147483648, 2147483647)

Now with the denominator, we have 2147483647 + 1.0. The first number in an int, the second is a float. So what happens is that the int gets cast to a float and then the two added, resulting in (on my compiler) 2147483648.000000. So now we have:
Code:
int r = 1 + int([B]([/B][I]R[/I][B])[/B]/(2147483648.0));
R is in the range -2147483648 ≤ R ≤ 2147483647.
Then the division is performed resulting in:
Code:
int r = 1 + int([I]S[/I]);
Where S is in the range -1 ≤ S < 1. Then you cast it to an int, where it all gets squashed to 0 (apart from the really rare exception where R = -2147483648):

Code:
int r = 1 + 0;
r is (pretty much always) 1. I don't know why you got 38, but this will explain why you weren't getting your expected range.

orb

News Reporter
If you need true randomness use /dev/random device in linux which works the best (i.e. much faster) when used with [ame="http://en.wikipedia.org/wiki/Hardware_random_number_generator"]Hardware random number generator[/ame], or if don't have one and there is no RNG on the motherboard either, a daemon that gets entropy form FSB/clock drift or a microphone (or a webcam). Otherwise the entropy pool fills very slowly (a bit faster if you type and move mouse randomly ).

Hielor

Defender of Truth
Donator
Beta Tester
There's also a function that returns the time your computer has been running in milliseconds. That's also a good seed.
Not as good as the time in milliseconds since 1970--uptime will repeat, time since 1970 doesn't.

agentgonzo

Grounded since '09
There's also a function that returns the time your computer has been running in milliseconds. That's also a good seed.
On windows, this is GetTickCount(), but it is limited to the system clock resolution (normally ~16ms).

boyan3001

New member
Excuse me, I am new in here, but...
You could also use the fact that C++ alow you to define varibale without initializing it. In fact, every time you run your compiled code, that variable will be placed on some pice of memory that already contain some value, lefted behind from a previous user (of memory location).
So define some int seed, do not initialize it, and give that to rand() as seed. This could provide some good randomnes for seeding... but it could be someway predictable.

kuddel

Donator
Donator
Excuse me, I am new in here, but...
You could also use the fact that C++ alow you to define varibale without initializing it. In fact, every time you run your compiled code, that variable will be placed on some pice of memory that already contain some value, lefted behind from a previous user (of memory location).
So define some int seed, do not initialize it, and give that to rand() as seed. This could provide some good randomnes for seeding... but it could be someway predictable.

This is one (not the best) soluton, but remember that most compilers create different (assemby-)code in DEBUG version versus RELEASE version.
In the DEBUG version uninitialized members/variables are often 'initialized' with a certain pattern (e.g. 0xACACAC, or even 0x00).

In general:
1) Use rand()/seed() only if you know how it works
2) call seed() only once with a "random" value (time since Epoch is quite OK for that)
3) after that you should only call rand() further on...
simple is that.

/Kuddel

agentgonzo

Grounded since '09
Excuse me, I am new in here, but...
You could also use the fact that C++ alow you to define varibale without initializing it.
If you were writing code as a job and you suggested this, I'd request that you taken off my team.

n72.75

Move slow and break things
Orbiter Contributor
Tutorial Publisher
Donator
74623

martins

Orbiter Founder
Orbiter Founder

A very fine specimen indeed. How did you come by it?

However, it pales compared to my own champion: 470301. This seed will father a sequence so random that even a lump of decaying uranium will tick with the regularity of an atomic clock by comparison.

jangofett287

Heat shield 'tester'
Excuse me, I am new in here, but...
You could also use the fact that C++ alow you to define varibale without initializing it. In fact, every time you run your compiled code, that variable will be placed on some pice of memory that already contain some value, lefted behind from a previous user (of memory location).
So define some int seed, do not initialize it, and give that to rand() as seed. This could provide some good randomnes for seeding... but it could be someway predictable.

This is risking all sorts of memory leaks just to increase unpredictability, besides, if you only run well written programs that clean up after themselves, this will always turn out as 0 or NULL, depending on the system. I suspect the compiler will also want to chew your head off...

agentgonzo

Grounded since '09
You obviously have no idea of how computer programs work.
This is risking all sorts of memory leaks just to increase unpredictability
No it won't. Memory will not leak as you have defined your 4 (or 8) bytes of int on the stack and will get dealt with exactly the same whether it gets initialised or not. Memory won't randomly leak just because you don't initialise one value.

besides, if you only run well written programs that clean up after themselves, this will always turn out as 0 or NULL, depending on the system.
No it won't. Firstly, you can't guarantee that whatever memory the OS assigns to you has been used before, so you can end up with whatever value got assigned to that area when the computer powered on (unless something wrote to it). Furthermore, well written programs that 'clean up' after themselves do things like release resources (including memory). They do not wipe the memory as there is no point as it is not going to be used (by them) again. If I saw code that reset all memory used to a known value when it deallocated it, I would smack the author of it for wasting my time.

I suspect the compiler will also want to chew your head off...
It will likely do one of the following:

1. Give you a warning you are using an uninitialised value
2. Give you an error that you are using an uninitualised value (though I have not seen this on C/C++ compilers unless you have the werror flag)
3. Initialise it for you to 0 or some recognisable pattern
4. Do nothing.

---------- Post added at 16:40 ---------- Previous post was at 16:29 ----------

This thread now seems to be populated by people who don't understand programming, so I will re-iterate what has already been said by Kuddel/martins/orb:

srand(time(null)); // ONCE ONLY
int r = rand(); // every time you want a random number.

Use these unless you can mathematically prove for your situation why they are insufficient. Otherwise shut up with stupid new ideas to improve randomness. rand() is good enough when used correctly for almost all situations (and I cannot think of any in orbiter where it is not)

Last edited by a moderator:

RisingFury

OBSP developer
Not as good as the time in milliseconds since 1970--uptime will repeat, time since 1970 doesn't.

I had a similar similar problem when programming for Arduino. Time since Arduino got turned on in milliseconds and microseconds is logged, but the problem is that it can overflow the variable it's stored in. The millisecond counter overflows in 70 days or something, but microsecond counter overflows in a few hours.

How does the PC deal with that? Milliseconds since 1970 is a large number...

orb

News Reporter
How does the PC deal with that? Milliseconds since 1970 is a large number...
The format is extended to use wider data variable. For 32-bit time there was [ame="http://en.wikipedia.org/wiki/Year_2038_problem"]Year 2038 problem[/ame], but currently new systems use 64-bit time.

Donator
Donator
Beta Tester
This could be overkill but I've been using Newran in my work for quite some time.

As others have pointed out before, it's not the "randomness" that's the useful part here, but the various distributions it allows you to generate. This allows you to bind these random numbers directly to a real-life modelling situation (Mean Time Between Failures in your case) without bothering with much of the math detail.

Replies
1
Views
471
Replies
5
Views
519
Project Project Mercury
Replies
59
Views
8K