we are in the context of a lua script which uses some C/C++ functions exported to be used with lua.
In lua, we have
math.randomseed(12) // 12 for example
for i=0, 10 do
c++function()
print(math.random())
end
the output is always the same number.
When i saw the cause, i found that in the c++_function, there is an srand(0) and some calls to the rand() function.
So our math.randomseed(12) will have no effect, and we will in each iteration have srand(0), the rand() call, and after that the math.random() call(which just call the C rand() function).
and because we are giving always the same seed, we have always the same sequence generated.
The question is, is there a solution to make srand(x) limited to a specific scope ? so the rand() call in c++_function will use the seed 0, and when we return back to lua, the math.random() uses the math.randomseed(x).
If no, any one have a suggestion ?
Thank you
Unfortunately, srand does not return its current seed. Nevertheless, you can fake it. Try this:
function call_c_function()
local s=math.random(1,2^30)
c++function()
math.randomseed(s)
end
for i=0, 10 do
call_c_function()
print(math.random())
end
Just make sure that you don't call math.randomseed before each call to math.random, but only after calling c++function, as above.
You probably will not be able to limit the scope of srand() to affect only your invocation of math.random().
I'd suggest to use a random number generator that is independent of the built-in. See Generating uniform random numbers in Lua for an example.
Related
I'm a C++ newbie and I'm stumped on this. I need to call this function in my main function three times but each time it gives me the same result, i.e. pull_1, pull_2, pull_3 are the same. What do I need to do to make them actually random?
string PullOne()
{
string pick;
string choices[3] = {"BAR", "7", "cherries"};
std::srand(time(0));
pick = choices[(std::rand() % 3)];
return pick;
}
From my main function:
string pull_1, pull_2, pull_3;
pull_1 = PullOne();
pull_2 = PullOne();
pull_3 = PullOne();
You shouldn't call srand() before each call to rand(). Call it once – somewhere at the start of your program.
The problem is you restart the random generator so it starts to produce the very same pseudorandom sequence from the very same point.
The random number generator is reset to an initial state, which is dictated by the seed value, every time you call srand. Time value may be the same between successive calls to time, hence the same seed and the same number generated.
Call seeding function (srand) only once in your main function before generating random samples.
Why do you keep calling std::srand(time(0));? That re-seeds the PRNG.... and because this all happens within the same second, you're always re-seeding it with the same sequence.
Call srand once in your program, and once only.
Also, I would recommend, at least on POSIX-compliant systems, something like std::srand(time(0) ^ getpid()), so that you can run your program twice within the same "second" and still get a new PRNG sequence.
The time(0) function may not have 'ticked' between function calls. So you are seeding the random number generator with the same value each time, leading to identical values for rand()
Your problem is that you seed the RNG each time you call the function. You should only seed this once in a program for best results. If you want the result to vary from one execution of the program to the next, srand based on the result of the time() function.
I'm a C++ newbie and I'm stumped on this. I need to call this function in my main function three times but each time it gives me the same result, i.e. pull_1, pull_2, pull_3 are the same. What do I need to do to make them actually random?
string PullOne()
{
string pick;
string choices[3] = {"BAR", "7", "cherries"};
std::srand(time(0));
pick = choices[(std::rand() % 3)];
return pick;
}
From my main function:
string pull_1, pull_2, pull_3;
pull_1 = PullOne();
pull_2 = PullOne();
pull_3 = PullOne();
You shouldn't call srand() before each call to rand(). Call it once – somewhere at the start of your program.
The problem is you restart the random generator so it starts to produce the very same pseudorandom sequence from the very same point.
The random number generator is reset to an initial state, which is dictated by the seed value, every time you call srand. Time value may be the same between successive calls to time, hence the same seed and the same number generated.
Call seeding function (srand) only once in your main function before generating random samples.
Why do you keep calling std::srand(time(0));? That re-seeds the PRNG.... and because this all happens within the same second, you're always re-seeding it with the same sequence.
Call srand once in your program, and once only.
Also, I would recommend, at least on POSIX-compliant systems, something like std::srand(time(0) ^ getpid()), so that you can run your program twice within the same "second" and still get a new PRNG sequence.
The time(0) function may not have 'ticked' between function calls. So you are seeding the random number generator with the same value each time, leading to identical values for rand()
Your problem is that you seed the RNG each time you call the function. You should only seed this once in a program for best results. If you want the result to vary from one execution of the program to the next, srand based on the result of the time() function.
I'm a C++ newbie and I'm stumped on this. I need to call this function in my main function three times but each time it gives me the same result, i.e. pull_1, pull_2, pull_3 are the same. What do I need to do to make them actually random?
string PullOne()
{
string pick;
string choices[3] = {"BAR", "7", "cherries"};
std::srand(time(0));
pick = choices[(std::rand() % 3)];
return pick;
}
From my main function:
string pull_1, pull_2, pull_3;
pull_1 = PullOne();
pull_2 = PullOne();
pull_3 = PullOne();
You shouldn't call srand() before each call to rand(). Call it once – somewhere at the start of your program.
The problem is you restart the random generator so it starts to produce the very same pseudorandom sequence from the very same point.
The random number generator is reset to an initial state, which is dictated by the seed value, every time you call srand. Time value may be the same between successive calls to time, hence the same seed and the same number generated.
Call seeding function (srand) only once in your main function before generating random samples.
Why do you keep calling std::srand(time(0));? That re-seeds the PRNG.... and because this all happens within the same second, you're always re-seeding it with the same sequence.
Call srand once in your program, and once only.
Also, I would recommend, at least on POSIX-compliant systems, something like std::srand(time(0) ^ getpid()), so that you can run your program twice within the same "second" and still get a new PRNG sequence.
The time(0) function may not have 'ticked' between function calls. So you are seeding the random number generator with the same value each time, leading to identical values for rand()
Your problem is that you seed the RNG each time you call the function. You should only seed this once in a program for best results. If you want the result to vary from one execution of the program to the next, srand based on the result of the time() function.
I'm a C++ newbie and I'm stumped on this. I need to call this function in my main function three times but each time it gives me the same result, i.e. pull_1, pull_2, pull_3 are the same. What do I need to do to make them actually random?
string PullOne()
{
string pick;
string choices[3] = {"BAR", "7", "cherries"};
std::srand(time(0));
pick = choices[(std::rand() % 3)];
return pick;
}
From my main function:
string pull_1, pull_2, pull_3;
pull_1 = PullOne();
pull_2 = PullOne();
pull_3 = PullOne();
You shouldn't call srand() before each call to rand(). Call it once – somewhere at the start of your program.
The problem is you restart the random generator so it starts to produce the very same pseudorandom sequence from the very same point.
The random number generator is reset to an initial state, which is dictated by the seed value, every time you call srand. Time value may be the same between successive calls to time, hence the same seed and the same number generated.
Call seeding function (srand) only once in your main function before generating random samples.
Why do you keep calling std::srand(time(0));? That re-seeds the PRNG.... and because this all happens within the same second, you're always re-seeding it with the same sequence.
Call srand once in your program, and once only.
Also, I would recommend, at least on POSIX-compliant systems, something like std::srand(time(0) ^ getpid()), so that you can run your program twice within the same "second" and still get a new PRNG sequence.
The time(0) function may not have 'ticked' between function calls. So you are seeding the random number generator with the same value each time, leading to identical values for rand()
Your problem is that you seed the RNG each time you call the function. You should only seed this once in a program for best results. If you want the result to vary from one execution of the program to the next, srand based on the result of the time() function.
I was creating a simple program that simulates a coin toss for my class. (Actually, class is over this term and i'm just working through the rest of the projects that weren't required). It involves the creating and calling a function that generates a random number between 1 and 2. Originally, I tried to seed the random number generator within the function that would be using it (coinToss); however, it did not produce a random number. Each time the program was run it was the same number as though I had only used
rand()
instead of
unsigned seed = time(0);
srand(seed);
rand();
Yet, when i moved the above within
int main()
it worked fine.
My question is 1)why did it not work when setup within the function that called it and (2) how does rand()
have access to what was done by srand() if they do not both occur in the same function?
Obviously, i'm a beginner so please forgive me if i didn't formulate the question correctly. Also, my book has only briefly touched on rand() and srand() so that's all i really know.
thanks for any help!
Pertinent code:
First attempt that didn't work:
int main()
{
//...........
coinToss();
//...........
}
int coinToss()
{
unsigned seed = time(0);
srand(seed);
return 1 + rand() % 2;
}
Second attempt which did work:
int main()
{
unsigned seed = time(0);
srand(seed);
coinToss();
}
int coinToss()
{
return 1 + rand() % 2;
}
You probably only want to seed the random number generator once. rand() returns the next pseudo-random number from it's internal generator. Every time you call rand() you will get the next number from the internal generator.
srand() however sets the initial conditions of the random number generator. You can think of it as setting the 'starting-out point' for the internal random number generator (in reality it's a lot more complicated than that, but it's a useful cognitive model to follow).
So, you should be calling srand(time(0)) exactly once in your application - somewhere near the beginning. After that, you can call rand() as many times as you want!
However
To answer your actual question - the first version doesn't work because time() returns the number of seconds since the epoch. So If you call coinToss() several times in a second (say, if you wanted to simulate 100 coin tosses), then you'd be constantly seeding the random number generator with the same number, thereby resetting it's internal state (and thus the next number you get) every time.
Anyway - using time() as a seed to srand() is somewhat crappy for this very reason - time() doesn't chage very often, and worse, it's predictable. If you know the current time, you can work out what rand() will return. The internet has many, many examples of better srand() seeds.
Pseudo-random number generators (like rand) work by taking a single starting number (the seed) and performing a numeric transformation on it each time you request a new number. You want to seed the generator just once, or it will continually get reset, which is not what you want.
As you discovered, you should just call srand just once in main. Also note that a number of rand implementations have pretty short cycles on the low 4 bits or so. In practice this means you might get an easily predictable repeating cycle of numbers You might want to shift the return from rand right by 4-8 bits before you take the % 2.
EDIT: The call would look something like:
return 1 + (rand() >> 6) % 2;
Seed only once per program, not every time you call coinToss()
To expand on Mark B's answer: It is not so much that the random number generator is reset as it sets a new variable to be used in calculating random numbers. However your program doesn't do that much work between calls to srand. Therefore every time you call srand(time(0)) it is using the same seed, so you are resetting the internal state of the random number generator . If you put a sleep in there so that time(0) changed you would not get the same number every time.
As for how data passes from srand to rand, it is fairly simple, a global variable is used. All names that start with an underscore and a capital letter or two underscores are reserved for variables used by your compiler. More than likely this variable has been declared static so it isn't visible outside of the translation unit(aka the library file that contains your compiler's standard library.) This is done so that #define STUFF 5 doesn't break your standard library.
for simple simulations, you must not change the seed at all during the simulation. Your simulation will be "worse" in that case.
To understand this, you should see pseudo random sequences as a big wheel of fortune. When you change the seed, it is like you change the position, and then, each call to rand will give you a different number. If you roll again, it will be more probable finding yourself repeating numbers.