random generator in the constructor

Hello,
I want to use the random generator which initializes every time when constructor is called:

1
2
3
4
5
6
7
8
9
10
11
12
13
StructureGenerator::StructureGenerator(const float& monomer_mass, const float& monomer_concentration)

        : _monomer_mass(monomer_mass)

        , _monomer_concentration(monomer_concentration)

{
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();

    std::default_random_engine generator(seed);

    _mt = std::mt19937_64 (generator);
}


getting the error : error: no match for call to '(const std::mersenne_twister_engine<long long unsigned int, 64, 312, 156, 31, 13043109905998158313, 29, 6148914691236517205, 17, 8202884508482404352, 37, 18444473444759240704, 43, 6364136223846793005>) ()'
__sum += _RealType(__urng() - __urng.min()) * __tmp;

I understand that problem is with incorrect types?
the example I see online is like this:

std::random_device rd; //I don't know if this is a generator or not, I have not dug into how all the parts interact under the hood, I just use the <random> thing in very basic ways.
std::mt19937_64 gen(rd());

i also see re-seed examples that would be
_mt.seed(value); //just put the chrono equation in here?
Last edited on
Usually in Computer Science adding another level of indirection solves the problem. However in this case you have too many indirections. It's simply:

1
2
3
4
5
6
7
8
9
StructureGenerator::StructureGenerator(const float& monomer_mass, const float& monomer_concentration)

        : _monomer_mass(monomer_mass)

        , _monomer_concentration(monomer_concentration)

       , _mt(std::mt19937_64(std::chrono::system_clock::now().time_since_epoch().count()))

{}

Last edited on
Thanks for the help and attention,

no, it does not work either, I am getting the same error,


Maybe I needed to post the function in which it is used further:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::vector<float>
StructureGenerator::_random_number(float a, float b) const {

    std::uniform_real_distribution<float> dist(a, b);

    std::vector<float> rand {};

    for (int32_t i = 0; i < 6; i++)
    {
        float randomX = dist(_mt);

        rand.push_back(randomX);
    }

    return rand;
}
Last edited on
Don't overdo the "const".

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

class StructureGenerator
{
   float _monomer_mass;
   float _monomer_concentration;
   std::mt19937_64 _mt;
public:
   StructureGenerator( float monomer_mass, float monomer_concentration )
      : _monomer_mass( monomer_mass ),
        _monomer_concentration( monomer_concentration ),
        _mt( std::chrono::system_clock::now().time_since_epoch().count() )
      {}
   std::vector<float> _random_number( float a, float b )  // <===== No const qualifier
   {
      std::uniform_real_distribution<float> dist(a, b);
      std::vector<float> rand{};
      for ( int i = 0; i < 6; i++) rand.push_back( dist( _mt ) );
      return rand;
   }
};


int main()
{
   StructureGenerator SG( 180.0f, 0.5f );
   std::vector<float> r = SG._random_number( 1.0f, 9.0f );
   for ( float e : r ) std::cout << e << ' ';
}
Last edited on
each number in the sequence is generated like this x_0 = seed
x_n = f(x_{n-1})
y_n = g(x_n)
y_n is the number that your obtain, x_n is an internal register used in the generation
so each time you ask for another number, the generator changes its state, for that reason `_mt' may not be constant.


> Maybe I needed to post the function in which it is used further:
in general, the error message will point to the line number on your code that causes the error
so that's kind of relevant
also, you need to show the definition of the variables used
Last edited on
If _random_number() needs to be const (eg because the calling object is const), then _mt can be mutable.

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

class StructureGenerator
{
	float _monomer_mass;
	float _monomer_concentration;
	mutable std::mt19937_64 _mt;

public:
	StructureGenerator(float monomer_mass, float monomer_concentration)
		: _monomer_mass(monomer_mass),
		_monomer_concentration(monomer_concentration),
		_mt(std::chrono::system_clock::now().time_since_epoch().count())
	{}

	std::vector<float> _random_number(float a, float b) const
	{
		std::uniform_real_distribution<float> dist(a, b);
		std::vector<float> rand {};

		for (int i = 0; i < 6; i++) rand.push_back(dist(_mt));

		return rand;
	}
};


int main()
{
	const StructureGenerator SG(180.0f, 0.5f);
	const auto r = SG._random_number(1.0f, 9.0f);

	for (auto e : r)
		std::cout << e << ' ';
}

Last edited on
Except for @jonnin it is evident that nowhere else in the whole history of human civilization and endeavour has such a meal been made out of generating 6 random numbers.

Why is there a class - why have member _mt? Why floats?

And now, FFS, we're into 'mutable' as this silliness continues.

I wonder, does @OP work at CERN by any chance?
@againtry pls try hold yourself out from unproductive comments, which brings only negative value - nothing more, as you have no idea about the whole code and how these inputs go to the certain sections and why it must be as they are.

The rest, thank you very much for your insights. It must be with const, so @seeplus thank you very much for your information how to do this with mutable. Thanks again,

A.
A CERN-inspired camel, now with 3 humps (1 mutable of course for a vitally important mersenne twister generator, go figure) complete with a pile of spag-code and all it is there for is to generate 6 random numbers. ROFL
@again, one more time - please keep the no-use comments to yourself. Like I said, you have no idea why is done as it is done, and you are naive enough to think only about 6 random numers. Good luck to you and please don't comment under my posts - I come here to learn, not to discuss some trivial things with toxic, obnoxious people. If it calms you down, believe me, I know how to generate random numbers with three code rows as well.
@TheTriHumpCamelAlex,

I'll comment where I like especially when I see through your no-use bad recipes posing as any sort of programming.

You're the one with 6 random numbers and your camel solution, not me.

if you had any ability and came here to learn you would have cottoned on to what @jonnin commented and left it at that instead of going down a rabbit hole with the others.

Toxic and obnoxious? is that your best shot to cover up when you can't program, don't understand classes, use floats, make a const member _mt. All you're doing is adding to your self-made joke of yourself as a totally immutable dope.

And you think you know what you are doing?
And how it goes further? You insult me, I will insult you, and so on, will you get a pleasure from this or what? Ok, let's try another way.

Dear Mr, yes, you are right, as you kindly noticed, I am a beginner in C++. Kindly please share your experience how would you rewrite this piece of code that it would serve the purpose in more efficient way? Note that this class is intended to generate the special geometrical structure using the random numbers. The _mt should be within the constructor, and it goes to the function of random_number, then output goes to the function of random_rotation, and this output goes to the actual construction of the specially rotated chain. The constructor has more functions as well, but these are not related to the random numbers.

Most of variables should be const as it speeds up the computing in the supercluster. I am not sure yet which way is better - remove const or use mutable. I need to check with my supervisor if I can remove const, for now I used mutable and it works - works well as intended.

With all above stated, and in the best spirit of learning instead of insulting and flaming, kindly please enlighten me, as I am using this first time ever and don't have a deep understanding: 1) why is bad to use mutable ? 2) what would be more preferable way? Also please note that I am not familiar with expert terminology ( I sincerely have no Idea what is camel in this context, humps, or why we are talking about CERN), so it would nice that you could just illustrate this in the example. Thank you very much, and sorry if I insulted you as your way of expressing your expert opinion in your posts above was not understandable for me(probably due my lack of experience).
Last edited on
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <vector>
#include <random>
#include <chrono>

class SomeUnknownToMe;

class SpecialGeometricStructure
{
private:
    std::vector<double> _m_vec;
    
public:
    SpecialGeometricStructure(){};
    std::vector<double> getVector()const {return _m_vec;}
    void generateVector(double, double);
    void displayVector() const;
};

void SpecialGeometricStructure::generateVector(const double a, const double b)
{
    _m_vec.clear();
    
    std::mt19937_64 gen;
    long long seed = std::chrono::system_clock::now().time_since_epoch().count();
    
    gen.seed(seed);
    std::uniform_real_distribution<> dist(a, b);
    for (int n = 0; n < 6; ++n)
    {
        _m_vec.push_back(dist(gen));
    }
}

void SpecialGeometricStructure::displayVector() const
{
    for (auto i: _m_vec)
    {
        std::cout << i << '\t';
    }
    std::cout << '\n';
}


class SomeUnknownClassToMe
{
private:
    double _monomer_mass;
    double _monomer_concentration;
    SpecialGeometricStructure _m_SGS;
    
public:
    SomeUnknownClassToMe(double m, double c) 
{_monomer_mass = m; _monomer_concentration = c; this->setSGS();}

    void setSGS() {_m_SGS.generateVector(_monomer_mass, _monomer_concentration);}
    SpecialGeometricStructure getSGS() const;
};

SpecialGeometricStructure SomeUnknownClassToMe::getSGS()const {return _m_SGS;}


int main()
{
    SomeUnknownClassToMe su_1(9,122);
    su_1.getSGS().displayVector(); // 'default' vector
    su_1.setSGS();
    su_1.getSGS().displayVector();
    
    su_1.setSGS();
    su_1.getSGS().displayVector();
    
    SomeUnknownClassToMe su_2(5,55.2);
    su_2.setSGS();
    su_2.getSGS().displayVector();
    
    return 0;
}



88.0243	49.2149	86.9656	72.1813	115.782	117.519	
118.728	89.038	88.2538	15.4579	90.4305	117.726	
38.0605	75.0771	78.4952	41.8175	19.3248	78.1441	
31.6663	12.6542	14.3089	31.844	36.4442	10.4196	
Program ended with exit code: 0
Last edited on
then output goes to the function of random_rotation, and this output goes to the actual construction of the specially rotated chain. The constructor has more functions as well, but these are not related to the random numbers.

That functionality can be added to the relevant class - SpecialGeometricStructure - by the sound of it. All by way of the other (SomeUnknownClassToMe) class member _m_SGS or separately under its own steam as a completely independent SpecialGeometricStructure object.
Thanks. So you propose to put the generator into the separate class, if I understand correctly. Respecting your work, I will try to do this and revert if it works as intended. Could you also please explain why it is better? Is it like so called good programming to use the separate classes for different things, I suppose? Or it should work more efficiently?
You obviously don't have to do it this way but it separates out into two classes what I am guessing you are trying to do without seeing the full picture.

It also enables you to isolate problems that may occur which if you look at the record here in this thread that is where it starts off.

Classes encapsulate objects (nouns) and objects have methods (c.f functions). Generating a vector (random or otherwise), a verb phrase, is a function or something an 'SGM' object does. That's the way OOP works.

If you think about it carefully, you'll see why the vector is an class/object member and generating it is something the object does to that member. The class encapsulates those two aspects. Keeping the classes simple and self-contained means they are easier to debug and can be shared jobs for a team.

Of course you can do all this with a single class but for all I know there may be other types of objects having SpecialGraphicStructures so there is greater reusability. That's up to your design.

Note also there is no need to have the twister as a data member . Why would you is my question? Only you know. All I see is that I make a couple of (su_1, su_2) objects by declaring them and telling them to go to work.


It's not the only way but there are lots of benefits with OOP ... same for C++ I suppose.

https://www.learncpp.com/cpp-tutorial/81-welcome-to-object-oriented-programming/



Thanks. I guess intuitively I am more into the functional programming as I tend to put everything in one place according their functionality, and OOP is counterintuitive for me however I recognize the benefits of it especially when everything grows and I accept that this is a way to go.
To sump up, after learning about more about the topic, it seems that mutable type could be possibly thread-unsafe, so the separation of random generator in to the other class is the way to go indeed.
Last edited on
Topic archived. No new replies allowed.