Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Same random numbers generated every time in C++ [duplicate]

Tags:

c++

random

Here is the code I have:

int main(int argc, char** argv) {

    int sleeptime = atoi(argv[1]);    
    int sleepCount = atoi(argv[2]);

    int sleepTimeRandom = 1 + (rand() % (int)(sleeptime));
    int sleepCountRandom = 1 + (rand() % (int)(sleepCount));

    sleepTimeRandom = sleepTimeRandom * 1000;

    DWORD id = GetCurrentProcessId();

    cout << "\n\nProcess with id " << id << " will sleep for " << sleepTimeRandom << " milliseconds\n";
    cout << "\n\nProcess with id " << id << " will sleep " << sleepCountRandom << " times \n";

When I call the exe like

sleeper 4 4 

I always get 2000 milliseconds, 4 times.. Why?

like image 810
Koray Tugay Avatar asked Nov 25 '13 19:11

Koray Tugay


2 Answers

You must seed the random number generator. see here for an example.

not-seeded.c

#include <stdio.h>
#include <stdlib.h>

int main ()
{
  printf ("Random not seeded: %d\n", rand()%10);
  return 0;
}

not-seeded output

Random not seeded: 3
Random not seeded: 3
Random not seeded: 3
Random not seeded: 3
Random not seeded: 3

seeded.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main ()
{
  srand(time(NULL));
  printf ("Random seeded: %d\n", rand()%10);
  return 0;
}

seeded output

Random fast seeded: 7
Random fast seeded: 7
Random fast seeded: 7
Random fast seeded: 1
Random fast seeded: 1
Random fast seeded: 1
Random fast seeded: 5
Random fast seeded: 5
Random fast seeded: 5
Random fast seeded: 5

fast-seeded.c

If you want to be able to call your utility more than once a second, you will have to use a different source for you seed, otherwise you will still end up with some repeated random numbers.

Here is an example that uses nanoseconds instead of time() which only returns seconds.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main ()
{
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);

    /* using nano-seconds instead of seconds */
    srand((time_t)ts.tv_nsec);

    printf ("Random fast seeded: %d\n", rand()%10);
    return 0;
}

fast-seeded output

You can see here that the numbers aren't grouped as much as the previous example.

Random fast seeded: 9
Random fast seeded: 6
Random fast seeded: 5
Random fast seeded: 6
Random fast seeded: 1
Random fast seeded: 1
Random fast seeded: 9
Random fast seeded: 4
Random fast seeded: 3
Random fast seeded: 2

uniformly distributed random numbers

If you are interested in uniformly distributed random numbers, you should see user3003631's answer below. If you are in fact using C++, that's how I would recommend doing random numbers. More information here too on this.

like image 144
rkyser Avatar answered Oct 11 '22 07:10

rkyser


There is also the random utility here in C++
in case you want a different approach ... potentially higher quality
Please excuse the minimum of explanation

#include <iostream>
#include <algorithm>
#include <random>

int random_test_200()
{
    std::random_device rd;
    uniform_int_distribution<int> ud(1,9);
    mt19937 mt(rd());
    std::vector<int> v1;
    for (int i = 0; i < 40; ++i)
    {
        auto x = ud(mt);
        v1.push_back(x);
    }
}
like image 45
VIRTUAL-VOID Avatar answered Oct 11 '22 06:10

VIRTUAL-VOID