Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> default_random_engine и классы 
V
    Опции темы
Luyan
Дата 15.12.2013, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 3.12.2008

Репутация: 2
Всего: 7



Доброго времени суток.
Использовал в С++ прошлого стандарта rand(), а srand() делал глобально.
srand() менял в цикле и получал различные результаты (для усреднения и тд).
Есть проект, несколько классов и все вызывают rand() в различных местах.
Но теперь появилась потребность в некоторых классах кое-где использовать нормальное распеределение, вместо равномерного. Поэтому начал переводить код на C++11 с их рандомом и использовать uniform_real_distribution и normal_distribution.
Вот как было раньше, упрощенный пример:
Код

#include <iostream>
#include <cstdlib>

class B
{
public:
  B(){}
  int random()
  {
    return rand()%100;
  }
  // ....
};

class A
{
public:
  A(){}
  void load()
  {
    B obj2;
    std::cout << obj2.random() << std::endl;
  }
  // ....
};

int main()
{
  int n = 10; 
  A obj;
  
  for(int i = 0; i < n; i++)
  {
    // ....
    srand(1+i);
    obj.load();
    // ....
  }
}


А вот как я пытаюсь делать сейчас:
Код

#include <iostream>
#include <random>

class B
{
  std::default_random_engine generator_b;
public:
  B(std::default_random_engine& t)
  {
    generator_b = t;
  }
  int random()
  {
    std::uniform_int_distribution<int> dist(0,9);
    return dist(generator_b);
  }
};

class A
{
protected:
  std::default_random_engine generator_a;
public:
  A():generator_a(std::default_random_engine()){}
  void set_seed(int t)
  {
    generator_a.seed(t);
  }
  void load()
  {
    B obj2(generator_a);
    std::cout << obj2.random() << std::endl;
  }
};

int main()
{
  int n = 10;
  
  A obj;
  for(int i = 0; i < n; i++)
  {
    // ....
    obj.set_seed(1+i);
    obj.load();
    // ....
  }
}


Но это почему-то не работает - выдает нули. В чем ошибка?
Как я понимаю, в C++11 надо везде таскать за собой generator?
Или есть другие способы, кроме глобального объявления? 

PM   Вверх
akizelokro
Дата 15.12.2013, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Код

  int random()
  {
    std::uniform_int_distribution<int> dist(0,9);
    return dist(generator_b);
  }


Каждый раз создаётся std::uniform_int_distribution<int>, попробуй его сделать членом класса B, а создание перенести в конструктор.


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
Luyan
Дата 15.12.2013, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 3.12.2008

Репутация: 2
Всего: 7



Цитата(akizelokro @  15.12.2013,  17:26 Найти цитируемый пост)
создание перенести в конструктор

Создание в смысле установки параметров? или сделать поле dist указателем и через new в конструкторе выделять?
сделал так:
Код

class B
{
  std::default_random_engine generator_b;
  std::uniform_int_distribution<int> dist;
public:
  B(std::default_random_engine& t):generator_b(t),dist(0,9)
  {
    std:: cout << "a: " << dist.a() << ", b: " << dist.b() << std::endl;   
  }
  int random()
  {
    return dist(generator_b);
  }
};

Код все равно выдает 0:
Код

a: 0, b: 9
0
a: 0, b: 9
0
a: 0, b: 9
0
a: 0, b: 9
0
a: 0, b: 9
0
a: 0, b: 9
0
a: 0, b: 9
0
a: 0, b: 9
0
a: 0, b: 9
0
a: 0, b: 9
0

А generator типа default_random_engine можно просто делать членом класса? или есть какие-нибудь ограничения? похоже в этом проблема. В сети ничего стоящего по этой теме не могу найти, все останавливаются на примерчиках в main.
PM   Вверх
akizelokro
Дата 15.12.2013, 21:30 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Да просто и genertor'ы и все виды distribution'ов в новом стандарте уже сами классы, в стандарте уже сделана работа, которую ты пытаешься повторить, по идее просто делай, как указано в примерах. Потому что по моему имхо ты делаешь не совсем нужное усложнение.
Потом же смотри, судя по твоему листингу у тебя постоянно идёт сообщение из конструктора
Код

a: 0, b: 9

то есть, ты ещё где-то код изменил. Смысл моего предложения был в том, чтобы uniform_int_distribution не пересоздавался каждый раз, потому что с этой мутью я уже сталкивался в том плане, что эти генераторы и распределения псевдослучайны и тупо повторяютя на первом шагу. А если бы ты брал второй шаг, было бы уже другое 
Понял, это у тебя в
Код

  void load()
  {
    B obj2;
    std::cout << obj2.random() << std::endl;
  }


где ты при каждом вызове создаёшь класс B по новой. Сделай экземпляр класса B членом класса А и посмотри.
Код

class A {
...
B obj2; // здесь добавил
...
  void load()
  {
//    B obj2(generator_a); - здесь убрал
    std::cout << obj2.random() << std::endl;
  }



--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
Luyan
Дата 15.12.2013, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 3.12.2008

Репутация: 2
Всего: 7



Цитата(akizelokro @  15.12.2013,  21:30 Найти цитируемый пост)
эти генераторы и распределения псевдослучайны и тупо повторяютя на первом шагу

Вот за эту фразу большое спасибо. Проверил, действительно:
Код

int main()
{
  int n = 10;
  std::default_random_engine generator;
  std::uniform_int_distribution<int> dist(0,9);
  //std::uniform_real_distribution<double> dist(0.0,1.0);
  
  for(int i = 0; i < n; i++)
  {
    generator.seed(1+i);
    for(int j = 0; j < 5; j++)
      std::cout << dist(generator) << ' ';
    std::cout << std::endl;
  }
}

Выдает:
Код

0 1 7 4 5 
0 2 5 9 0 
0 3 2 3 5 
0 5 0 8 1 
0 6 7 2 6 
0 7 5 7 1 
0 9 2 2 7 
0 0 0 6 2 
0 1 8 1 7 
0 3 5 5 3

Хорошо, что это не справедливо для вещественных типов:
Код

0.131538 0.45865 0.218959 0.678865 0.934693 
0.263076 0.9173 0.437918 0.357729 0.869386 
0.394613 0.37595 0.656878 0.0365942 0.804079 
0.526151 0.834601 0.875837 0.715459 0.738772 
0.657689 0.293251 0.0947959 0.394324 0.673464 
0.789227 0.751901 0.313755 0.0731883 0.608157 
0.920765 0.210551 0.532714 0.752053 0.54285 
0.0523023 0.669201 0.751673 0.430918 0.477543 
0.18384 0.127851 0.970633 0.109782 0.412236 
0.315378 0.586501 0.189592 0.788647 0.346929


Короче, с классами тоже все работает. Спасибо.
PM   Вверх
akizelokro
Дата 16.12.2013, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Да я столкнулся сам как-то раз с таким поведением для Visual Studio, правда, как я от этого ушёл для int'ов, надо смотреть. А тут у тебя наслоилось всё это, что ты "дёргал" только первую цифру. Ну, я и подумал, что это из той темы, а даже не из ошибок, но до конца не был уверен, потому что дело было давно. Скажем так, что-то меня подталкивало подозревать..


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0715 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.