Mysterious random number - wanting to be the same even after "srand()" [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Rand generating same numbers
The following is tried when answering another question on StackOverflow:
#include <time.h>
#include <iostream>
using namespace std;
main() {
srand ( time(NULL) );
cout << (float) rand() / RAND_MAX << endl;
cout << ((float) rand()) << endl;
cout << RAND_MAX << endl;
cout << (float) rand() / RAND_MAX << endl;
}
Very strangely, the first output number is always a similar number, either on Windows 7 with cygwin or on Mac with Leopard.
The last number is a good random number from 0 to 1. If the first cout line is commented out, the first printed random number is always a similar value one.
How could that be happening?

I have stumbled upon this phenomenon myself in the past. The first call to rand() in four sequential runs of a test program gave the following output:
27592
27595
27598
27602
Notice how similar those numbers are? This is because the random number generator is initialized with the current time, and the first result is heavily influenced by that. Similar initial values for srand yield similar initial results for rand. It's as simple as that.
This similarity is irrelevant if you calculate rand() % n, but if you go with the rand() / m approach, this is a problem. For example, if you divide rand() by 100, you will get the same number 3 times in a row!
Now let's take a look at the second result of rand() in four sequential runs:
11520
22268
248
10997
This looks much better, doesn't it? A simple quick-fix is to call rand() a few times after seeding and simply ignoring the result.
int main()
{
srand(time(0));
rand(); rand(); rand();
std::cout << rand() / float(RAND_MAX) << std::endl;
}

rand() function in VS2008 returns this: return ((current_value = current_value * 214013 + 2531011) >> 16) & 0x7fff;. This current_value you set with srand. This function is such that it will return similar pseudo random numbers for similar seeds, and there is no help about it. The problem is that those bits that are the most random in first call are eaten up with >> 16 part. To workaround the problem just roll it a few times (rand(); rand();).

Related

How do I use the rand functions output in C++?

I am trying to create a slot machine where I have to generate 3 random numbers from 2 - 7 and then use that output to give different outcomes. For example if the output is 777 and then your bet gets multiplied by 10, if it's 222 then it gets multiplied by 5. I can't seem to get the output of the rand function into a variable to use it and its not calculating properly.
Code:
This is not the full code
if (bet <= 2000)
{
std::cout << endl;
int game_num = 0;
srand (0);
for (int i = 0; i < 3; i++)
std::cout << (rand() % 1) + 2;
std::cout << endl;
if (game_num == 777)
{
bet = bet * 10;
std::cout << "You Won: " << bet << endl;
return 0;
}
else if (game_num == 222 || 333 || 444 || 555 || 666)
{
bet = bet * 5;
std::cout << "You Won: " << bet << endl;
return 0;
}
The issue is that you aren’t seeding the random number generator properly in this situation.
This will always return the same sequence of random numbers every time the program runs.
srand(0)
You want to seed the random number generator with a new value each time the program is run.
Using the timestamp at runtime will enable that behavior.
srand(time(0))
Dan's answer is correct, you're using the same seed every time, so every sequence of numbers is identical. You need to seed with a random value. Time as source of randomness isn't great in terms of being random, but it's working unless you run twice in the same second (due to time() only counting seconds, and seconds being ... long for modern computers, unlike 1970's computers, when that way of seeding was invented).
So, instead, honestly, don't use srand or rand at all. They're really bad random number generators to begin with, and their dependence on "hidden" state makes them a nightmare to deal with. Simply. Ignore their existence!
C++ brings its own random facilities:
You want a uniform integer distribution, so use uniform_int_distribution. Seed with an actual random value from actual randomness-generating events.
#include <random>
// …
// Somewhen before you need the random numbers, not every time:
// Will be used to obtain a seed for the random number engine
std::random_device real_random;
// Set up the generator for random bits, seed it from the actual random
std::mt19937 gen(real_random());
// Use that to generate random numbers in [2,7]
std::uniform_int_distribution<> distrib(2, 7);
// Where you need the randomness:
for (int i = 0; i < 3; i++)
std::cout << distrib(gen) << "\n";

What would be a good way to generate 16 bit random numbers in Visual C++? [duplicate]

I'm trying to make a game with dice, and I need to have random numbers in it (to simulate the sides of the die. I know how to make it between 1 and 6). Using
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
int main()
{
srand((unsigned)time(0));
int i;
i = (rand()%6)+1;
cout << i << "\n";
}
doesn't work very well, because when I run the program a few times, here's the output I get:
6
1
1
1
1
1
2
2
2
2
5
2
So I want a command that will generate a different random number each time, not the same one 5 times in a row. Is there a command that will do this?
Using modulo may introduce bias into the random numbers, depending on the random number generator. See this question for more info. Of course, it's perfectly possible to get repeating numbers in a random sequence.
Try some C++11 features for better distribution:
#include <random>
#include <iostream>
int main()
{
std::random_device dev;
std::mt19937 rng(dev());
std::uniform_int_distribution<std::mt19937::result_type> dist6(1,6); // distribution in range [1, 6]
std::cout << dist6(rng) << std::endl;
}
See this question/answer for more info on C++11 random numbers. The above isn't the only way to do this, but is one way.
The most fundamental problem of your test application is that you call srand once and then call rand one time and exit.
The whole point of srand function is to initialize the sequence of pseudo-random numbers with a random seed.
It means that if you pass the same value to srand in two different applications (with the same srand/rand implementation) then you will get exactly the same sequence of rand() values read after that in both applications.
BUT in your example application pseudo-random sequence consists only of one element - the first element of a pseudo-random sequence generated from seed equal to current time of 1 sec precision. What do you expect to see on output then?
Obviously when you happen to run application on the same second - you use the same seed value - thus your result is the same of course (as Martin York already mentioned in a comment to the question).
Actually you should call srand(seed) one time and then call rand() many times and analyze that sequence - it should look random.
AMENDMENT 1 - example code:
OK I get it.
Apparently verbal description is not enough (maybe language barrier or something... :) ).
Old-fashioned C code example based on the same srand()/rand()/time() functions that was used in the question:
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
int main(void)
{
unsigned long j;
srand( (unsigned)time(NULL) );
for( j = 0; j < 100500; ++j )
{
int n;
/* skip rand() readings that would make n%6 non-uniformly distributed
(assuming rand() itself is uniformly distributed from 0 to RAND_MAX) */
while( ( n = rand() ) > RAND_MAX - (RAND_MAX-5)%6 )
{ /* bad value retrieved so get next one */ }
printf( "%d,\t%d\n", n, n % 6 + 1 );
}
return 0;
}
^^^ THAT sequence from a single run of the program is supposed to look random.
Please NOTE that I don't recommend to use rand/srand functions in production code for the reasons explained below and I absolutely don't recommend to use function time as a random seed for the reasons that IMO already should be quite obvious. Those are fine for educational purposes and to illustrate the point sometimes but for any serious use they are mostly useless.
AMENDMENT 2 - detailed explanation:
It is important to understand that as of now there is NO C or C++ standard features (library functions or classes) producing actually random data definitively (i.e. guaranteed by the standard to be actually random). The only standard feature that approaches this problem is std::random_device that unfortunately still does not provide guarantees of actual randomness.
Depending on the nature of application you should first decide if you really need truly random (unpredictable) data. Notable case when you do most certainly need true randomness is information security - e.g. generating symmetric keys, asymmetric private keys, salt values, security tokens, etc.
Actually security-grade random numbers is a separate industry worth a separate article. (I briefly touch it in this answer of mine.)
In most cases Pseudo-Random Number Generator is sufficient - e.g. for scientific simulations or games. In some cases consistently defined pseudo-random sequence is even required - e.g. in games you may generate the same map(s) each time in runtime to save installation package size.
The original question and reoccurring multitude of identical/similar questions (and even many misguided "answers" to them) indicate that first and foremost it is important to distinguish random numbers from pseudo-random numbers AND to understand what is pseudo-random number sequence in the first place AND to realize that pseudo-random number generators are NOT used the same way you could use true random number generators.
Intuitively when you request random number - the result returned shouldn't depend on previously returned values and shouldn't depend if
anyone requested anything before and shouldn't depend in what moment
and by what process and on what computer and from what generator and
in what galaxy it was requested. That is what word "random" means
after all - being unpredictable and independent of anything -
otherwise it is not random anymore, right? With this intuition it is
only natural to search the web for some magic spells to cast to get
such random number in any possible context.
^^^ THAT kind of intuitive expectations IS VERY WRONG and harmful in all cases involving Pseudo-Random Number Generators - despite being reasonable for true random numbers.
While the meaningful notion of "random number" exists (kind of) - there is no such thing as "pseudo-random number". A Pseudo-Random Number Generator actually produces pseudo-random number sequence.
Pseudo-random sequence is in fact always deterministic (predetermined by its algorithm and initial parameters) - i.e. there is actually nothing random about it.
When experts talk about quality of PRNG they actually talk about statistical properties of the generated sequence (and its notable sub-sequences). For example if you combine two high quality PRNGs by using them both in turns - you may produce bad resulting sequence - despite them generating good sequences each separately (those two good sequences may simply correlate to each other and thus combine badly).
Specifically rand()/srand(s) pair of functions provide a singular per-process non-thread-safe(!) pseudo-random number sequence generated with implementation-defined algorithm. Function rand() produces values in range [0, RAND_MAX].
Quote from C11 standard (ISO/IEC 9899:2011):
The srand function uses the argument as a seed for a new sequence of
pseudo-random numbers to be returned by subsequent calls to rand. If
srand is then called with the same seed value, the sequence of
pseudo-random numbers shall be repeated. If rand is called before any
calls to srand have been made, the same sequence shall be generated as
when srand is first called with a seed value of 1.
Many people reasonably expect that rand() would produce a sequence of semi-independent uniformly distributed numbers in range 0 to RAND_MAX. Well it most certainly should (otherwise it's useless) but unfortunately not only standard doesn't require that - there is even explicit disclaimer that states "there is no guarantees as to the quality of the random sequence produced".
In some historical cases rand/srand implementation was of very bad quality indeed. Even though in modern implementations it is most likely good enough - but the trust is broken and not easy to recover.
Besides its non-thread-safe nature makes its safe usage in multi-threaded applications tricky and limited (still possible - you may just use them from one dedicated thread).
New class template std::mersenne_twister_engine<> (and its convenience typedefs - std::mt19937/std::mt19937_64 with good template parameters combination) provides per-object pseudo-random number generator defined in C++11 standard. With the same template parameters and the same initialization parameters different objects will generate exactly the same per-object output sequence on any computer in any application built with C++11 compliant standard library. The advantage of this class is its predictably high quality output sequence and full consistency across implementations.
Also there are other (much simpler) PRNG engines defined in C++11 standard - std::linear_congruential_engine<> (historically used as fair quality srand/rand algorithm in some C standard library implementations) and std::subtract_with_carry_engine<>. They also generate fully defined parameter-dependent per-object output sequences.
Modern day C++11 example replacement for the obsolete C code above:
#include <iostream>
#include <chrono>
#include <random>
int main()
{
std::random_device rd;
// seed value is designed specifically to make initialization
// parameters of std::mt19937 (instance of std::mersenne_twister_engine<>)
// different across executions of application
std::mt19937::result_type seed = rd() ^ (
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()
).count() +
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch()
).count() );
std::mt19937 gen(seed);
for( unsigned long j = 0; j < 100500; ++j )
/* ^^^Yes. Generating single pseudo-random number makes no sense
even if you use std::mersenne_twister_engine instead of rand()
and even when your seed quality is much better than time(NULL) */
{
std::mt19937::result_type n;
// reject readings that would make n%6 non-uniformly distributed
while( ( n = gen() ) > std::mt19937::max() -
( std::mt19937::max() - 5 )%6 )
{ /* bad value retrieved so get next one */ }
std::cout << n << '\t' << n % 6 + 1 << '\n';
}
return 0;
}
The version of previous code that uses std::uniform_int_distribution<>
#include <iostream>
#include <chrono>
#include <random>
int main()
{
std::random_device rd;
std::mt19937::result_type seed = rd() ^ (
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()
).count() +
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch()
).count() );
std::mt19937 gen(seed);
std::uniform_int_distribution<unsigned> distrib(1, 6);
for( unsigned long j = 0; j < 100500; ++j )
{
std::cout << distrib(gen) << ' ';
}
std::cout << '\n';
return 0;
}
Whenever you do a basic web search for random number generation in the C++ programming language this question is usually the first to pop up! I want to throw my hat into the ring to hopefully better clarify the concept of pseudo-random number generation in C++ for future coders that will inevitably search this same question on the web!
The Basics
Pseudo-random number generation involves the process of utilizing a deterministic algorithm that produces a sequence of numbers whose properties approximately resemble random numbers. I say approximately resemble, because true randomness is a rather elusive mystery in mathematics and computer science. Hence, why the term pseudo-random is utilized to be more pedantically correct!
Before you can actually use a PRNG, i.e., pseudo-random number generator, you must provide the algorithm with an initial value often referred too as the seed. However, the seed must only be set once before using the algorithm itself!
/// Proper way!
seed( 1234 ) /// Seed set only once...
for( x in range( 0, 10) ):
PRNG( seed ) /// Will work as expected
/// Wrong way!
for( x in rang( 0, 10 ) ):
seed( 1234 ) /// Seed reset for ten iterations!
PRNG( seed ) /// Output will be the same...
Thus, if you want a good sequence of numbers, then you must provide an ample seed to the PRNG!
The Old C Way
The backwards compatible standard library of C that C++ has, uses what is called a linear congruential generator found in the cstdlib header file! This PRNG functions through a discontinuous piecewise function that utilizes modular arithmetic, i.e., a quick algorithm that likes to use the modulo operator '%'. The following is common usage of this PRNG, with regards to the original question asked by #Predictability:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main( void )
{
int low_dist = 1;
int high_dist = 6;
std::srand( ( unsigned int )std::time( nullptr ) );
for( int repetition = 0; repetition < 10; ++repetition )
std::cout << low_dist + std::rand() % ( high_dist - low_dist ) << std::endl;
return 0;
}
The common usage of C's PRNG houses a whole host of issues such as:
The overall interface of std::rand() isn't very intuitive for the proper generation of pseudo-random numbers between a given range, e.g., producing numbers between [1, 6] the way #Predictability wanted.
The common usage of std::rand() eliminates the possibility of a uniform distribution of pseudo-random numbers, because of the Pigeonhole Principle.
The common way std::rand() gets seeded through std::srand( ( unsigned int )std::time( nullptr ) ) technically isn't correct, because time_t is considered to be a restricted type. Therefore, the conversion from time_t to unsigned int is not guaranteed!
For more detailed information about the overall issues of using C's PRNG, and how to possibly circumvent them, please refer to Using rand() (C/C++): Advice for the C standard library’s rand() function!
The Standard C++ Way
Since the ISO/IEC 14882:2011 standard was published, i.e., C++11, the random library has been apart of the C++ programming language for a while now. This library comes equipped with multiple PRNGs, and different distribution types such as: uniform distribution, normal distribution, binomial distribution, etc. The following source code example demonstrates a very basic usage of the random library, with regards to #Predictability's original question:
#include <iostream>
#include <cctype>
#include <random>
using u32 = uint_least32_t;
using engine = std::mt19937;
int main( void )
{
std::random_device os_seed;
const u32 seed = os_seed();
engine generator( seed );
std::uniform_int_distribution< u32 > distribute( 1, 6 );
for( int repetition = 0; repetition < 10; ++repetition )
std::cout << distribute( generator ) << std::endl;
return 0;
}
The 32-bit Mersenne Twister engine, with a uniform distribution of integer values was utilized in the above example. (The name of the engine in source code sounds weird, because its name comes from its period of 2^19937-1 ). The example also uses std::random_device to seed the engine, which obtains its value from the operating system (If you are using a Linux system, then std::random_device returns a value from /dev/urandom).
Take note, that you do not have to use std::random_device to seed any engine. You can use constants or even the chrono library! You also don't have to use the 32-bit version of the std::mt19937 engine, there are other options! For more information about the capabilities of the random library, please refer to cplusplus.com
All in all, C++ programmers should not use std::rand() anymore, not because its bad, but because the current standard provides better alternatives that are more straight forward and reliable. Hopefully, many of you find this helpful, especially those of you who recently web searched generating random numbers in c++!
If you are using boost libs you can obtain a random generator in this way:
#include <iostream>
#include <string>
// Used in randomization
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
using namespace std;
using namespace boost;
int current_time_nanoseconds(){
struct timespec tm;
clock_gettime(CLOCK_REALTIME, &tm);
return tm.tv_nsec;
}
int main (int argc, char* argv[]) {
unsigned int dice_rolls = 12;
random::mt19937 rng(current_time_nanoseconds());
random::uniform_int_distribution<> six(1,6);
for(unsigned int i=0; i<dice_rolls; i++){
cout << six(rng) << endl;
}
}
Where the function current_time_nanoseconds() gives the current time in nanoseconds which is used as a seed.
Here is a more general class to get random integers and dates in a range:
#include <iostream>
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include "boost/date_time/posix_time/posix_time.hpp"
#include "boost/date_time/gregorian/gregorian.hpp"
using namespace std;
using namespace boost;
using namespace boost::posix_time;
using namespace boost::gregorian;
class Randomizer {
private:
static const bool debug_mode = false;
random::mt19937 rng_;
// The private constructor so that the user can not directly instantiate
Randomizer() {
if(debug_mode==true){
this->rng_ = random::mt19937();
}else{
this->rng_ = random::mt19937(current_time_nanoseconds());
}
};
int current_time_nanoseconds(){
struct timespec tm;
clock_gettime(CLOCK_REALTIME, &tm);
return tm.tv_nsec;
}
// C++ 03
// ========
// Dont forget to declare these two. You want to make sure they
// are unacceptable otherwise you may accidentally get copies of
// your singleton appearing.
Randomizer(Randomizer const&); // Don't Implement
void operator=(Randomizer const&); // Don't implement
public:
static Randomizer& get_instance(){
// The only instance of the class is created at the first call get_instance ()
// and will be destroyed only when the program exits
static Randomizer instance;
return instance;
}
bool method() { return true; };
int rand(unsigned int floor, unsigned int ceil){
random::uniform_int_distribution<> rand_ = random::uniform_int_distribution<> (floor,ceil);
return (rand_(rng_));
}
// Is not considering the millisecons
time_duration rand_time_duration(){
boost::posix_time::time_duration floor(0, 0, 0, 0);
boost::posix_time::time_duration ceil(23, 59, 59, 0);
unsigned int rand_seconds = rand(floor.total_seconds(), ceil.total_seconds());
return seconds(rand_seconds);
}
date rand_date_from_epoch_to_now(){
date now = second_clock::local_time().date();
return rand_date_from_epoch_to_ceil(now);
}
date rand_date_from_epoch_to_ceil(date ceil_date){
date epoch = ptime(date(1970,1,1)).date();
return rand_date_in_interval(epoch, ceil_date);
}
date rand_date_in_interval(date floor_date, date ceil_date){
return rand_ptime_in_interval(ptime(floor_date), ptime(ceil_date)).date();
}
ptime rand_ptime_from_epoch_to_now(){
ptime now = second_clock::local_time();
return rand_ptime_from_epoch_to_ceil(now);
}
ptime rand_ptime_from_epoch_to_ceil(ptime ceil_date){
ptime epoch = ptime(date(1970,1,1));
return rand_ptime_in_interval(epoch, ceil_date);
}
ptime rand_ptime_in_interval(ptime floor_date, ptime ceil_date){
time_duration const diff = ceil_date - floor_date;
long long gap_seconds = diff.total_seconds();
long long step_seconds = Randomizer::get_instance().rand(0, gap_seconds);
return floor_date + seconds(step_seconds);
}
};
#include <iostream>
#include <cstdlib>
#include <ctime>
int main() {
srand(time(NULL));
int random_number = std::rand(); // rand() return a number between ​0​ and RAND_MAX
std::cout << random_number;
return 0;
}
http://en.cppreference.com/w/cpp/numeric/random/rand
Can get full Randomer class code for generating random numbers from here!
If you need random numbers in different parts of the project you can create a separate class Randomer to incapsulate all the random stuff inside it.
Something like that:
class Randomer {
// random seed by default
std::mt19937 gen_;
std::uniform_int_distribution<size_t> dist_;
public:
/* ... some convenient ctors ... */
Randomer(size_t min, size_t max, unsigned int seed = std::random_device{}())
: gen_{seed}, dist_{min, max} {
}
// if you want predictable numbers
void SetSeed(unsigned int seed) {
gen_.seed(seed);
}
size_t operator()() {
return dist_(gen_);
}
};
Such a class would be handy later on:
int main() {
Randomer randomer{0, 10};
std::cout << randomer() << "\n";
}
You can check this link as an example how i use such Randomer class to generate random strings. You can also use Randomer if you wish.
Generate a different random number each time, not the same one six times in a row.
Use case scenario
I likened Predictability's problem to a bag of six bits of paper, each with a value from 0 to 5 written on it. A piece of paper is drawn from the bag each time a new value is required. If the bag is empty, then the numbers are put back into the bag.
...from this, I can create an algorithm of sorts.
Algorithm
A bag is usually a Collection. I chose a bool[] (otherwise known as a boolean array, bit plane or bit map) to take the role of the bag.
The reason I chose a bool[] is because the index of each item is already the value of each piece of paper. If the papers required anything else written on them then I would have used a Dictionary<string, bool> in its place. The boolean value is used to keep track of whether the number has been drawn yet or not.
A counter called RemainingNumberCount is initialised to 5 that counts down as a random number is chosen. This saves us from having to count how many pieces of paper are left each time we wish to draw a new number.
To select the next random value I'm using a for..loop to scan through the bag of indexes, and a counter to count off when an index is false called NumberOfMoves.
NumberOfMoves is used to choose the next available number. NumberOfMoves is first set to be a random value between 0 and 5, because there are 0..5 available steps we can make through the bag. On the next iteration NumberOfMoves is set to be a random value between 0 and 4, because there are now 0..4 steps we can make through the bag. As the numbers are used, the available numbers reduce so we instead use rand() % (RemainingNumberCount + 1) to calculate the next value for NumberOfMoves.
When the NumberOfMoves counter reaches zero, the for..loop should as follows:
Set the current Value to be the same as for..loop's index.
Set all the numbers in the bag to false.
Break from the for..loop.
Code
The code for the above solution is as follows:
(put the following three blocks into the main .cpp file one after the other)
#include "stdafx.h"
#include <ctime>
#include <iostream>
#include <string>
class RandomBag {
public:
int Value = -1;
RandomBag() {
ResetBag();
}
void NextValue() {
int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);
int NumberOfMoves = rand() % (RemainingNumberCount + 1);
for (int i = 0; i < BagOfNumbersLength; i++)
if (BagOfNumbers[i] == 0) {
NumberOfMoves--;
if (NumberOfMoves == -1)
{
Value = i;
BagOfNumbers[i] = 1;
break;
}
}
if (RemainingNumberCount == 0) {
RemainingNumberCount = 5;
ResetBag();
}
else
RemainingNumberCount--;
}
std::string ToString() {
return std::to_string(Value);
}
private:
bool BagOfNumbers[6];
int RemainingNumberCount;
int NumberOfMoves;
void ResetBag() {
RemainingNumberCount = 5;
NumberOfMoves = rand() % 6;
int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);
for (int i = 0; i < BagOfNumbersLength; i++)
BagOfNumbers[i] = 0;
}
};
A Console class
I create this Console class because it makes it easy to redirect output.
Below in the code...
Console::WriteLine("The next value is " + randomBag.ToString());
...can be replaced by...
std::cout << "The next value is " + randomBag.ToString() << std::endl;
...and then this Console class can be deleted if desired.
class Console {
public:
static void WriteLine(std::string s) {
std::cout << s << std::endl;
}
};
Main method
Example usage as follows:
int main() {
srand((unsigned)time(0)); // Initialise random seed based on current time
RandomBag randomBag;
Console::WriteLine("First set of six...\n");
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
Console::WriteLine("\nSecond set of six...\n");
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
Console::WriteLine("\nThird set of six...\n");
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
Console::WriteLine("\nProcess complete.\n");
system("pause");
}
Example output
When I ran the program, I got the following output:
First set of six...
The next value is 2
The next value is 3
The next value is 4
The next value is 5
The next value is 0
The next value is 1
Second set of six...
The next value is 3
The next value is 4
The next value is 2
The next value is 0
The next value is 1
The next value is 5
Third set of six...
The next value is 4
The next value is 5
The next value is 2
The next value is 0
The next value is 3
The next value is 1
Process complete.
Press any key to continue . . .
Closing statement
This program was written using Visual Studio 2017, and I chose to make it a Visual C++ Windows Console Application project using .Net 4.6.1.
I'm not doing anything particularly special here, so the code should work on earlier versions of Visual Studio too.
A very opinionated answer
The c++ <random> library violates one of the best principles of software engineering: "Simple things done simple, complex, uncommon things can be a bit more complex."
Instead, they make even the simple and common use cases overly complex, just because they suffer from a cultural disease, fearing comments like "This is not general enough."
As a result, now whenever you want a simple random number, you have to look into the documentation, read stack overflow with walls of text, glorifying this terrible design, instead of it just being an easy-to-remember one or 2 liner. (Common Lisp is more pragmatic: (random 5) yields uniformly distributed integers from 0..4 and (random 1.0) yields real numbers between 0.0..1.0. That is the most common use case and it is at your finger tips. If you need more sophisticated stuff, you have to find packages and libraries or do it yourself.)
Just calculate the across the globe accrued man hours of everyone wasting time on understanding that header and its contents to see how bad it is.
Even I am wasting my time now, writing this answer and you waste your time, reading it, just because they created a piece of complex puzzle, which is in kindred spirit with other modern abominations, such as the Vulkan API.
So, how to cope with it? Waste your time once, write yourself a header file for your most common use cases and then just re-use it whenever you need it.
Here is a solution. Create a function that returns the random number and place it
outside the main function to make it global. Hope this helps
#include <iostream>
#include <cstdlib>
#include <ctime>
int rollDie();
using std::cout;
int main (){
srand((unsigned)time(0));
int die1;
int die2;
for (int n=10; n>0; n--){
die1 = rollDie();
die2 = rollDie();
cout << die1 << " + " << die2 << " = " << die1 + die2 << "\n";
}
system("pause");
return 0;
}
int rollDie(){
return (rand()%6)+1;
}
This code produces random numbers from n to m.
int random(int from, int to){
return rand() % (to - from + 1) + from;
}
example:
int main(){
srand(time(0));
cout << random(0, 99) << "\n";
}
for random every RUN file
size_t randomGenerator(size_t min, size_t max) {
std::mt19937 rng;
rng.seed(std::random_device()());
//rng.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
std::uniform_int_distribution<std::mt19937::result_type> dist(min, max);
return dist(rng);
}
I know how to generate random number in C++ without using any headers, compiler intrinsics or whatever.
#include <cstdio> // Just for printf
int main() {
auto val = new char[0x10000];
auto num = reinterpret_cast<unsigned long long>(val);
delete[] val;
num = num / 0x1000 % 10;
printf("%llu\n", num);
}
I got the following stats after run for some period of time:
0: 5268
1: 5284
2: 5279
3: 5242
4: 5191
5: 5135
6: 5183
7: 5236
8: 5372
9: 5343
Looks random.
How it works:
Modern compilers protect you from buffer overflow using ASLR (address space layout randomization).
So you can generate some random numbers without using any libraries, but it is just for fun. Do not use ASLR like that.
Here my 5 cents:
// System includes
#include <iostream>
#include <algorithm>
#include <chrono>
#include <random>
// Application includes
// Namespace
using namespace std;
// Constants
#define A_UNUSED(inVariable) (void)inVariable;
int main(int inCounter, char* inArguments[]) {
A_UNUSED(inCounter);
A_UNUSED(inArguments);
std::random_device oRandomDevice;
mt19937_64 oNumber;
std::mt19937_64::result_type oSeed;
std::mt19937_64::result_type oValue1;
std::mt19937_64::result_type oValue2;
for (int i = 0; i < 20; i++) {
oValue1 = (std::mt19937_64::result_type) std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
oValue2 = (std::mt19937_64::result_type) std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
oSeed = oRandomDevice() ^ (oValue1 + oValue2);
oNumber.seed(oSeed);
cout << "oNumber: " << oNumber << "\n";
cout << "oNumber.default_seed: " << oNumber.default_seed << "\n";
cout << "oNumber.initialization_multiplier: " << oNumber.initialization_multiplier << "\n";
cout << "oNumber.mask_bits: " << oNumber.mask_bits << "\n";
cout << "oNumber.max(): " << oNumber.max() << "\n";
cout << "oNumber.min(): " << oNumber.min() << "\n";
cout << "oNumber.shift_size: " << oNumber.shift_size << "\n";
cout << "oNumber.state_size: " << oNumber.state_size << "\n";
cout << "oNumber.tempering_b: " << oNumber.tempering_b << "\n";
cout << "oNumber.tempering_c: " << oNumber.tempering_c << "\n";
cout << "oNumber.tempering_d: " << oNumber.tempering_d << "\n";
cout << "oNumber.tempering_l: " << oNumber.tempering_l << "\n";
cout << "oNumber.tempering_s: " << oNumber.tempering_s << "\n";
cout << "oNumber.tempering_t: " << oNumber.tempering_t << "\n";
cout << "oNumber.tempering_u: " << oNumber.tempering_u << "\n";
cout << "oNumber.word_size: " << oNumber.word_size << "\n";
cout << "oNumber.xor_mask: " << oNumber.xor_mask << "\n";
cout << "oNumber._Max: " << oNumber._Max << "\n";
cout << "oNumber._Min: " << oNumber._Min << "\n";
}
cout << "Random v2" << endl;
return 0;
}
Here is a simple random generator with approx. equal probability of generating positive and negative values around 0:
int getNextRandom(const size_t lim)
{
int nextRand = rand() % lim;
int nextSign = rand() % lim;
if (nextSign < lim / 2)
return -nextRand;
return nextRand;
}
int main()
{
srand(time(NULL));
int r = getNextRandom(100);
cout << r << endl;
return 0;
}

My random number generator is printing duplicate numbers [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
srand() — why call it only once?
(7 answers)
Closed 7 years ago.
I'm working on a program that uses a function that would generate 2 random integers that I would later use to ask the user to add and figure out the sum. For the time being, I came across a problem in which it's duplicating the same number.
Here's the program thus far:
#include<iostream>
#include<ctime>
using namespace std;
/*
This function generates a random integer
between 0 and max_int
*/
int get_rand_int(int max_int){
srand(time(0));
return int(rand()) % max_int;
}
This program generates random addition problems
with integers between 0 and 100
int main(){
int num1 = get_rand_int(101);
int num2 = get_rand_int(101);
cout << num1 << endl;
cout << num2 << endl;
Please note this this is a homework problem my teacher assigned. He provided us with the skeleton and we're trying to fill in the blanks. I have a feeling the problem lies within the srand section of my function but that was part of my teacher's work so I'm not sure whether I need to touch that. Thanks in advance.
Yes. srand initializes the random sequence with the result of time. However, time changes only once per second! This means that if you call your function twice in a one-second delay, you get the same number.
One solution is to call srand just once, at the beginning of your program (in the main function, for instance).
You must seed the random generator only once in your program,
srand(time(0)); // this must happen only once, at the beginning of main()
You now seed it inside the function get_rand_int, and call the function twice in a very short amount of time. The seed ends up being the same, so you get the same sequence of numbers.
Call the srand(time(0)) in the main to set the current time only once to use random generation instantly.
int main(){
srand(time(0));
int num1 = get_rand_int(101);
int num2 = get_rand_int(101);
cout << num1 << endl;
cout << num2 << endl;
}

Does using a modulus with rand() limit results?

This is a program created for a game, in which I am using rand() to try and generate randomly what types of trees can be found at a settlement. The seed for rand() has been set to time in main.cpp so that it is unique each time. My question here however is about my modulus: trees[x]=rand()%40;
If I understand how rand() works correctly, once it outputs a number it has already outputted, it will repeat the same number sequence it has already because it uses a formula. Is using the modulus limiting my program to only produce 40 different random number sequences? Or does it continue to draw the new random number for each of the following arrays from the system clock?
#include <stdafx.h>
#include <iostream>
#include <cstdlib> // for rand() and srand()
#include <ctime> // for time()
using namespace std;
int forestdeterminator()
{
int trees[32];
for (int x=0; x<32; ++x)
trees[x]=rand()%40;
if (trees[0]>=1 && trees[0]<=9)
cout << "Birch Trees" << endl;
if (trees[1]>=1 && trees[1]<=3)
cout << "Mahogany Trees" << endl;
if (trees[2]>=1 && trees[2]<=20)
cout << "Oak Trees" << endl;
if (trees[3]>=1 && trees[3]<=4)
cout << "Cherry Trees" << endl;
if (trees[4]==1)
cout << "Tigerwood Trees" << endl;
if (trees[5]==1)
cout << "Swampwood Trees (Swamp Only)" << endl;
if (trees[6]>=1 && trees[6]<=8)
cout << "Yew Trees" << endl;
if (trees[7]==1)
cout << "Petrified Trees" << endl;
if (trees[8]>=1 && trees[8]<=24)
cout << "Pine Trees" << endl;
if etc etc...
No. You are only using the result of the rand() function, so it has absolutely no effect on the output of the PRNG. Only if you used rand()%40 to successively seed the PRNG would you run into that limit.
Also, note that a PRNG is typically only seeded from the system clock once, at its initialization. From there on, each number "depends" on the previously outputted one.
Finally, be aware that using a modulus on the output of a PRNG will in almost all cases skew the resulting probability distribution. This effect is very very small, for small modulus, but may be important to consider, depending on your application.
Is using the modulus limiting my program to only produce 40 different random number sequences?
Sequences, debatable. Numbers. Definitely. You can't have effective randomness with only 40 possible outputs; there's just not enough freedom there to fluctuate. But no, you're not effecting the numbers that are outputted, you're just heavily limiting what the output of your program is.
what you do is put 32 (pseudo)randomly generated integers in range from 0 to 39 to an array called trees. doing this doesn't affect how the function rand() works. it'll keep generating numbers from the full scope, no matter what operations you apply to it's former results.
so, if I understand you, the answer is: no, using rand()%40 somewhere in your code won't magically make the rand() function generate only numbers from range 0-39.

How to generate a random number in C++?

I'm trying to make a game with dice, and I need to have random numbers in it (to simulate the sides of the die. I know how to make it between 1 and 6). Using
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
int main()
{
srand((unsigned)time(0));
int i;
i = (rand()%6)+1;
cout << i << "\n";
}
doesn't work very well, because when I run the program a few times, here's the output I get:
6
1
1
1
1
1
2
2
2
2
5
2
So I want a command that will generate a different random number each time, not the same one 5 times in a row. Is there a command that will do this?
Using modulo may introduce bias into the random numbers, depending on the random number generator. See this question for more info. Of course, it's perfectly possible to get repeating numbers in a random sequence.
Try some C++11 features for better distribution:
#include <random>
#include <iostream>
int main()
{
std::random_device dev;
std::mt19937 rng(dev());
std::uniform_int_distribution<std::mt19937::result_type> dist6(1,6); // distribution in range [1, 6]
std::cout << dist6(rng) << std::endl;
}
See this question/answer for more info on C++11 random numbers. The above isn't the only way to do this, but is one way.
The most fundamental problem of your test application is that you call srand once and then call rand one time and exit.
The whole point of srand function is to initialize the sequence of pseudo-random numbers with a random seed.
It means that if you pass the same value to srand in two different applications (with the same srand/rand implementation) then you will get exactly the same sequence of rand() values read after that in both applications.
BUT in your example application pseudo-random sequence consists only of one element - the first element of a pseudo-random sequence generated from seed equal to current time of 1 sec precision. What do you expect to see on output then?
Obviously when you happen to run application on the same second - you use the same seed value - thus your result is the same of course (as Martin York already mentioned in a comment to the question).
Actually you should call srand(seed) one time and then call rand() many times and analyze that sequence - it should look random.
AMENDMENT 1 - example code:
OK I get it.
Apparently verbal description is not enough (maybe language barrier or something... :) ).
Old-fashioned C code example based on the same srand()/rand()/time() functions that was used in the question:
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
int main(void)
{
unsigned long j;
srand( (unsigned)time(NULL) );
for( j = 0; j < 100500; ++j )
{
int n;
/* skip rand() readings that would make n%6 non-uniformly distributed
(assuming rand() itself is uniformly distributed from 0 to RAND_MAX) */
while( ( n = rand() ) > RAND_MAX - (RAND_MAX-5)%6 )
{ /* bad value retrieved so get next one */ }
printf( "%d,\t%d\n", n, n % 6 + 1 );
}
return 0;
}
^^^ THAT sequence from a single run of the program is supposed to look random.
Please NOTE that I don't recommend to use rand/srand functions in production code for the reasons explained below and I absolutely don't recommend to use function time as a random seed for the reasons that IMO already should be quite obvious. Those are fine for educational purposes and to illustrate the point sometimes but for any serious use they are mostly useless.
AMENDMENT 2 - detailed explanation:
It is important to understand that as of now there is NO C or C++ standard features (library functions or classes) producing actually random data definitively (i.e. guaranteed by the standard to be actually random). The only standard feature that approaches this problem is std::random_device that unfortunately still does not provide guarantees of actual randomness.
Depending on the nature of application you should first decide if you really need truly random (unpredictable) data. Notable case when you do most certainly need true randomness is information security - e.g. generating symmetric keys, asymmetric private keys, salt values, security tokens, etc.
Actually security-grade random numbers is a separate industry worth a separate article. (I briefly touch it in this answer of mine.)
In most cases Pseudo-Random Number Generator is sufficient - e.g. for scientific simulations or games. In some cases consistently defined pseudo-random sequence is even required - e.g. in games you may generate the same map(s) each time in runtime to save installation package size.
The original question and reoccurring multitude of identical/similar questions (and even many misguided "answers" to them) indicate that first and foremost it is important to distinguish random numbers from pseudo-random numbers AND to understand what is pseudo-random number sequence in the first place AND to realize that pseudo-random number generators are NOT used the same way you could use true random number generators.
Intuitively when you request random number - the result returned shouldn't depend on previously returned values and shouldn't depend if
anyone requested anything before and shouldn't depend in what moment
and by what process and on what computer and from what generator and
in what galaxy it was requested. That is what word "random" means
after all - being unpredictable and independent of anything -
otherwise it is not random anymore, right? With this intuition it is
only natural to search the web for some magic spells to cast to get
such random number in any possible context.
^^^ THAT kind of intuitive expectations IS VERY WRONG and harmful in all cases involving Pseudo-Random Number Generators - despite being reasonable for true random numbers.
While the meaningful notion of "random number" exists (kind of) - there is no such thing as "pseudo-random number". A Pseudo-Random Number Generator actually produces pseudo-random number sequence.
Pseudo-random sequence is in fact always deterministic (predetermined by its algorithm and initial parameters) - i.e. there is actually nothing random about it.
When experts talk about quality of PRNG they actually talk about statistical properties of the generated sequence (and its notable sub-sequences). For example if you combine two high quality PRNGs by using them both in turns - you may produce bad resulting sequence - despite them generating good sequences each separately (those two good sequences may simply correlate to each other and thus combine badly).
Specifically rand()/srand(s) pair of functions provide a singular per-process non-thread-safe(!) pseudo-random number sequence generated with implementation-defined algorithm. Function rand() produces values in range [0, RAND_MAX].
Quote from C11 standard (ISO/IEC 9899:2011):
The srand function uses the argument as a seed for a new sequence of
pseudo-random numbers to be returned by subsequent calls to rand. If
srand is then called with the same seed value, the sequence of
pseudo-random numbers shall be repeated. If rand is called before any
calls to srand have been made, the same sequence shall be generated as
when srand is first called with a seed value of 1.
Many people reasonably expect that rand() would produce a sequence of semi-independent uniformly distributed numbers in range 0 to RAND_MAX. Well it most certainly should (otherwise it's useless) but unfortunately not only standard doesn't require that - there is even explicit disclaimer that states "there is no guarantees as to the quality of the random sequence produced".
In some historical cases rand/srand implementation was of very bad quality indeed. Even though in modern implementations it is most likely good enough - but the trust is broken and not easy to recover.
Besides its non-thread-safe nature makes its safe usage in multi-threaded applications tricky and limited (still possible - you may just use them from one dedicated thread).
New class template std::mersenne_twister_engine<> (and its convenience typedefs - std::mt19937/std::mt19937_64 with good template parameters combination) provides per-object pseudo-random number generator defined in C++11 standard. With the same template parameters and the same initialization parameters different objects will generate exactly the same per-object output sequence on any computer in any application built with C++11 compliant standard library. The advantage of this class is its predictably high quality output sequence and full consistency across implementations.
Also there are other (much simpler) PRNG engines defined in C++11 standard - std::linear_congruential_engine<> (historically used as fair quality srand/rand algorithm in some C standard library implementations) and std::subtract_with_carry_engine<>. They also generate fully defined parameter-dependent per-object output sequences.
Modern day C++11 example replacement for the obsolete C code above:
#include <iostream>
#include <chrono>
#include <random>
int main()
{
std::random_device rd;
// seed value is designed specifically to make initialization
// parameters of std::mt19937 (instance of std::mersenne_twister_engine<>)
// different across executions of application
std::mt19937::result_type seed = rd() ^ (
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()
).count() +
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch()
).count() );
std::mt19937 gen(seed);
for( unsigned long j = 0; j < 100500; ++j )
/* ^^^Yes. Generating single pseudo-random number makes no sense
even if you use std::mersenne_twister_engine instead of rand()
and even when your seed quality is much better than time(NULL) */
{
std::mt19937::result_type n;
// reject readings that would make n%6 non-uniformly distributed
while( ( n = gen() ) > std::mt19937::max() -
( std::mt19937::max() - 5 )%6 )
{ /* bad value retrieved so get next one */ }
std::cout << n << '\t' << n % 6 + 1 << '\n';
}
return 0;
}
The version of previous code that uses std::uniform_int_distribution<>
#include <iostream>
#include <chrono>
#include <random>
int main()
{
std::random_device rd;
std::mt19937::result_type seed = rd() ^ (
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()
).count() +
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch()
).count() );
std::mt19937 gen(seed);
std::uniform_int_distribution<unsigned> distrib(1, 6);
for( unsigned long j = 0; j < 100500; ++j )
{
std::cout << distrib(gen) << ' ';
}
std::cout << '\n';
return 0;
}
Whenever you do a basic web search for random number generation in the C++ programming language this question is usually the first to pop up! I want to throw my hat into the ring to hopefully better clarify the concept of pseudo-random number generation in C++ for future coders that will inevitably search this same question on the web!
The Basics
Pseudo-random number generation involves the process of utilizing a deterministic algorithm that produces a sequence of numbers whose properties approximately resemble random numbers. I say approximately resemble, because true randomness is a rather elusive mystery in mathematics and computer science. Hence, why the term pseudo-random is utilized to be more pedantically correct!
Before you can actually use a PRNG, i.e., pseudo-random number generator, you must provide the algorithm with an initial value often referred too as the seed. However, the seed must only be set once before using the algorithm itself!
/// Proper way!
seed( 1234 ) /// Seed set only once...
for( x in range( 0, 10) ):
PRNG( seed ) /// Will work as expected
/// Wrong way!
for( x in rang( 0, 10 ) ):
seed( 1234 ) /// Seed reset for ten iterations!
PRNG( seed ) /// Output will be the same...
Thus, if you want a good sequence of numbers, then you must provide an ample seed to the PRNG!
The Old C Way
The backwards compatible standard library of C that C++ has, uses what is called a linear congruential generator found in the cstdlib header file! This PRNG functions through a discontinuous piecewise function that utilizes modular arithmetic, i.e., a quick algorithm that likes to use the modulo operator '%'. The following is common usage of this PRNG, with regards to the original question asked by #Predictability:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main( void )
{
int low_dist = 1;
int high_dist = 6;
std::srand( ( unsigned int )std::time( nullptr ) );
for( int repetition = 0; repetition < 10; ++repetition )
std::cout << low_dist + std::rand() % ( high_dist - low_dist ) << std::endl;
return 0;
}
The common usage of C's PRNG houses a whole host of issues such as:
The overall interface of std::rand() isn't very intuitive for the proper generation of pseudo-random numbers between a given range, e.g., producing numbers between [1, 6] the way #Predictability wanted.
The common usage of std::rand() eliminates the possibility of a uniform distribution of pseudo-random numbers, because of the Pigeonhole Principle.
The common way std::rand() gets seeded through std::srand( ( unsigned int )std::time( nullptr ) ) technically isn't correct, because time_t is considered to be a restricted type. Therefore, the conversion from time_t to unsigned int is not guaranteed!
For more detailed information about the overall issues of using C's PRNG, and how to possibly circumvent them, please refer to Using rand() (C/C++): Advice for the C standard library’s rand() function!
The Standard C++ Way
Since the ISO/IEC 14882:2011 standard was published, i.e., C++11, the random library has been apart of the C++ programming language for a while now. This library comes equipped with multiple PRNGs, and different distribution types such as: uniform distribution, normal distribution, binomial distribution, etc. The following source code example demonstrates a very basic usage of the random library, with regards to #Predictability's original question:
#include <iostream>
#include <cctype>
#include <random>
using u32 = uint_least32_t;
using engine = std::mt19937;
int main( void )
{
std::random_device os_seed;
const u32 seed = os_seed();
engine generator( seed );
std::uniform_int_distribution< u32 > distribute( 1, 6 );
for( int repetition = 0; repetition < 10; ++repetition )
std::cout << distribute( generator ) << std::endl;
return 0;
}
The 32-bit Mersenne Twister engine, with a uniform distribution of integer values was utilized in the above example. (The name of the engine in source code sounds weird, because its name comes from its period of 2^19937-1 ). The example also uses std::random_device to seed the engine, which obtains its value from the operating system (If you are using a Linux system, then std::random_device returns a value from /dev/urandom).
Take note, that you do not have to use std::random_device to seed any engine. You can use constants or even the chrono library! You also don't have to use the 32-bit version of the std::mt19937 engine, there are other options! For more information about the capabilities of the random library, please refer to cplusplus.com
All in all, C++ programmers should not use std::rand() anymore, not because its bad, but because the current standard provides better alternatives that are more straight forward and reliable. Hopefully, many of you find this helpful, especially those of you who recently web searched generating random numbers in c++!
If you are using boost libs you can obtain a random generator in this way:
#include <iostream>
#include <string>
// Used in randomization
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
using namespace std;
using namespace boost;
int current_time_nanoseconds(){
struct timespec tm;
clock_gettime(CLOCK_REALTIME, &tm);
return tm.tv_nsec;
}
int main (int argc, char* argv[]) {
unsigned int dice_rolls = 12;
random::mt19937 rng(current_time_nanoseconds());
random::uniform_int_distribution<> six(1,6);
for(unsigned int i=0; i<dice_rolls; i++){
cout << six(rng) << endl;
}
}
Where the function current_time_nanoseconds() gives the current time in nanoseconds which is used as a seed.
Here is a more general class to get random integers and dates in a range:
#include <iostream>
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include "boost/date_time/posix_time/posix_time.hpp"
#include "boost/date_time/gregorian/gregorian.hpp"
using namespace std;
using namespace boost;
using namespace boost::posix_time;
using namespace boost::gregorian;
class Randomizer {
private:
static const bool debug_mode = false;
random::mt19937 rng_;
// The private constructor so that the user can not directly instantiate
Randomizer() {
if(debug_mode==true){
this->rng_ = random::mt19937();
}else{
this->rng_ = random::mt19937(current_time_nanoseconds());
}
};
int current_time_nanoseconds(){
struct timespec tm;
clock_gettime(CLOCK_REALTIME, &tm);
return tm.tv_nsec;
}
// C++ 03
// ========
// Dont forget to declare these two. You want to make sure they
// are unacceptable otherwise you may accidentally get copies of
// your singleton appearing.
Randomizer(Randomizer const&); // Don't Implement
void operator=(Randomizer const&); // Don't implement
public:
static Randomizer& get_instance(){
// The only instance of the class is created at the first call get_instance ()
// and will be destroyed only when the program exits
static Randomizer instance;
return instance;
}
bool method() { return true; };
int rand(unsigned int floor, unsigned int ceil){
random::uniform_int_distribution<> rand_ = random::uniform_int_distribution<> (floor,ceil);
return (rand_(rng_));
}
// Is not considering the millisecons
time_duration rand_time_duration(){
boost::posix_time::time_duration floor(0, 0, 0, 0);
boost::posix_time::time_duration ceil(23, 59, 59, 0);
unsigned int rand_seconds = rand(floor.total_seconds(), ceil.total_seconds());
return seconds(rand_seconds);
}
date rand_date_from_epoch_to_now(){
date now = second_clock::local_time().date();
return rand_date_from_epoch_to_ceil(now);
}
date rand_date_from_epoch_to_ceil(date ceil_date){
date epoch = ptime(date(1970,1,1)).date();
return rand_date_in_interval(epoch, ceil_date);
}
date rand_date_in_interval(date floor_date, date ceil_date){
return rand_ptime_in_interval(ptime(floor_date), ptime(ceil_date)).date();
}
ptime rand_ptime_from_epoch_to_now(){
ptime now = second_clock::local_time();
return rand_ptime_from_epoch_to_ceil(now);
}
ptime rand_ptime_from_epoch_to_ceil(ptime ceil_date){
ptime epoch = ptime(date(1970,1,1));
return rand_ptime_in_interval(epoch, ceil_date);
}
ptime rand_ptime_in_interval(ptime floor_date, ptime ceil_date){
time_duration const diff = ceil_date - floor_date;
long long gap_seconds = diff.total_seconds();
long long step_seconds = Randomizer::get_instance().rand(0, gap_seconds);
return floor_date + seconds(step_seconds);
}
};
#include <iostream>
#include <cstdlib>
#include <ctime>
int main() {
srand(time(NULL));
int random_number = std::rand(); // rand() return a number between ​0​ and RAND_MAX
std::cout << random_number;
return 0;
}
http://en.cppreference.com/w/cpp/numeric/random/rand
Can get full Randomer class code for generating random numbers from here!
If you need random numbers in different parts of the project you can create a separate class Randomer to incapsulate all the random stuff inside it.
Something like that:
class Randomer {
// random seed by default
std::mt19937 gen_;
std::uniform_int_distribution<size_t> dist_;
public:
/* ... some convenient ctors ... */
Randomer(size_t min, size_t max, unsigned int seed = std::random_device{}())
: gen_{seed}, dist_{min, max} {
}
// if you want predictable numbers
void SetSeed(unsigned int seed) {
gen_.seed(seed);
}
size_t operator()() {
return dist_(gen_);
}
};
Such a class would be handy later on:
int main() {
Randomer randomer{0, 10};
std::cout << randomer() << "\n";
}
You can check this link as an example how i use such Randomer class to generate random strings. You can also use Randomer if you wish.
Generate a different random number each time, not the same one six times in a row.
Use case scenario
I likened Predictability's problem to a bag of six bits of paper, each with a value from 0 to 5 written on it. A piece of paper is drawn from the bag each time a new value is required. If the bag is empty, then the numbers are put back into the bag.
...from this, I can create an algorithm of sorts.
Algorithm
A bag is usually a Collection. I chose a bool[] (otherwise known as a boolean array, bit plane or bit map) to take the role of the bag.
The reason I chose a bool[] is because the index of each item is already the value of each piece of paper. If the papers required anything else written on them then I would have used a Dictionary<string, bool> in its place. The boolean value is used to keep track of whether the number has been drawn yet or not.
A counter called RemainingNumberCount is initialised to 5 that counts down as a random number is chosen. This saves us from having to count how many pieces of paper are left each time we wish to draw a new number.
To select the next random value I'm using a for..loop to scan through the bag of indexes, and a counter to count off when an index is false called NumberOfMoves.
NumberOfMoves is used to choose the next available number. NumberOfMoves is first set to be a random value between 0 and 5, because there are 0..5 available steps we can make through the bag. On the next iteration NumberOfMoves is set to be a random value between 0 and 4, because there are now 0..4 steps we can make through the bag. As the numbers are used, the available numbers reduce so we instead use rand() % (RemainingNumberCount + 1) to calculate the next value for NumberOfMoves.
When the NumberOfMoves counter reaches zero, the for..loop should as follows:
Set the current Value to be the same as for..loop's index.
Set all the numbers in the bag to false.
Break from the for..loop.
Code
The code for the above solution is as follows:
(put the following three blocks into the main .cpp file one after the other)
#include "stdafx.h"
#include <ctime>
#include <iostream>
#include <string>
class RandomBag {
public:
int Value = -1;
RandomBag() {
ResetBag();
}
void NextValue() {
int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);
int NumberOfMoves = rand() % (RemainingNumberCount + 1);
for (int i = 0; i < BagOfNumbersLength; i++)
if (BagOfNumbers[i] == 0) {
NumberOfMoves--;
if (NumberOfMoves == -1)
{
Value = i;
BagOfNumbers[i] = 1;
break;
}
}
if (RemainingNumberCount == 0) {
RemainingNumberCount = 5;
ResetBag();
}
else
RemainingNumberCount--;
}
std::string ToString() {
return std::to_string(Value);
}
private:
bool BagOfNumbers[6];
int RemainingNumberCount;
int NumberOfMoves;
void ResetBag() {
RemainingNumberCount = 5;
NumberOfMoves = rand() % 6;
int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);
for (int i = 0; i < BagOfNumbersLength; i++)
BagOfNumbers[i] = 0;
}
};
A Console class
I create this Console class because it makes it easy to redirect output.
Below in the code...
Console::WriteLine("The next value is " + randomBag.ToString());
...can be replaced by...
std::cout << "The next value is " + randomBag.ToString() << std::endl;
...and then this Console class can be deleted if desired.
class Console {
public:
static void WriteLine(std::string s) {
std::cout << s << std::endl;
}
};
Main method
Example usage as follows:
int main() {
srand((unsigned)time(0)); // Initialise random seed based on current time
RandomBag randomBag;
Console::WriteLine("First set of six...\n");
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
Console::WriteLine("\nSecond set of six...\n");
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
Console::WriteLine("\nThird set of six...\n");
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
randomBag.NextValue();
Console::WriteLine("The next value is " + randomBag.ToString());
Console::WriteLine("\nProcess complete.\n");
system("pause");
}
Example output
When I ran the program, I got the following output:
First set of six...
The next value is 2
The next value is 3
The next value is 4
The next value is 5
The next value is 0
The next value is 1
Second set of six...
The next value is 3
The next value is 4
The next value is 2
The next value is 0
The next value is 1
The next value is 5
Third set of six...
The next value is 4
The next value is 5
The next value is 2
The next value is 0
The next value is 3
The next value is 1
Process complete.
Press any key to continue . . .
Closing statement
This program was written using Visual Studio 2017, and I chose to make it a Visual C++ Windows Console Application project using .Net 4.6.1.
I'm not doing anything particularly special here, so the code should work on earlier versions of Visual Studio too.
A very opinionated answer
The c++ <random> library violates one of the best principles of software engineering: "Simple things done simple, complex, uncommon things can be a bit more complex."
Instead, they make even the simple and common use cases overly complex, just because they suffer from a cultural disease, fearing comments like "This is not general enough."
As a result, now whenever you want a simple random number, you have to look into the documentation, read stack overflow with walls of text, glorifying this terrible design, instead of it just being an easy-to-remember one or 2 liner. (Common Lisp is more pragmatic: (random 5) yields uniformly distributed integers from 0..4 and (random 1.0) yields real numbers between 0.0..1.0. That is the most common use case and it is at your finger tips. If you need more sophisticated stuff, you have to find packages and libraries or do it yourself.)
Just calculate the across the globe accrued man hours of everyone wasting time on understanding that header and its contents to see how bad it is.
Even I am wasting my time now, writing this answer and you waste your time, reading it, just because they created a piece of complex puzzle, which is in kindred spirit with other modern abominations, such as the Vulkan API.
So, how to cope with it? Waste your time once, write yourself a header file for your most common use cases and then just re-use it whenever you need it.
Here is a solution. Create a function that returns the random number and place it
outside the main function to make it global. Hope this helps
#include <iostream>
#include <cstdlib>
#include <ctime>
int rollDie();
using std::cout;
int main (){
srand((unsigned)time(0));
int die1;
int die2;
for (int n=10; n>0; n--){
die1 = rollDie();
die2 = rollDie();
cout << die1 << " + " << die2 << " = " << die1 + die2 << "\n";
}
system("pause");
return 0;
}
int rollDie(){
return (rand()%6)+1;
}
This code produces random numbers from n to m.
int random(int from, int to){
return rand() % (to - from + 1) + from;
}
example:
int main(){
srand(time(0));
cout << random(0, 99) << "\n";
}
for random every RUN file
size_t randomGenerator(size_t min, size_t max) {
std::mt19937 rng;
rng.seed(std::random_device()());
//rng.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
std::uniform_int_distribution<std::mt19937::result_type> dist(min, max);
return dist(rng);
}
I know how to generate random number in C++ without using any headers, compiler intrinsics or whatever.
#include <cstdio> // Just for printf
int main() {
auto val = new char[0x10000];
auto num = reinterpret_cast<unsigned long long>(val);
delete[] val;
num = num / 0x1000 % 10;
printf("%llu\n", num);
}
I got the following stats after run for some period of time:
0: 5268
1: 5284
2: 5279
3: 5242
4: 5191
5: 5135
6: 5183
7: 5236
8: 5372
9: 5343
Looks random.
How it works:
Modern compilers protect you from buffer overflow using ASLR (address space layout randomization).
So you can generate some random numbers without using any libraries, but it is just for fun. Do not use ASLR like that.
Here my 5 cents:
// System includes
#include <iostream>
#include <algorithm>
#include <chrono>
#include <random>
// Application includes
// Namespace
using namespace std;
// Constants
#define A_UNUSED(inVariable) (void)inVariable;
int main(int inCounter, char* inArguments[]) {
A_UNUSED(inCounter);
A_UNUSED(inArguments);
std::random_device oRandomDevice;
mt19937_64 oNumber;
std::mt19937_64::result_type oSeed;
std::mt19937_64::result_type oValue1;
std::mt19937_64::result_type oValue2;
for (int i = 0; i < 20; i++) {
oValue1 = (std::mt19937_64::result_type) std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
oValue2 = (std::mt19937_64::result_type) std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
oSeed = oRandomDevice() ^ (oValue1 + oValue2);
oNumber.seed(oSeed);
cout << "oNumber: " << oNumber << "\n";
cout << "oNumber.default_seed: " << oNumber.default_seed << "\n";
cout << "oNumber.initialization_multiplier: " << oNumber.initialization_multiplier << "\n";
cout << "oNumber.mask_bits: " << oNumber.mask_bits << "\n";
cout << "oNumber.max(): " << oNumber.max() << "\n";
cout << "oNumber.min(): " << oNumber.min() << "\n";
cout << "oNumber.shift_size: " << oNumber.shift_size << "\n";
cout << "oNumber.state_size: " << oNumber.state_size << "\n";
cout << "oNumber.tempering_b: " << oNumber.tempering_b << "\n";
cout << "oNumber.tempering_c: " << oNumber.tempering_c << "\n";
cout << "oNumber.tempering_d: " << oNumber.tempering_d << "\n";
cout << "oNumber.tempering_l: " << oNumber.tempering_l << "\n";
cout << "oNumber.tempering_s: " << oNumber.tempering_s << "\n";
cout << "oNumber.tempering_t: " << oNumber.tempering_t << "\n";
cout << "oNumber.tempering_u: " << oNumber.tempering_u << "\n";
cout << "oNumber.word_size: " << oNumber.word_size << "\n";
cout << "oNumber.xor_mask: " << oNumber.xor_mask << "\n";
cout << "oNumber._Max: " << oNumber._Max << "\n";
cout << "oNumber._Min: " << oNumber._Min << "\n";
}
cout << "Random v2" << endl;
return 0;
}
Here is a simple random generator with approx. equal probability of generating positive and negative values around 0:
int getNextRandom(const size_t lim)
{
int nextRand = rand() % lim;
int nextSign = rand() % lim;
if (nextSign < lim / 2)
return -nextRand;
return nextRand;
}
int main()
{
srand(time(NULL));
int r = getNextRandom(100);
cout << r << endl;
return 0;
}