Генерация числа (0,1) с использованием мерсеннского твистера С++

Я работаю над внедрением R-кода в C++, чтобы он работал быстрее, но у меня возникают трудности с реализацией мерсенн-твистер. Я хочу генерировать значения только между (0,1). Вот что у меня есть по этому вопросу.

#include <random>

std::mt19937 generator (123);

std::cout << "Random value: " << generator() << std:: endl;

Я попытался разделить на RAND_MAX, но это не дало значений, которые я искал.

Заранее спасибо.


person user3508622    schedule 07.04.2014    source источник
comment
взгляните на std::uniform_real_distribution<float>   -  person OMGtechy    schedule 08.04.2014


Ответы (3)


В С++ 11 понятия "(псевдо) случайный генератор" и "распределение вероятностей" разделены, и на то есть веские причины.

То, что вы хотите, может быть достигнуто с помощью следующих строк:

  std::mt19937 generator (123);
  std::uniform_real_distribution<double> dis(0.0, 1.0);

  double randomRealBetweenZeroAndOne = dis(generator);

Если вы хотите понять, почему это разделение необходимо и почему использование стандартного деления/диапазона на выходе генератора — плохая идея, посмотрите это видео.

person sbabbi    schedule 07.04.2014
comment
использование стандартной манипуляции с делением/диапазоном на выходе генератора само по себе неплохая идея, именно так мы создаем определенные распределения или стохастические процессы для случайных величин. - person 4pie0; 08.04.2014
comment
и на самом деле стандартные реализации (по крайней мере, я проверил boost) выполняют простую манипуляцию диапазоном вычитания/деления. Это плохо? - person galinette; 08.04.2014
comment
однажды stl предоставит класс для вычисления процента. Потому что деление на ссылку и умножение на 100 может быть вредным. - person galinette; 08.04.2014
comment
@galinette, почему вы говорите, что это может быть вредно? - person kmiklas; 20.07.2016
comment
Будет ли это генерировать случайные числа, исключая 0 и 1, или включает границы 0 и 1?? Я хочу исключить значения 0 и 1 - person Shashank Shekhar; 05.10.2018
comment
Это будет включать 0, как описано здесь: cplusplus.com/reference/random/uniform_real_distribution. Быстрое исправление для исключения 0 состоит в том, чтобы добавить элемент управления if для того, является ли сгенерированное число равным 0, и повторно сгенерировать, когда это так (что почти никогда не произойдет). - person GabCaz; 11.07.2020

Вы можете рассмотреть такой код:

// For pseudo-random number generators and distributions
#include <random> 

...
    
// Use random_device to generate a seed for Mersenne twister engine.
std::random_device rd{};    

// Use Mersenne twister engine to generate pseudo-random numbers.
std::mt19937 engine{rd()};

// "Filter" MT engine's output to generate pseudo-random double values,
// **uniformly distributed** on the closed interval [0, 1].
// (Note that the range is [inclusive, inclusive].)
std::uniform_real_distribution<double> dist{0.0, 1.0};

// Generate pseudo-random number.
double x = dist(engine);

Дополнительные сведения о создании псевдослучайных чисел в C++ (включая причины, по которым rand() не подходит) см. в этом видео Stephan T. Lavavej (от Going Native 2013):

rand() считается вредным

person Mr.C64    schedule 08.04.2014

std::mt19937 генерирует не от 0 до RAND_MAX, как rand(), а от 0 до 2^32-1.

И, кстати, класс предоставляет значения min() и max()!

Вам нужно преобразовать значение в двойное, вычесть min() и разделить на max()-min()

uint32_t val;
val << generator;
double doubleval = ((double)val - generator::min())/(generator::max()-generator::min());

или (менее общий)

uint32_t val;
val << generator;
double doubleval = (double)val * (1.0 / std::numeric_limits<std::uint32_t>::max());
person galinette    schedule 07.04.2014
comment
Возможно, вы захотите объяснить это длинное двойное значение. Или заменить его на 1.0 / std::numeric_limits<std::uint32_t>::max() - person Brandon; 08.04.2014