263

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?

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Predictability
  • 2,919
  • 4
  • 16
  • 12
  • 88
    Distribution issues aside, keep in mind that with random numbers comes the possibility of getting the same result several times in a row. If you were guaranteed not to get the same number twice in a row, the results wouldn't really be random, would they? – cdhowie Nov 18 '12 at 23:25
  • 8
    What makes you think those numbers aren't random? Throw a die for real and you very well could get that outcome. If they were guaranteed to be different between each throw then it wouldn't really be random would it. – mattjgalloway Nov 18 '12 at 23:27
  • 3
    Also read http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx why using the modulus operator isn't often a good idea. – Benjamin Bannier Nov 18 '12 at 23:29
  • Another discussion of `rand()` distribution problems and suggested solutions: http://www.azillionmonkeys.com/qed/random.html – ezod Nov 18 '12 at 23:33
  • 5
    You're misunderstanding a lot more than one can fit in a comment or even an answer. You need to learn, independently, about pseudo-random number generators, about seeds, about the importance of picking a truly random seed, and about uniform distributions. – Kerrek SB Nov 18 '12 at 23:33
  • [HERE](http://stackoverflow.com/questions/9471604/what-is-the-best-way-to-generate-random-numbers/9471733#9471733)'s C-style solution that for now always worked perfectly for me ;) – LihO Nov 18 '12 at 23:37
  • 34
    When you seed with time. This also means that if you run your program more than once a second you will get the same number. – Martin York Nov 18 '12 at 23:37
  • 1
    http://stackoverflow.com/questions/322938/recommended-way-to-initialize-srand – Ciro Santilli OurBigBook.com Feb 21 '17 at 08:16
  • Related: [How to succinctly, portably, and thoroughly seed the mt19937 PRNG?](https://stackoverflow.com/questions/45069219/how-to-succinctly-portably-and-thoroughly-seed-the-mt19937-prng) – Peter Cordes Dec 01 '17 at 06:03
  • Here is an interesting video which explains why `std::rand` should generally not be used in C++ code, and why `std::mt19937` and `std::uniform_int_distribution` should be used instead: [rand() considered harmful](https://learn.microsoft.com/en-us/events/goingnative-2013/rand-considered-harmful) – Andreas Wenzel Jul 24 '23 at 11:33

14 Answers14

310

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.

Dan
  • 7,286
  • 6
  • 49
  • 114
Cornstalks
  • 37,137
  • 18
  • 79
  • 144
  • 12
    The amount of bias introduced by using `%6` is vanishingly small. Maybe significant if you're writing a craps game to be used in Las Vegas, but of no consequence in almost any other context. – Hot Licks May 08 '14 at 20:53
  • 15
    HotLicks: agreed, but if you're using a version of C++ that supports `random_device` and `mt19937` already, there is literally no reason *not* to go all out and use the standard `uniform_int_distribution` too. – Quuxplusone Aug 28 '17 at 21:25
  • 1
    Related: [How to succinctly, portably, and thoroughly seed the mt19937 PRNG?](https://stackoverflow.com/questions/45069219/how-to-succinctly-portably-and-thoroughly-seed-the-mt19937-prng). Apparently MinGW (in some versions) has a useless non-random `std::random_device` – Peter Cordes Dec 01 '17 at 06:05
  • 15
    All programmers should advise people to avoid modulo like the plague because it uses division and that costs hundreds of clock cycles and can mess up your application timing and/or burn a lot of battery power. –  Sep 05 '18 at 17:28
  • 9
    Is rng for "range"? – Chris Oct 02 '18 at 17:33
  • 16
    @ChristofferHjärtström: It's for **r**andom **n**umber **g**enerator. – Cornstalks Oct 03 '18 at 05:21
  • second line crashes, no error message, i'm using mingw on windows – Behrooz Karjoo Apr 11 '19 at 17:02
  • So you make single reading of `std::mersenne_twister_engine<>` and exit? Really? Why do you even use `std::mt19937`? You might simply use just `std::random_device` - that would be much more appropriate... – Serge Dundich Jul 15 '20 at 20:47
  • 3
    @user2356685 Disagree. `uniform_int_distribution` uses division under the hood, and it's a lot more complex than a single modulo. Hard and fast rules often fail to consider the alternative. – c z Aug 31 '21 at 09:40
  • 1
    Years come and go, but still, every time I want to generate random numbers in C++, I google this answer. And here I was laughing at [xkcd comics about tar](https://xkcd.com/1168/). – Dmitry Feb 24 '23 at 22:00
150

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;
}
Serge Dundich
  • 4,221
  • 2
  • 21
  • 16
  • I have asked similar question in here [link](https://stackoverflow.com/questions/55379591/rand-function-generates-the-next-number-by-ascending-to-the-previous-number) but still couldnt find any clear answer yet. Can you please demonstrate "Actually you should call srand(seed) one time and then call rand()" with codes because I already did what you say but it is not working properly. – bashburak Mar 28 '19 at 07:41
  • 2
    @bashburak It seems that you totally missed the point of this answer. Why exactly did you cut my quote? I said in my answer literally "Actually you should call srand(seed) one time and then call rand() *many times* and analyze that sequence - it should look random." Did you notice that you should call rand() MANY TIMES after single srand(...) call? Your question in your link is exact duplicate of this question with exact same misunderstanding. – Serge Dundich May 04 '19 at 16:36
  • This is an old answer, but it shows up when you google "C++ random number generation". It is poor advice for C++ programmers, because it advises you use `rand()` and `srand()`. Can you update it? – Yakk - Adam Nevraumont Jun 03 '20 at 14:37
  • 2
    @Yakk-AdamNevraumont It does not actually advise to use `rand()` and `srand()`. In fact it just answers the question with provided description. It is evident from the description (that uses `rand`/`srand`) that the basic concepts of pseudo-random numbers generation should be explained - like the very meaning of pseudo-random sequence and its seed. I'm trying to do exactly that and use the most simple and familiar `rand`/`srand` combination. Funny thing is that some other answers - even with very big rating - suffer from the same misunderstandings as the author of the question. – Serge Dundich Jun 08 '20 at 06:19
  • 2
    @Yakk-AdamNevraumont I took your advise and amended my answer with some info about newest C++ additions. Though I consider this a bit off topic - but your suggestion as well as some other answers indicates that both good old `std::rand/std::srand` AND new C++ library features like `std::random_device<>`, [std::mersenne_twister_engine<>](https://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/mersenne_twister_engine) and multitude of [random distributions](https://en.cppreference.com/w/cpp/named_req/RandomNumberDistribution) require some explanation. – Serge Dundich Jun 21 '20 at 19:07
  • In that seed, you aren't guaranteed that the two time_since_epoch operations will happen at the same instant, atomically. So the current times could be different between the two. Also, why add the current time in seconds plus the current time in microseconds? That seems wrong. I think current time in seconds would be more than sufficient. – Tyler Shellberg Apr 13 '23 at 16:05
  • @TylerShellberg You said: "In that seed, you aren't guaranteed that the two `time_since_epoch` operations will happen at the same instant, atomically." Could you please clarify what are you trying to say? The point of calling timer operations to initialize the seed is exactly opposite to call them at the same instant. Current time is used as simply some random info - we prefer it to be different each time. – Serge Dundich Apr 17 '23 at 09:13
  • @TylerShellberg You said: "Also, why add the current time in seconds plus the current time in microseconds? That seems wrong." - Could you please specify - what exactly is wrong with this in your opinion? You said: "I think current time in seconds would be more than sufficient." - Really? So you obviously totally missed the very problem OP encountered, right? The OP's original problem is that they seed with time since UNIX epoch in seconds and that leads to the same seed value if you happen to run the program in quick succession - more that once on the same second. – Serge Dundich Apr 17 '23 at 09:26
28

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:

  1. 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.
  2. The common usage of std::rand() eliminates the possibility of a uniform distribution of pseudo-random numbers, because of the Pigeonhole Principle.
  3. 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 a part 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++!

Tarick Welling
  • 3,119
  • 3
  • 19
  • 44
  • I noticed this [link](https://stackoverflow.com/questions/39288595/why-not-just-use-random-device) and now your post. I assume, at least some of the points presented there are no more valid? could you also have a look there and see if thats the case ? – Hossein Feb 16 '21 at 07:37
  • 1
    Howdy @Rika, I looked through the question and I do see that the points made there are valid. Although more elaboration is needed. It may take a while for me to provide a proper answer, because RNG seeding is complicated in C++. Maybe it would be beneficial to add a new section to this answer describing C++ PRNG seeding gotchas. –  Feb 17 '21 at 18:44
12

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);
    }
};
madx
  • 6,723
  • 4
  • 55
  • 59
  • 4
    Now that we have random as part of the standard I would discourage the use of the boost version unless you are using a truly old compiler. – Martin York Feb 26 '20 at 19:41
10
#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

Arley
  • 947
  • 1
  • 13
  • 19
  • 2
    What is the difference with question author's code? (Except that you don't use `%6`.) And if you decided to use `std::rand` C++ API of `rand` C library function then why not use `std::time` and `std::srand` for the sake of C++ style consistency? – Serge Dundich Jun 08 '20 at 16:44
5

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.

Gusev Slava
  • 2,136
  • 3
  • 21
  • 26
  • 1
    Would you not want to re-use the generator for all your Randomer objects? Especially since it is relatively expensive to create initialize and maintain its state. – Martin York Feb 26 '20 at 19:44
4

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:

  1. Set the current Value to be the same as for..loop's index.
  2. Set all the numbers in the bag to false.
  3. 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.

WonderWorker
  • 8,539
  • 4
  • 63
  • 74
  • If this is VS 2017, you should be using the most recent version of the standard library: https://en.cppreference.com/w/cpp/numeric/random . Currently this example uses the C random library functions and "There are no guarantees as to the quality of the random sequence produced". – Robert Andrzejuk Jan 13 '19 at 19:22
3

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.

BitTickler
  • 10,905
  • 5
  • 32
  • 53
2

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;
}
HDSSNET
  • 131
  • 3
2

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";
}
Amir Fo
  • 5,163
  • 1
  • 43
  • 51
  • 3
    This doesn't really answer the question. – HolyBlackCat Jul 07 '18 at 10:28
  • @HolyBlackCat First I read the title only, after your attention I fixed it. thanks. – Amir Fo Jul 07 '18 at 11:47
  • 1
    You didn't fix it. The point of the question is that if you run the program multiple times per second, then it generates the same random values. Your code does that too. – HolyBlackCat Jul 07 '18 at 11:48
  • 1
    @HolyBlackCat I've checked it for multiple runs, it's working. Have you added `srand(time(0))` to the main function before `random(n, m)`? – Amir Fo Jul 07 '18 at 11:54
  • 1
    You should add `srand(time(0))` to main function not to for loop or inside the function implementation. – Amir Fo Jul 07 '18 at 11:56
  • 1
    I've copied your code verbatim. Did you run it *multiple times per second*? – HolyBlackCat Jul 07 '18 at 12:04
  • @HolyBlackCat I tried it by command line shell to execute multiple times in a second. I'm testing it with Linux GCC c++11 and it's working. – Amir Fo Jul 07 '18 at 12:39
1

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);
}
Coloured Panda
  • 3,293
  • 3
  • 20
  • 30
Nehigienix
  • 53
  • 4
  • 3
    You are not supposed to create the generator multiple times. It maintains a bunch of state so that it generates a sequence of random numbers that has the appropriate distribution (to make it look random). – Martin York Feb 26 '20 at 19:46
1

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

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;
}
-2

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;
   }
Andrushenko Alexander
  • 1,839
  • 19
  • 14