Случайные числа в конструкторе массива объектов - PullRequest
1 голос
/ 27 марта 2020

Во-первых, извините, если это глупый вопрос, но я недавно научился обращаться с классами. Моя проблема в том, что я создал конструктор, который дает каждому элементу данных случайное число со следующим синтаксисом:

#include <random>

...

//Constructor
cSystem::cSystem(void)
{
//Range of random numbers
double lower_bound = -100;
double upper_bound = 100;
std::uniform_real_distribution<double> unif(lower_bound,upper_bound);
std::default_random_engine re;

/*Initialization of data members*/
sMass=1.0014;
sPositionX= unif(re);
sPositionY= unif(re);
}

Но затем я хочу создать массив этих "систем" в моей главной функции

int main (void)
{
cSystem systems[numsist]; //numsist is a constant defined to be 1000

//Function that writes its characteristics in a file using a method that returns positions
getPositions(systems);

return 0;
}

Но в файле я просто получаю

-73.6924    -8.26997
-73.6924    -8.26997
-73.6924    -8.26997

Я думал, что я прохожу через конструктор для каждого элемент массива, давая ему другое случайное значение, но кажется, что в начале дается одно значение, а затем оно повторяется по всему вектору. Что я могу сделать, чтобы получить конструктор, который инициализирует каждый элемент случайным образом?

Примечание: я также получаю одинаковые значения при каждом запуске программы, я полагаю, что начальное число не меняется, почему случай

Ответы [ 2 ]

0 голосов
/ 27 марта 2020

Моя проблема в том, что я создал конструктор, который дает каждому элементу данных случайное число

  • Вы не заполняете PRNG, когда создаете его по умолчанию. Каждый раз он будет начинаться с состояния по умолчанию.
  • Предполагается, что PRNG не принадлежит ни одному классу один . Заполнить его дорого, и предполагается, что он используется всеми функциями (для каждого потока), которым необходимо генерировать случайные числа, поэтому отделите его от любых классов.

Я предпочитаю выбирать определенный PRNG , но по умолчанию это может выглядеть так:

std::default_random_engine& prng() {
    // seed only one PRNG per thread that needs is:
    static thread_local std::default_random_engine gen(std::random_device{}());
    return gen;
}

В каждой функции распределения (функции-члене или иным образом), которую вы используете в своей программе, вы можете теперь вызывать prng(), чтобы получить генератор, отобранный один раз , а не превышен .

0 голосов
/ 27 марта 2020

Вы получаете одинаковые значения sPositionX и sPositionY для каждого экземпляра cSystem, поскольку вы создаете std::uniform_real_distribution<double> и std::default_random_engine каждый раз, когда вызывается конструктор.

You нужно создать их один раз и повторно использовать в конструкторе. Один из способов сделать это - создать объекты класса static.

struct cSystem
{
   ...

   static std::uniform_real_distribution<double> unif;
   static std::default_random_engine re;
};

и просто использовать их в конструкторе.

Вот полная программа.

#include <random>
#include <iostream>

struct cSystem
{
   cSystem();

   double sPositionX;
   double sPositionY;
   double sMass;

   static std::uniform_real_distribution<double> unif;
   static std::default_random_engine re;
};

std::uniform_real_distribution<double> cSystem::unif(-100, 100);
std::default_random_engine cSystem::re;

//Constructor
cSystem::cSystem()
{
   /*Initialization of data members*/
   sMass=1.0014;
   sPositionX= unif(re);
   sPositionY= unif(re);
}

void getPositions(cSystem* systems)
{
   for (unsigned i = 0; i < 3; ++i )
   {
      std::cout << systems[i].sPositionX << " " << systems[i].sPositionY << std::endl;
   }
}

int main (void)
{
   cSystem systems[3];

   getPositions(systems);

   return 0;
}

См., Что это работает на https://ideone.com/bS8E4u.

Обновление в ответ на комментарий ОП.

Вы можете инициализировать re, как показано ниже, чтобы получить другое случайное значение номера при повторном запуске программы.

std::default_random_engine cSystem::re{std::random_device()()};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...