Rand() Generating the Same Number - Even with Srand(Time(Null)) in My Main!

rand() generating the same number – even with srand(time(NULL)) in my main!

The issue is that the random number generator is being seeded with a values that are very close together - each run of the program only changes the return value of time() by a small amount - maybe 1 second, maybe even none! The rather poor standard random number generator then uses these similar seed values to generate apparently identical initial random numbers. Basically, you need a better initial seed generator than time() and a better random number generator than rand().

The actual looping algorithm used is I think lifted from Accelerated C++ and is intended to produce a better spread of numbers over the required range than say using the mod operator would. But it can't compensate for always being (effectively) given the same seed.

rand() not generating random numbers even after srand(time(NULL))

You must call srand() once, whereas you call it on every entry into generateWeight(). Since nowadays computers are fast and time() returns the time in seconds, this mostly restarts the random number generator from the same seed.

rand function is giving me the same result at each run even when I called srand(time(NULL))

There are two fundamental problems with your code which, in combination, produce the curious result you're experiencing.

Almost anyone will warn you about the use of the rand() interface. Indeed, the Mac OS manpage itself starts with a warning:

$ man rand
NAME
rand, srand, sranddev, rand_r -- bad random number generator

Yep, it's a bad random number generator. Bad random number generators can be hard to seed, among other problems.

But speaking of seeding, here's another issue, perhaps less discussed but nonetheless important:
Do not use time(NULL) to seed your random number generator.

The linked answer goes into more detail about this, but the basic issue is simple: the value of time(NULL) changes infrequently (if frequently is measured in nanoseconds), and doesn't change much when it changes. So not only are you relying on the program to not be run very often (or at least less than once per second), you're also depending on the random number generator to produce radically different values from slightly different seeds. Perhaps a good random number generator would do that, but we've already established that rand() is a bad random number generator.

OK, that's all very general. The specific problem is somewhat interesting, at least for academic purposes (academic, since the practicial solution is always "use a better random number generator and seed it with a good random seed"). The precise problem here is that you're using rand() % 7.

That's a problem because what the Mac OS / FreeBSD implementation of rand() does is to multiply the seed by a multiple of 7. Because that product is reduced modulo 232 (which is not a multiple of 7), the value modulo 7 of the first random number produced by slowly incrementing seeds will eventually change, but it will have to wait until the amount of the overflow changes.

Here's a link to the code. The essence is in these three lines:

    hi = *ctx / 127773;
lo = *ctx % 127773;
x = 16807 * lo - 2836 * hi;

which, according to a comment, "compute[s] x = (7^5 * x) mod (2^31 - 1) without overflowing 31 bits." x is the value which will eventually be returned (modulo 232) and it is also the next seed. *ctx is the current seed.

16807 is, as the comment says, 75, which is obviously divisible by 7. And 2836 mod 7 is 1. So by the rules of modular arithmetic:

x mod 7 = (16807 * lo) mod 7 - (2836 * hi) mod 7
= 0 - hi mod 7

That value only depends on hi, which is seed / 127773. So hi changes exactly once every 127773 ticks. Since the result of time(NULL) is in seconds, that's one change in 127773 seconds, which is about a day and a half. So if you ran your program once a day, you'd notice that the first random number is sometimes the same as the previous day and sometimes one less. But you're running it quite a bit more often than that, even if you wait a few seconds between runs, so you just see the same first random number every time. Eventually it will tick down and then you'll see a series of 3s instead of 4s.

Rand() is generator the same number even though I called srand(time(NULL))

As said in the comments, rand() % 1 is nonsensical. The remainder of anything divided by 1 is 0. You then add 100 to it.

Instead, (rand() % 100) + 1 will give you a random number in the range [1, 100].

The facilities in <random> are much better, and it is a good idea to learn them.

std::mt19937 mt((std::random_device()())); //create engine
std::uniform_int_distribution<int> dist(1, 100); //define distribution

dist(mt); //better random number in range [1, 100]

rand() produces the same result on each function call (with srand(time(0))

(Converting my comment to an answer).

For most applications, you'll only really want to seed rand once in the course of running a program. Seeding it multiple times requires you to get different random seeds, and it's easy to mess that up.

In your case, the time function usually returns something with resolution on the level of seconds (though this isn't actually required by the standard). As a result, if you call time twice within the same second, you might get back the same value. That would explain why you're getting duplicate values: you're seeding the randomizer with the same value twice and then immediately querying it for a random number.

The best solution to this is to just seed the randomizer once. Typically, you'd do that in main.

If you really do want to seed the randomizer multiple times, make sure that you're doing so using a seed that is going to be pretty much random. Otherwise, you risk something like this happening.

Using srand(time(NULL)) gives same output each time my program is run (not in loop, seeded with large enough values)

It's a problem of timing. The random number expression in your header is executed before the random number generator seeding code in your main function. Change your code like this

// header
int rand_number;
std::string codeword;

// source
int main() {
srand (time(NULL));
rand_number = rand() % codewords.size();
codeword = codewords[rand_number];

Now the random number is generated after the random number generator has been seeded.

PS why are the take_turn and display functions in your header file? Functions (unless they are inline) should be placed in source files.

Getting same values with srand time null in Inheritance class

Tx to Adrian Mole's comment, i got the answer.

i declared a static bool called "Seeded" and for first time i call the constructor it changes it to True from false, so next time i call the constructor it won't try to reseed.

Answer: Each time i call the constructor i reseed it (Calling srand time null for more than once) so i declared a static bool which is used to call srand time null once.



Related Topics



Leave a reply



Submit