Seeding a random number generator C++ [duplicate] - c++

This question already has answers here:
How to generate a random number in C++?
(14 answers)
Closed 5 years ago.
I have two questions.
What other ways are there to seed a psuedo-random number generator in C++ without using srand(time(NULL))?
The reason I asked the first question. I'm currently using time as my seed for my generator, but the number that the generator returns is always the same. I'm pretty sure the reason is because the variable that stores time is being truncated to some degree. (I have a warning message saying, "Implicit conversion loses integer precision: 'time_t' (aka 'long') to 'unsigned int') I'm guessing that this is telling me that in essence my seed will not change until next year occurs. For my purposes, using time as my seed would work just fine, but I don't know how to get rid of this warning.
I have never gotten that error message before, so I assume it has something to do with my Mac. It's 64-bit OS X v10.8. I'm also using Xcode to write and compile, but I had no problems on other computers with Xcode.
Edit:
After toying and researching this more, I discovered a bug that 64-bit Macs have. (Please correct me if I am mistaken.) If you try to have your mac select a random number between 1 and 7 using time(NULL) as the seed, you will always get the number four. Always. I ended up using mach_absolute_time() to seed my randomizer. Obviously this eliminates all portability from my program... but I'm just a hobbyist.
Edit2:
Source code:
#include <iostream>
#include <time.h>
using namespace std;
int main(int argc, const char * argv[]) {
srand(time(NULL));
cout << rand() % 7 + 1;
return 0;
}
I ran this code again to test it. Now it's only returning 3. This must be something to do with my computer and not the C++ itself.

Tl;dr but, most likely, you're doing it wrong. You're only supposed to set the seed once, whereas you might have something like:
for ( ... )
{
srand(time(NULL));
whatever = rand();
}
when it should be
srand(time(NULL));
for ( ... )
{
whatever = rand();
}

1.Not really. You can ask user to input random seed, for example. Or use some other system parameters, but this won't make a difference.
2.To rid of this warning you have to do explicit conversion. Like:
unsigned int time_ui = unsigned int( time(NULL) );
srand( time_ui );
or
unsigned int time_ui = static_cast<unsigned int>( time(NULL) );
or
unsigned int time_ui = static_cast<unsigned int>( time(NULL)%1000 );
to check whether this is really conversion problem you can simply output your time on the screen and see yourself
std::cout << time(NULL);

You should see random once at the begining of you program:
int main()
{
// When testing you probably want your code to be deterministic
// Thus don't see random and you will get the same set of results each time
// This will allow you to use unit tests on code that use rand().
#if !defined(TESTING)
srand(time(NULL)); // Never call again
#endif
// Your code here.
}

For x86, direct call to the CPU time stamp counter rdtsc, instead of a library function TIME(NULL), could be used. Below 1) reads timestamp 2) seed RAND in assembly:
rdtsc
mov edi, eax
call srand
For C++, the following would do the job with g++ compiler.
asm("rdtsc\n"
"mov edi, eax\n"
"call srand");
NOTE: But may not be recommended if code is running in virtual machine.

Related

Trouble generating random numbers in c++ on a Mac using Xcode [duplicate]

This question already has an answer here:
std::random_shuffle produce the same result even though srand(time(0)) called once
(1 answer)
Closed 7 years ago.
I am writing a program that uses random numbers extensively in different ways and I am getting the same random numbers each time. I know to put srand(time(NULL));at the beginning of the program to seed the random number generator and so I have that, but it isn't working. Perhaps it has something to do with XCode or the Mac or something else? I can't find a similar problem online that I has a solution I haven't already tried. Some ways I'm using the random numbers are:
for (int i=0; i<num; i++)
{
chrom_arr[i] = i;
}
random_shuffle(&chrom_arr[0], &chrom_arr[num-1]);
(to get an array with a series of random ints between 0 and num-1)
int crossover = rand() % num;
and other simple things like that. Even though I have srand(time(NULL)); at the beginning, it still doesn't work. I've also tried srand(time(0)); and also putting it in different parts of the program, but I have since learned that's not right.
Alex, can you please post a small but complete program that fails to generate different random numbers every time you run it? I'd be interested to see it...
Here's one that (of course) does yield different numbers every time it is run on my Mac:
#include <iostream>
#include <ctime>
#include <cstdlib>
int main()
{
srand(time(NULL));
for (int i = 0; i < 10; ++i)
std::cout << rand() % 10 << std::endl;
return 0;
}
What does it do if you compile and run it several times on your computer?
UPDATE:
I thought you meant srand() + rand() also produced identical numbers every time. That is not true. However, you are right about the behaviour of srand() + random_shuffle(): it may indeed produce the same numbers every time, depending on your compiler. It does on my compiler (clang on Mac) too.
This is explained here.
You should try somethig like this:
srand(static_cast<unsigned int>(time(0)));
std::shuffle(chrom_arr.begin(), chrom_arr.end(), default_random_engine(rand()));
This will work as long as chrom_arr is a std::vector. Once you are using C++, I presume this is what you are trying to do.

Random number generator always picks the same number [duplicate]

This question already has answers here:
function with rand initializes matrix always the same way
(2 answers)
Seeding a random number generator C++ [duplicate]
(4 answers)
Closed 8 years ago.
I'm making a small "dungeons and dragons" type of program to help demonstrate rand() command to me. It's working just fine, except it always picks 2. Never 1. Help?
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
cout << "welcome to T's version of dungeons and dragons! \n Scenario:";
int Scenario1 = rand() % 2 + 1;
if(Scenario1==1){
cout << "you come across a sleeping traveler, Do you ignore him, or steal his loot?";
}
else {
cout << "you find an old bandit hideout in a cave. Do you ignore, or enter?";
}
}
rand() will essentially generate the same series of numbers every time if you don't seed it.
The seed determines how the rand function generates numbers. For better 'randomness', call the following once at the beginning of the program, for example as the first statement inside main:
srand(time(NULL));
This seeds the random number generator with the value of the current UNIX timestamp, which should be unique enough to guarantee a better illusion of randomness.
More information on srand here:
http://www.cplusplus.com/reference/cstdlib/srand/
Edit
As others have mentioned, it's better to use the functionality found in the <random> header, as this is a more modern approach that avoids many of the pitfalls of the srand/rand paradigm.
rand() will always generate the number in same sequence.
To generate totally random number you can use srand(time(0)); time() is available in header file called #include <ctime>
Fore more detail please have a look :: https://www.youtube.com/watch?v=naXUIEAIt4U

srand (time (null)) causes compiler warning: implicit conversion loses integer precision

Apologies if this question has already been answered.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main () {
srand( time(NULL) );
cout << rand();
}
"implicit conversion loses integer precision: 'time_t' (aka 'long') to 'unsigned int'"
Is the error message Im getting when I execute the code above. I am using xcode 4.6.1. Now when I use a different complier such as the one from codepad.org it executes perfectly fine generating what seems like random numbers so I am assuming it is an xcode issue that I need to work around?
I have JUST started programming so I am a complete beginner when it comes to this. Is there a problem with my code or is it my complier?
Any help would be appreciated!
"implicit conversion loses integer precision: 'time_t' (aka 'long') to 'unsigned int'"
You're losing precision implicitly because time() returns a long which is larger than an unsigned int on your target. In order to workaround this problem, you should explicitly cast the result (thus removing the "implicit precision loss"):
srand( static_cast<unsigned int>(time(nullptr)));
Given that it's now 2017, I'm editing this question to suggest that you consider the features provided by std::chrono::* defined in <chrono> as a part of C++11. Does your favorite compiler provide C++11? If not, it really should!
To get the current time, you should use:
#include <chrono>
void f() {
const std::chrono::time_point current_time = std::chrono::system_clock::now();
}
Why should I bother with this when time() works?
IMO, just one reason is enough: clear, explicit types. When you deal with large programs among big enough teams, knowing whether the values passed around represent time intervals or "absolute" times, and what magnitudes is critical. With std::chrono you can design interfaces and data structures that are portable and skip out on the is-that-timeout-a-deadline-or-milliseconds-from-now-or-wait-was-it-seconds blues.
As mentioned by "nio", a clean workaround would be to explicitly type cast.
Deeper explanation:
The srand() requires an unsigned int as parameter (srand(unsigned int)) but time() returns a long int (long int time()) and this is not accepted by the srand() so in order to fix this, the compiler has to simply typecast (convert) the "long int" to "unsigned int".
BUT in your case the compiler warns you about it instead (as the designers of the compiler thought you should be aware that's all).
So a simple
srand( (unsigned int) time(NULL) );
will do the trick!
(forgive me if i have done something wrong, this is my first answer on stackoverflow)
The srand() function has unsigned int as a type of argument, time_t is long type. the upper 4 bytes from long are stripped out, but there's no problem in it.
srand() will randomize the rand() algorithm with 4 lower bytes of time(), so you're supplying more data than is needed.
If you get an error, try to just explicitly cast the time_t type to unsigned int:
srand( static_cast<unsigned int>(time(NULL)) );
Another interesting thing is that if you run your program twice in the same second, you'll get the same random number, which can be sometimes undesired, that's because if you seed the rand() algorithm with the same data, it will generate the same random sequence. Or it can be desirable when you debug some piece of code and need to test the same behaviour again... then you simply use something like srand(123456).
This is not an error. The code is valid and its meaning is well defined; if a compiler refuses to compile it, the compiler does not conform to the language definition. More likely, it's a warning, and it's telling you that the compiler writer thinks that you might have made a mistake. If you insist on eliminating warning messages you could add a cast, as others have suggested. I'm not a big fan of rewriting valid, meaningful code in order to satisfy some compiler writer's notion of good style; I'd turn off the warning. If you do that, though, you might overlook other places where a conversion loses data that you didn't intend.
#include <stdlib.h>
#include <iostream> //rand
#include <time.h> //time
float randomizer(int VarMin, int VarMax){
srand((unsigned)time(NULL));
int range = (VarMax - VarMin);
float rnd = VarMin + float(range*(rand()/(RAND_MAX + 1.0)));
return rnd;
}

rand() and srand() in C++

What is the basis of generating random numbers in C++?
Is there some logic or principle behind that?
Are the numbers generated completely random?
Suppose I am running this program:
#include <iostream.h>
#include <stdlib.h>
#include <time.h>
int main()
{
/*
Declare variable to hold seconds on clock.
*/
time_t seconds;
/*
Get value from system clock and
place in seconds variable.
*/
time(&seconds);
/*
Convert seconds to a unsigned
integer.
*/
srand((unsigned int) seconds);
/*
Output random values.
*/
cout<< rand() << endl;
cout<< rand() << endl;
cout<< rand() << endl;
return 0;
}
What it shows:
http://img14.imageshack.us/img14/1538/98271820.png
It showed 205 twice.
The question was basically answered in comments and another answer, but I'll gather it up in one place.
C++ rand() function produces not a truly random sequence of numbers, but a pseudo-random one. This means that it is basically a pre-defined sequence of numbers which are "random", but fixed somewhere (actually, it's more complex than that, but this is a simplification for better understanding). Think of it as a long list of integers.
Each call to rand() function pulls the current number and moves the pointer to "current "random" number" to the next one.
What srand() function does is basically setting the pointer to some location in the list. If you don't call the srand() function on each launch, or call it with fixed parameter (seed), you will have the same sequence of numbers on each program launch.
When you're setting your seed from the seconds, if you launch your program twice within that second, your seed will be the same - hence producing the same result.
Try the following code:
#include <windows.h>
// << other code >>
for (int i=0; i<50; i++) {
time(&seconds);
srand(seconds);
cout<< seconds<<" "<<rand()<<endl;
Sleep(100);
}
You will notice, that each "seconds" value correspond to some fixed "first" value for the rand() function.
Starting with the second question:
Are the numbers generated completely random?
No, that is very unlikely to ever happen in a computer. They are "pseudo-random" numbers, which is some sequence of numbers that vary in range over time in a random-like fashion. But if you start with the same "seed", you get the same sequence each time. This predictability is sometimes very useful, as it allows repeating the same experiment several times with the same outcome - altering the seed, will allow a similar run to have a different outcome.
The function srand sets the seed. Some systems do have a function called randomize, but it is not part of the standard as such. If it does exist it sets the seed to something unknown to the code - such as the current time in milliseconds.
Is there some logic or principle behind that?
Yes. There are several methods for generating pseudo-randum numbers. Simple ones can be written in one or two lines of C code using regular int or long types, and just consists of taking the "current value" + some constant, multiplied by some large number and modulo some other large number.
More complex ones involve dozens of more lines of rather complicated math with large numbers - for example Mersenne Twister is a recent work that is available as source code if you search a little bit.

generating random numbers in C++ using TR1 /dev/random (resilient to <1 second runs)

I would like to generate uniform random numbers in C++ between 0 and 1, in a way which does not use the standard rand() and srand(time(NULL)) method. The reason for this is that if I run the application more than once within the same second of my clock, the seed will be exactly the same and produce the same output.
I do not want to rely on boost or OS/compiler specifics. x86 can be assumed.
It seems as though an alternate way to do this is to use TR1 (I do not have C++11) and seeding with /dev/random in some way?
Right now I have this, but it still uses time(NULL) as a seed which will not work well within 1 second runs:
#include <iostream>
#include <tr1/random>
int main()
{
std::tr1::mt19937 eng;
eng.seed(time(NULL));
std::tr1::uniform_int<int> unif(1, RAND_MAX);
int u = unif(eng);
std::cout << (float)u/RAND_MAX << std::endl;
}
Posting at request of the OP:
This is still somewhat compiler-specific, but will still work on nearly all x86-targeting compilers:
#ifdef _WIN32
// Windows
#define rdtsc __rdtsc
#else
// For everything else
unsigned long long rdtsc(){
unsigned int lo,hi;
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return ((unsigned long long)hi << 32) | lo;
}
#endif
int main()
{
std::tr1::mt19937 eng;
eng.seed( rdtsc() ); // Seed with rdtsc.
std::tr1::uniform_int<int> unif(1, RAND_MAX);
int u = unif(eng);
std::cout << (float)u/RAND_MAX << std::endl;
}
The idea here is to seed your random number generator with the rdtsc cycle-counter.
The reason why this works is because the rdtsc cycle-counter iterates at about (often the same) speed as the CPU frequency. Therefore, the chances of two calls to it returning the same value are extremely slim - thereby, making it an excellent seed for a RNG.
TR1 in [tr.rand.device] specifies a random_device class that generates unsigned ints from an implementation-dependent source. So the following should work, although I haven't compiled it myself:
int main() {
std::tr1::random_device dev_random;
std::tr1::mt19937 eng(dev_random());
...
In TR1, passing dev_random directly without calling it works and initializes eng's state more randomly, but in C++11 you have to wrap seed arguments into another class. Since calling the argument works in both libraries, I'd do that for maintainability, unless you have more demanding needs.
Your problem is related to the way you seed the random number generator. Obviously seeding with time(NULL) is going to produce the same PRNG sequence within that second when seeded. This is the most common way to seed rand, but is unfortunately bad practice because of this very issue. Not only that, I have read that it can cause bias in the results.
Note that EVERY PRNG will produce the same result if seeded with the same values. So your problem is not related to the generator, more to seeding.
I asked a question about seeding on here just a few weeks back and was given a link to the following article which you may also find useful.
Good Practice in (Pseudo) Random Number Generation for Bioinformatics Applications
See the section on seeding or warming up the generator.
rand() is not the best random number generator, but is suitable in many cases provided it is properly seeded. If you want something better where the repeat sequence is very large then there are some provided in that link. Or use the TR1 based ones. Personally, I'd go with more portable C++03 based code and steer clear of TR1.
Also consider Multiply with carry as an alternative PRNG algorithm.