<random> and <chrono>

closed account (N8MNAqkS)
alright correct me if I am wrong in my evaluation of this code, im trying to understand how this works and I think I have figured it out.

(BTW this is code I was given on the forums that I modified into a little guessing game credit go's to Ganado for showing me <random> and <chrono>)

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
28
29
30
31
32
33
34
35
36
37
38
39
#include "pch.h"
#include<iostream>
#include <Windows.h>
#include <random>
#include <chrono>
using namespace std;




int main()
{
	
	unsigned seed1 = chrono::system_clock::now().time_since_epoch().count();
	
	std::mt19937 generator(seed1);

	std::uniform_int_distribution<int> distribution(1, 10);

	int PRN;
	int i = 0;
	cout << "Guess a number between 1 and 10 and press enter" << endl;
	cin >> i;

	PRN = distribution(generator);
	cout << "winning number "<< PRN << "\n";

	if (i == distribution(generator))
	{
		cout << "you win" << endl << endl << endl << endl << endl;
	}
	else
	{
		cout << "you lose" <<endl <<endl << endl << endl << endl;
	}


	return 0;
}


so
unsigned seed1 = chrono::system_clock::now().time_since_epoch().count();

gets numbers from the real time system clock and slaps those into seed1 which is then slaped into the equation that

std::mt19937 generator(seed1);

uses to generate a number. this number stays between whatever parameters I set in


std::uniform_int_distribution<int> distribution(1, 10);

and then stores that generated number in

distribution(generator)

which I then output to the screen via cout.

anything I miss or get wrong?


Last edited on
1. unsigned seed = std::chrono::system_clock::now().time_since_epoch().count()); gets the current system time, similar to std::time(nullptr).

2. The C library has only one available pseudo-random number generator (rand()), C++ has several. std::mt19937 is one of them, std::default_random_engine is another.

I personally prefer std::default_random_engine.

3. std::mt19937 generator(seed); is used to seed your random engine when you create it. Similar to srand(). No random numbers are generated on creation of the engine.

4. std::uniform_int_distribution<int> distribution(1, 10); creates a distribution object, setting the range of random numbers that can be generated. CRUDELY similar to rand() % 10 + 1;.

5. The distribution does NOT create any random number, that is done with distribution(generator).

Your if statement at line 28 will generate a different random number than the one you created at line 25 and stored in PRN.

You should change line 28 to if (i == PRN) if you want to compare the stored random number.

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
28
29
#include<iostream>
#include <random>
#include <chrono>

int main()
{

   unsigned seed = static_cast<unsigned> (std::chrono::system_clock::now().time_since_epoch().count());

   std::mt19937 generator(seed);

   std::uniform_int_distribution<int> distribution(1, 10);

   std::cout << "Guess a number between 1 and 10 and press enter: ";
   int i = 0;
   std::cin >> i;

   int PRN = distribution(generator);
   std::cout << "(winning number: " << PRN << ")\n\n";

   if (i == PRN)
   {
      std::cout << "You win!\n\n\n\n";
   }
   else
   {
      std::cout << "You lose.\n\n\n\n\n";
   }
}
Last edited on
closed account (N8MNAqkS)
So ur saying that everytime i call distribution (generator) it makes a new random number and that to check if i is equivalent to the first distribution (generator) that I have to check if I is equivalent to PRN.
So ur saying that everytime i call distribution (generator) it makes a new random number

Yes. In the range you chose when creating the distribution. 1 to 10, inclusive, line 12.

You want someone to guess a SINGLE random number, you generate one. Line 19.

You get the guess from the user, line 16, and compare the stored random number with the user input.

A game of Heads/Tails, each guess you flip the coin ONCE. Possible distribution of (0, 1).

distribution(generator) as you set up in your program is CRUDELY similar to rand() % 10 + 1.

generator() gets a new random number, distribution() modifies the random number to conform to the specified distribution range. With a uniform distribution any number in the range has the same chance of being generated as every other number.

rand() has bias issues, as explained here: http://www.cplusplus.com/forum/beginner/251741/#msg1108315

There are other distributions available in the <random> header, that generates numbers by other means. One, std::normal_distribution can generate random numbers on a bell curve.

Generating random numbers with C++ can be intimidating at first because there are so many options. And is done differently than how random numbers are generated in C.
Last edited on
closed account (N8MNAqkS)
ok thank you for your help.

im gonna run down this one more time to see if I understand

unsigned seed = static_cast<unsigned> (std::chrono::system_clock::now().time_since_epoch().count());

gets a number from the system clock and stores it in seed.



std::mt19937 generator(seed);

puts that number into distribution(generator) or "seeds" it whenever distribution(generator) is called.










std::mt19937 generator(seed);

puts that number into distribution(generator) or "seeds" it whenever distribution(generator) is called.

The seed is a value that is used to initialize the generator. If you use the same seed each time the generator's internal state would always start out the same which means you would always generate the same sequence of numbers.

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

int main()
{
	const int seed = 123;
	
	std::mt19937 generator1(seed);
	std::mt19937 generator2(seed);
	
	const int column_width = 12;
	
	std::cout << std::setw(column_width) << "generator1";
	std::cout << std::setw(column_width) << "generator2";
	std::cout << '\n';
	
	for (int i = 0; i < 10; ++i)
	{
		std::cout << std::setw(column_width) << generator1();
		std::cout << std::setw(column_width) << generator2();
		std::cout << '\n';
	}
}
  generator1  generator2
  2991312382  2991312382
  3062119789  3062119789
  1228959102  1228959102
  1840268610  1840268610
   974319580   974319580
  2967327842  2967327842
  2367878886  2367878886
  3088727057  3088727057
  3090095699  3090095699
  2109339754  2109339754

If you use different seeds you will (most likely) get a different sequence of numbers.

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
#include <iostream>
#include <iomanip>
#include <random>

int main()
{
	const int seed1 = 123;
	const int seed2 = 456;
	
	std::mt19937 generator1(seed1);
	std::mt19937 generator2(seed2);
	
	const int column_width = 12;
	
	std::cout << std::setw(column_width) << "generator1";
	std::cout << std::setw(column_width) << "generator2";
	std::cout << '\n';
	
	for (int i = 0; i < 10; ++i)
	{
		std::cout << std::setw(column_width) << generator1();
		std::cout << std::setw(column_width) << generator2();
		std::cout << '\n';
	}
}
  generator1  generator2
  2991312382  1068398491
  3062119789  4211147365
  1228959102   700366507
  1840268610   650865241
   974319580  3365722154
  2967327842  1437477359
  2367878886  3472581532
  3088727057  1224769390
  3090095699  2687053647
  2109339754   664237178


When you write distribution(generator) the distribution will use the generator as its source of randomness in order to generate a random number according to the distribution. No "seeding" is happening here. std::uniform_int_distribution tries to make all numbers within the specified range equally likely but there are also more advanced distributions where some numbers are more likely than others.
Last edited on
Topic archived. No new replies allowed.