Realistic random numbers

closed account (SECMoG1T)
I hate the fact that every time i need to get some random numbers in a program i'll have to use the 'C' library srand and rand functions because the so called library random number generators always got me disappointed and so i had to give up on them "they always gave me predictable sequences" something i could do without them but now i want to take the challenge and know why they misbehaved when i needed them , for example the following function always returns the same random sequence on each program execution..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  #include <random>
  #include <vector>
  #include <iostream>

  void print(const std::vector<unsigned int> &vec)
   {
     for(const auto& rand_no : vec)
       std::cout<<rand_no<<" ";
   }
  
  std::vector<unsigned int> get_random_seq()
   {
     static std::default_random_engine u_engine(43323);
     static std::uniform_int_distribution<unsigned int> u_distrib(1,30);
     std::vector<unsigned int> u_vec;

     for(std::size_t i=0;i<30;i++)
        u_vec.push_back(u_distrib(u_engine));

     return u_vec;
   }

   int main(int argc, char* argv[])
   {
      auto my_vec=get_random_seq();
      print(my_vec);
   }


Actually i read from an article that the consistency in the produced sequence during different program execution was meant to be handy during testing and debugging but that make no sense to me if the glorified testing functionality continues to impose limitations in my program's performance

What do i need to do to get real random numbers (i mean unpredictable sequences) similar to those i get with srand?
Last edited on
To get a different sequence of numbers you need to use a different seed. In the program above you use 43323 as the seed. Often the current time (e.g. std::time(0) or std::chrono::high_resolution_clock::now().time_since_epoch().count()) is used as the seed.
closed account (SECMoG1T)
Ooh thanks @peter87 does that mean
std::time(0)
returns an unsigned integer , std::chrono::high_resolution_clock::now().time_since_epoch().count()) av not heard of this yet, where do i get it??
<ctime>
?? what does it do?
you can also use std::random_device from <random>. It generates random numbers and you don't have to seed it. It's pretty slow so use it just as a seed.
Peter87 already told about that, but why are you using std::default_random_engine u_engine(43323); in the first place?
And why are you saying that srand will help here? If you do srand(43323), you will get same results on every execution too.
closed account (SECMoG1T)
Ooh i see am getting somewhere now
@Peter - confirmed
static std::default_random_engine u_engine(std::time(nullptr));
worked fine for my example above, thank you very much.

@TheHardew great suggestion there, i would appreciate a simple example too using that random_device, thank you pal.
std::default_random_engine And I would not suggest it either: you do not know what that engine would be. And usually it is LCG, which gives you pretty bad randomness.

I suggest using std::mt19937: a Mersenne Twister algorithm which gives you good tradeoff between randoness and speed.

Before using random_device, insert check if it is really random. On some platform it might give you same sequence each time.
http://stackoverflow.com/a/18880689


http://en.cppreference.com/w/cpp/numeric/random/random_device/entropy
http://en.cppreference.com/w/cpp/numeric/random/random_device
Last edited on
closed account (SECMoG1T)
Thanks @MiiniPaa for that , am testing this nowstd::mt19937, thanks for the links i'll check them after testing.
closed account (SECMoG1T)
Perfect it works great, it also solved a problem i got when using std::time(nullptr) with default_random_engine in the function below

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
unsigned int random_int_d_eng()
{
    static std::default_random_engine u_engine(std::time(nullptr));
    static std::uniform_int_distribution<unsigned int> u_distrib(0,100);
    return u_distrib(u_engine);
}

unsigned int random_int_mt199()
{
    static std::mt19937 u_mt(std::time(nullptr));
    static std::uniform_int_distribution<unsigned int> u_distrib(0,100);
    return u_distrib(u_mt);
}

int main()
{

     std::cout<<random_int_d_eng()<<"    "<<random_int_mt199()<<std::endl;

    return 0;
}


output on 5 different executions, default_random_engine seems to use the same seed all the time.


78    11
78     5
78    96
78    27
78    77


Well i guess i'll now stick to mt19937 , it's pretty cool, thanks for that.
default_random_engine seems to use the same seed all the time.
Ha, it is LCG, I knew it. No, it is just not initialized properly yet. Skip several first iteratons and you will see:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <random>
#include <ctime>
#include <mutex>

std::once_flag flag;

unsigned int random_int_d_eng()
{
    static std::default_random_engine u_engine(std::time(nullptr));
    std::call_once(flag, [](){ u_engine.discard(5); }); //Drop first five results
    static std::uniform_int_distribution<unsigned int> u_distrib(0,100);
    return u_distrib(u_engine);
}

unsigned int random_int_mt199()
{
    static std::mt19937 u_mt(std::time(nullptr));
    static std::uniform_int_distribution<unsigned int> u_distrib(0,100);
    return u_distrib(u_mt);
}

int main()
{
    std::cout<<random_int_d_eng()<<"    "<<random_int_mt199()<<std::endl;
}
50    54
25    92
79    27
closed account (SECMoG1T)
@Miinipaa yeah it works when i use your example, what happened with it? also what does thisit is LCG mean?
Last edited on
I think LCG stands for linear congruential generator. http://en.wikipedia.org/wiki/Linear_congruential_generator
LCG = Linear Congruental Generator, simpliest PRNG possible.

Because of its generation method, small changes in seed (and time() changes slowly: once each second) will result to small changes in resulting bit pattern on first iterations (then differences will accumulate enough to ensure at least some randomness). And distributions not always use all bits from RNG: they usually uses as much as needed to ensure uniform distribution, and they do not take into account that some bits might be not random or that result of calling RNG might strongly correlate with result of previous execution.
closed account (SECMoG1T)
Ooh thanks now i get it now but i might have to check on some more details later, thank you very much
Topic archived. No new replies allowed.