Random number generator

hello everybody.

I encountered that I do have a Problem with programming in c++, when I try to define classes and work with them. I have a Java background, and its sometimes hard for me to step away from this encapsulation scheme. Basically I want to use Random numbers, generated with the mersenne twister RNG, in a class A and perhaps later on in a class B. At the moment Iam familiar with the use of the MT RNG, but only if I have one file without additional classes. I will just post somehow the structure of the problem, since all my attempts to solve the problem were rubbish.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

class A{
public:
    A();
    ~A();
    int showRandomNumber();


};
int A::showRandomNumber(){
    return generateRandomNumber();
}

int main(void){
    A a;
    std::cout << a.showRandomNumber() << std::endl;
}


Is it necessary to implement somehow a RNG class, with a function seed() and generateRandomNumber() and then at the beginning of main I will first seed it, and then I can safely use it through my entire program?

I really hope someone is willing to help me out, I would appreciate it so much!

Thank you, omikron.
So, how would you solve this in Java? You should be able to do this in C++ in very similar way.

In Java you have import which is similar to #include
In c++ you have usually two files for a class. The header file (e.g. a.h) is the interface of the class which needs to be #include d where it's use. In the implementation file (e.g. a.cpp) you provide the body for the interface:

a.h:
1
2
3
4
5
6
7
8
class A{
public:
    A();
    ~A();
    int showRandomNumber();


};


a.cpp
1
2
3
4
5
6
7
8
9
10
11
A::A()
{
}

A::~A()
{
}

int A::showRandomNumber(){
    return generateRandomNumber();
}


main.cpp:
1
2
3
4
5
6
7
#include <iostream>
#include <a.h>

int main(void){
    A a;
    std::cout << a.showRandomNumber() << std::endl;
}


You need to add all of this file to your project
Also you do not need to implemnt RNG yourself. Standard library alrady has it:
http://en.cppreference.com/w/cpp/numeric/random

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

int roll_dice()
{
    //random_device should be used sparingly
    //as some implementations does not implement it properly
    ////std::random_device rd;
    static std::mt19937 gen(std::time(nullptr)); //Better to find another proper source of entropy
    static std::uniform_int_distribution<> dis(1, 6);
    return dis(gen);
}

int main()
{
    for (int n = 0; n < 10; ++n)
        std::cout << roll_dice() << ' ';
    std::cout << '\n';
}

May i ask you a question @ MiiNiPaa

as cpu run very fast, is there a risk that time(nullptr) return the same value from adjacent iterations.
gen is static. That means it initialised once on a first use.

However, you should really use proper (usually platform dependend) methods to generate seed if you really need proper randomness.
Thank you both for your answer.

I am aware about the fact that a class has two files, but i thought for the sake of readability it is better to just post one code snippet. And I never used anything else in Java than the biased rand() method and I never had a look at RNGs and stuff in Java, therefore I dont really know if I could implement it in Java.

Test.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma once
#include<random>
#include<ctime>

static int randomNumber(int min, int max){
	static std::mt19937 gen(std::time(nullptr)); //Better to find another proper source of entropy
	static std::uniform_int_distribution<> dis(min, max);
	return dis(gen);
}

class Test{
public:
	Test();
	~Test();
	int showRandomNumber(int,int);
};


Test.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
#include "Test.h"

Test::Test(){
}


Test::~Test(){
}

int Test::showRandomNumber(int min, int max){
	return randomNumber(min,max);
}


main.cpp
1
2
3
4
5
6
7
8
9
10
#include "Test.h"
#include <iostream>

int main(){
	Test a,b;

	for (int i = 0; i < 10; i++){
		std::cout << "a: " << a.showRandomNumber(1,6) << "\tb: " << b.showRandomNumber(1,6) << std::endl;
	}
}


This approach seems to work. But is this in the spirit of c++ programming? And now I seed everytime I call randomNumber(int min, int max), which is against the only seed once paradigm. The thing I want to achieve is to have a function like rand(), which I can use in class, like my class Test.
And now I seed everytime I call randomNumber(int min, int max),
No, you seed it once, as gen is declared static.
In fact you are creating distribution once too, so if you call it as randomNumber(-1, 1); and then as randomNumber(5, 10);, it will still return value in range [-1,1]
Declaring function several times with internal linkage is not good too.

You should move it to the cpp file and slightly change it:
1
2
3
4
5
6
//Test.cpp
int randomNumber(int min, int max){
	static std::mt19937 gen(std::time(nullptr));
	std::uniform_int_distribution<> dis(min, max); //Not static
	return dis(gen);
}
Last edited on
Thank you. I know what confused me. So if I do have like a Test.cpp file, there the Global Scope space is not connected with the Global Scope space from e.g. the main.cpp file. Therefore I can define in Test.cpp like a "freely floating" randomNumber() function, which can be used in the whole file, but not outside of it, is that correct? And if one then has like alot of these "freely floating" functions, it is advised to declare namespaces, roughly speaking? sorry for the newby questions, but its really hard to figure it out autodidactically

In a comment of your code snippet you mentioned
//Better to find another proper source of entropy

Would this be better:
1
2
3
4
5
6
7

int randomNumber(int min, int max){
        std::random_device rd;
	static std::mt19937 gen(rd());
	std::uniform_int_distribution<> dis(min, max); //Not static
	return dis(gen);
}



"freely floating" randomNumber() function, which can be used in the whole file, but not outside of it, is that correct?
No, it is externally visible. Compiler would complain if you will try to use function you not declared, will allows you to define function with the same name in another file; but if linker will see functions violating One Definition Rule, it will generate an error.

So you should have implementation file, where function definitions are stored, and header file where their declarations are stored (if needed) which will be included in another files which want to use that function.

Would this be better:
Avoid unnesesary creation of objects. You need random_device only once, so you better to do this:
static std::mt19937 gen(std::random_device());

Also as I said you should check if random_device is implemented properly. On MinGW TDM GCC 4.9.1 random_device always returns same number, making it useless.
I see the point with the unnecessary creation of objects, but
static std::mt19937 gen(std::random_device());
this gives an Error: block-scope function may only have extern storage class
Ah, my bad. use this: static std::mt19937 gen(std::random_device{}());
Topic archived. No new replies allowed.