Seeding a random number generator C++ [duplicate]

2019-01-20 11:02发布

问题:

This question already has an answer here:

  • How to generate a random number in C++? 10 answers

I have two questions.

  1. What other ways are there to seed a psuedo-random number generator in C++ without using srand(time(NULL))?

  2. 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.

回答1:

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);


回答2:

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();
}


回答3:

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.

}


回答4:

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.



标签: c++ random