4

Вопрос по c++, c++11, random – генерация случайных чисел двойников между двумя интервалами [a, b]

Мне нужно сгенерироватьX случайные двойные числа, равномерно распределенные между двумя интервалами [a, b], гдеa а такжеb также двойные числа.

ТеX числа должны быть сгенерированы внутри функции класса, скажемmyclass::doSomething(a,b), Дело в том, что интервалы[a,b] перешел кdoSomething(a,b) функция меняется каждый раз, когдаdoSomething(a,b) функция вызывается другой функцией класса, скажемdoThat().

Я хотел бы решение, которое позволяет мне:
1. Иметьengine с большей областью действия, в идеале, он должен быть посеян только один раз за запуск приложения.
2. TheX случайные двойные числа, генерируемые внутри каждого отдельного вызоваdoSomething() функция, должна быть равномерно распределена.

Мое решение, приведенное ниже, не позволяетengine и кажется, что сгенерированные числа не обязательно распределены равномерно.

//file: utilities.h
template <typename Generator>
double randomDoubleEngine(Generator& engine, double low_bound, double high_bound )
{
        if (low_bound > high_bound){
                std::swap(low_bound, high_bound);
        }

        return std::uniform_real_distribution<>( low_bound, high_bound )( engine );
}

//file: myclass.h
       void myclass::doThat(param1, param2){

            for(int i=0; i < myclass.iter; i++){
                ...
                ...
                doSomething(a,b);
                ...
            }

        }

        void myclass::doSomething(double a, double b)
        {
                std::random_device rd;
                static std::mt19937 engine(rd());
                .....
                double curThreshold = randomDoubleEngine(engine, a, b);
                ...
         }

Ваше решение работает? Если да, то какую проблему вам нужно решить? Другими словами, какой вопрос для SO-аудитории?

Apr 06, 2012, 1:45 PMот

Какой тест вы использовали для определения равномерности распределения, и каков был ваш размер выборки? Кстати, следует отметить, что разница между двумя сгенерированными числами<b>not</b> равномерно распределены, когда два числа.

Apr 06, 2012, 2:04 PMот

@ OliCharlesworth, мое решение не работает полностью. Я обновил свой оригинальный пост. Во-первых,<code>engine</code> не является глобальным, и, во-вторых, сгенерированные числа, кажется, не распределены равномерно.

Apr 06, 2012, 1:49 PMот

1ответ

2

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

Также обратите внимание, что gcc выглядит неправильно по сравнению со стандартом (см. Ссылки в комментариях к коду), поэтому, если вы используете его, это может объяснить, почему любой тест, который вы применяете к этим числам (для проверки равномерного распределения), дает сбой. Как я понимаю, gcc хочет, чтобы механизм возвращал числа в [0,1), в то время как стандарт говорит, что это должны быть одинаковые целые числа в некотором диапазоне.

Я боюсь, что смогу протестировать это только с помощью gcc 4.4, так как я использую более старую версию Ubuntu, а ideone, похоже, не разрешает std :: random_device.

#include <random>
#include <iostream>

/* In GCC 4.4, uniform_real_distribution is called uniform_real; renamed in 4.5
 *
 * However, GCC's description here
 *
 * http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-api-4.6/a00731.html
 *
 * doesn't match expectation here
 *
 * http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution
 *
 * which seems to match 26.5.8.2.2 of N3337
 *
 */
#if defined(__GNUC_MINOR__) && (__GNUC_MINOR__ <= 4)
#  define uniform_real_distribution uniform_real
#endif

template <typename Generator>
double randomDoubleEngine(Generator& engine, double low_bound, double high_bound)
{
  if (low_bound > high_bound){
    std::swap(low_bound, high_bound);
  }
  return std::uniform_real_distribution<double>(low_bound, high_bound)(engine);
}

class myclass
{
  double curThreshold;
  static std::mt19937 engine;
  void doSomething(double a, double b)
  {
    curThreshold= randomDoubleEngine(engine, a, b);
  }
public:
  myclass(): curThreshold(0) {}

  void doThat(){
    doSomething(0,10);
    std::cout << "threshold is " << curThreshold << std::endl;
  }
};

std::mt19937 myclass::engine=std::mt19937(std::random_device()());

int
main()
{
  myclass m;
  m.doThat();
  m.doThat();
  return 0;
}

RelatedQuestions