Generate super random number in c++ - c++

C++11 Introduced the class that allows for generating very random numbers, it also creates an even distribution of random numbers. There is also implementation to generate a seed (a number used to make the Random Number Generator more random).
I am trying to make a function that generates a random number between min and max but I am having trouble. The function only generates the seeds and the random number once. When I call the function in other words it will keep giving me the same number.
Below is the code, I try to generate a bunch of seeds, pick one of them randomly, use that seed for the RNG and finaly produce a random number.
int Utils::GenerateSuperRandomNum(int min, int max)
{
//Seed a the RNG
int randNum;
int randIndex;
seed_seq seq{ 1, 2, 3, 4, 5 };
vector<int> seeds(5 * max);
uniform_int_distribution<int> rngDistribution(min, max); //Generates number in the range min to max.
//Generate our seed numbers.
seq.generate(seeds.begin(), seeds.end());
//Generate random index bewteen 0 and size - 1.
srand(seeds.at(0));
randIndex = rand() % seeds.size();
//Seed the RNG with a random seed from our vector.
mt19937 rngGenerator(seeds.at(randIndex));
//Get a random number.
randNum = rngDistribution(rngGenerator);
return randNum;
}

seed_seq seq{ 1, 2, 3, 4, 5 };
vector<int> seeds(5 * max);
uniform_int_distribution<int> rngDistribution(min, max); //Generates number in the range min to max.
//Generate our seed numbers.
seq.generate(seeds.begin(), seeds.end());
seq is always fed the same input {1,2,3,4,5} so always has the same state. Since it has the same state, seeds.at(0) is always the same value.
//Generate random index bewteen 0 and size - 1.
srand(seeds.at(0));
Since srand is seeded with that same value every time, it to starts with the same state every time. Since it receives the same value every time, it always starts with the same state. The same state that rand uses.
randIndex = rand() % seeds.size();
Since rand always has the same state as per the srand, it will always generate the same first number every single time.
mt19937 rngGenerator(seeds.at(randIndex));
Since randIndex is always the same value, then seeds.at(randIndex) is always the same value. Since rngGenerator is always seeded with the same value, it always has the same state.
randNum = rngDistribution(rngGenerator);
Since rngDistribution always has the same state, it always produces the same value.
This is obviously a problem. The simple fix is to seed based on the CPU temperature, or the time, or some other value that changes often.
Basically, you've seriously overthought this. It's designed to be used like this:
int Utils::GenerateSuperRandomNum(int min, int max) {
static mt19937 rngGenerator(std::random_device{}());
std::uniform_int_distribution<int> rngDistribution(min, max);
return rngDistribution(rngGenerator);
}
std::random_device{}() generates a vaguely randomish number based on magic, hopefully hardware, like maybe the CPU tempurature or something. It can be slow or have other issues, so you should only use it once per program. Namely, to seed a faster/better generator.
static mt19937 rngGenerator( creates a single global generator, which is seeded the first time the function is called, and is never seeded again. This is perfect, because we want it to be initialized once, and then just do it's magic from then on. The usage of other generators like rand don't add any entropy, so don't do that. We also don't want to re-seed it, as that might accidentally reduce randomness, rather than increase it.
std::uniform_int_distribution<int> rngDistribution(min, max); and rngDistribution(rngGenerator) you seem to understand. They use the generator to give random numbers in that distribution. Done deal.

A seed does not make a (pseudo-)random number generator more random. It provides a starting point for generating a reproducible sequence of random numbers.
Which means, if you provide the exact same seed, you'll get the exact same results.

Making a random number generator more "random" by using it to generate it's own seed is a bit like trying to lift yourself up by pulling on your boot straps. If this is just for fun the time is a sufficiently random seed, if you are doing super spy crypto a h/w device that provides true random events is what you need.
You could try using this service, I don't know if it is valid or just the NSA trying to trick you. https://www.random.org

Related

Produce a random seed to give to srand() - Not time(NULL)

I am currently writing a level generation program for the game Sokoban. I use the rand() function quite a lot to generate each level, and I thought that a nice feature would be for the user to be able to control the seed used for the generation, meaning that two people could enter the same seed and the generator would generate the same levels.
I have been using
srand(std::time(NULL));
to produce the seed which works fine and my program will generate the same levels with the same seed no problem. However, as std::time(NULL) return the system time in Milliseconds, it doesn't give very interesting or diverse numbers, i.e it would produce 1476894985, and then the next seed might be 1476897904.
To give some more interesting seeds I tried creating a random seed between 0 and 9999999999 using the following code:
typedef unsigned long long ull;
SokoGenerator::ull SokoGenerator::randomNumber(ull min, ull max, int divisor){
ull number = rand() % (max - min + 1)+ min;
while(number % divisor != 0){
number = rand() % (max - min + 1) + min;
}
return number;
}
srand(std::time(0));
genSeed = randomNumber(0, 999999999); }
srand(genSeed);
//Generate Levels After this point
But this seems to produce similar results, except they are a lot smaller now, i.e 45789, 46389, 47958.
Is there a better way to generate a good random seed between 0 and 9999999999 to give to the srand() function?
I ended up using the C++11 Uniform Distribution Random Number Generator to give me a value between 0 and 4,294,967,295 like so:
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution;
generator.seed(chrono::steady_clock::now().time_since_epoch().count());
random = distribution(generator);

C++ Random number from 1 to a very large number (e.g. 25 million)

How would you make a function that generates a random number from 1 to 25 million?
I've thought about using rand() but am I right in thinking that the maximum number, RAND_MAX is = 32000 (there about)?
Is there a way around this, a way that doesn't reduce the probability of picking very low numbers and doesn't increase the probability of picking high / medium numbers?
Edit: #Jamey D 's method worked perfectly independent of Qt.
You could (should) use the new C++11 std::uniform_real_distribution
#include <random>
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> distribution(1, 25000000);
//generating a random integer:
double random = distribution(gen);
Have a look at ran3
http://www.codeforge.com/read/33054/ran3.cpp__html
You should be able to get what you want from it.
Ran3 is (atleast when I was still doing computational modelling) faster than rand() with a more uniform distribution, though that was several years ago. It returns a random integer value.
For example, getting the source code from the link above:
int main() {
srand(time(null));
int randomNumber = ran3(rand()) % 25000000;
int nextRandomNumber = ran3(randomNumber);
}

C++ GMP Generating Random Number

I'm trying to generate a huge random number in C++ using the GMP library but am having issues figuring out the syntax. This is slightly different from other examples I've found because I need to set a floor and ceiling for the random number to be between. This is kinda what I need to do:
mpz_class high, low;
low = pow(2,199);
high = pow(2,210);
// code to use the high and low numbers to generate the random number
I know this isn't much to go on, but again, I'm not sure what the syntax would even be at this point, I've tried several things but nothing I've found enables me to tell GMP to use a high and low range for the number generation.
Thoughts?
From Gmp Lib Documentation
Function: void mpz_urandomb (mpz_t rop, gmp_randstate_t state,
mp_bitcnt_t n)
Generate a uniformly distributed random integer in the range 0 to
2^nāˆ’1, inclusive
So, take 210 - 199, and use that as n, generate a random number and add the result to pow(2,199).
If you want something more granular than a power of 2 upper limit, this won't work for you. You could try the unsigned int sized random function using the same technique above:
ā€” Function: unsigned long gmp_urandomm_ui (gmp_randstate_t state, unsigned long n)
Return a uniformly distributed random number in the range 0 to n-1, inclusive.
Here, you would find your granular range and use that for n. Then add the random number to your lower value. The limitation is n must be less than MAXUINT, usually 2^32 -1
Using the logic presented by #Less, I wrote the following to solve my problem:
void
makeprime ()
{
// *********************** VARIABLE DECLARATION *********************** //
// initilize the variables as gmp class instances
mpz_t l, rand;
unsigned long seed;
// perform inits to create variable pointers with 0 value
mpz_inits(l, rand);
//mpz_init(rand);
// calculate the random number floor
mpz_ui_pow_ui(l, 2, 199);
// initilze the state object for the random generator functions
gmp_randstate_t rstate;
// initialize state for a Mersenne Twister algorithm. This algorithm is fast and has good randomness properties.
gmp_randinit_mt(rstate);
// create the generator seed for the random engine to reference
gmp_randseed_ui(rstate, seed);
/*
Function:
int mpz_probab_prime_p (const mpz_t n, int reps)
Determine whether n is prime. Return 2 if n is definitely prime, return 1 if n is probably prime (without being certain),
or return 0 if n is definitely composite.
*/
do {
// return a uniformly distributed random number in the range 0 to n-1, inclusive.
mpz_urandomb(rand, rstate, 310);
// add the random number to the low number, which will make sure the random number is between the low and high ranges
mpz_add(rand, rand, l);
gmp_printf("randomly generated number: %Zd\n", rand);
} while ( !(mpz_probab_prime_p(rand, 25)) );
// *********************** GARBAGE COLLECTION *********************** //
// empty the memory location for the random generator state
gmp_randclear(rstate);
// clear the memory locations for the variables used to avoid leaks
mpz_clear(l);
mpz_clear(rand);
}
Thanks #Less for your logic and help!

rand() always returns the same sequence on application restart

I have the following method which generates a random number:
int random_number() //Random number generator
{
int x = rand() % 1000000 + 1; //Generate an integer between 1 and 1000000
return x;
}
The call to this method is used in a loop which iterates five times. The problem with this method is that it always seems to generate the same numbers when running the program several times. How can this be solved?
You need to seed the random number generator, such as:
srand ( time(NULL) );
int x = rand() % 1000000 + 1;
Seeding the pseudorandom number generator essentially decides on the random number set that it will iterate through. Using the time is the standard method of achieving adequately random results.
EDIT:
To clarify, you should seed only once and get many random numbers, something like this:
srand ( time(NULL) );
loop {
int x = rand() % 1000000 + 1;
}
Rather than something like:
loop {
//Particularly bad if this line is hit multiple times in one second
srand ( time(NULL) );
int x = rand() % 1000000 + 1;
}
make a call to srand(time(NULL)); when your program launches.
srand sets a seed to the rand function. Giving it the return value of time(NULL) helps getting a different seed at each program run.
As you tagged your question as c++, you could either use c++11 feature to handle random number generation.
femtoRgon is right. This will seed the program but take a look at the new c++ standard as they have improved random number generation
see
Random numbers in C++0x
rand is not really a random number, but rather a pseudo-random one that just "looks" random if you don't know the algorithm used to generate the values. From the man page:
The rand() function returns a pseudo-random integer in the range 0 to RAND_MAX inclusive
pseudo-random means that given the same input, called a seed, it will give the same output. This is actually quite useful when you're trying to debug a problem since the same "random" values will be returned, letting you reproduce the problem.
It's bad if you really need randomness.
As noted above by changing the seed to something different on each run, like say seconds since the epoch, you can get different values from your call to rand().
srand(time(NULL))
If you're trying to debug you may want to print out the seed so you can reproduce problems if they occur.

How do I generate totally a random number at a time?

I want to create 3 random number at a time (simultaneously). However, they returned me the same numbers at a time even though they are actually random. Example:
------------------------
Variable: A B C
------------------------
Time 1 : 5 5 5
Time 2 : 3 3 3
Time 3 : 9 9 9
------------------------
They suppose to be different numbers at all. From the observation, I can see that my code can only pick a random number at a time (interval 1 second). Here is my generator code that I'm using:
unsigned int CMain::GenerateRandom(int min, int max)
{
srand((unsigned)time(0));
unsigned int random_integer;
int lowest = min, highest = max;
int range = (highest - lowest) + 1;
random_integer = lowest + int(range * rand() / (RAND_MAX + 1.0));
return random_integer;
}
How could I generate a totally random numbers at a time? Please help.
Thank you.
Your issue here is you're resetting the random seed every call using the current time which you shouldn't do.
Call srand() once before querying any random numbers - that's all and more than enough.
Right now you always reset your random seed to the exact same value (as you use current time). Random numbers in PCs aren't really random at all. The same seed will always result in the same set of random numbers generated later on. This is intentional and used in e.g. savegames for games to always have the same things happen without having to save every random number generated, etc.
Don't call srand() each time you generate a new random number. Call it once at the start of your program and then just call rand() each time you need a new random number.
FYI: Values returned from rand() are not "totally random". They are pseudo-random numbers generated by an algorithm. (This is not related to your question though.)
The problem is that you are calling srand() for every iteration. Srand() is setting a seed based on the current timestamp. Therefore you only need to call srand() once, and just call rand() to generate a new pseudo-random number. I say pseudo-random because computers cannot generate truly random numbers.
Sample code:
#include <iostream>
#include <cstdlib>
int main()
{
int i, r;
srand(time(0));
for(i = 0; r <= 20000; i++)
r = rand();
return 0;
}
time(0) changes slowly. If you query GenerateRandom quickly you can get the same number multiple times.
But in general, that isn't a right way to generate random numbers. You want to seed the random number generator only once, before any other function uses it. Treat rand as a global singleton object. If any of your functions modifies its seed by calling srand, then the change will affect all other calls to rand.