Различный диапазон

Итак, у меня есть случайный объект:

typedef unsigned int uint32;

class Random {
public:
Random() = default;
Random(std::mt19937::result_type seed) : eng(seed) {}

private:
uint32 DrawNumber();
std::mt19937 eng{std::random_device{}()};
std::uniform_int_distribution<uint32> uniform_dist{0, UINT32_MAX};
};

uint32 Random::DrawNumber()
{
return uniform_dist(eng);
}

Как лучше всего изменить (с помощью другой функции или иным образом) верхнюю границу распределения?

(также готовы принять совет по другим вопросам стиля)

20

Решение

Распределение объектов облегчено. Просто создайте новый дистрибутив, когда вам нужно случайное число. Я использую этот подход в игровом движке, и после бенчмаркинга он сравним с использованием старого доброго rand(),

Кроме того, я спросил, как изменить диапазон распространения в прямом эфире GoingNative 2013, и Стивен Т. Лававей, член комитета по стандартизации, предложил просто создать новые дистрибутивы, так как это не должно быть проблемой производительности.

Вот как бы я написал ваш код:

using uint32 = unsigned int;

class Random {
public:
Random() = default;
Random(std::mt19937::result_type seed) : eng(seed) {}
uint32 DrawNumber(uint32 min, uint32 max);

private:
std::mt19937 eng{std::random_device{}()};
};

uint32 Random::DrawNumber(uint32 min, uint32 max)
{
return std::uniform_int_distribution<uint32>{min, max}(eng);
}
35

Другие решения

Вы можете просто создать std::uniform_int_distribution<uint32>::param_type и измените диапазон, используя param() метод. Вы можете уменьшить шум шаблона с decltype :

decltype(uniform_dist.param()) new_range (0, upper);
uniform_dist.param(new_range);
8

Я делаю DrawNumber функция public для моего примера. Вы можете предоставить перегрузку, которая принимает верхнюю границу, а затем передать новый uniform_int_distribution::param_type в uniform_int_distribution::operator()

param_type может быть построен с использованием тех же аргументов, что и соответствующее распределение.

От N3337, §26.5.1.6 / 9 [Rand.req.dist]

Для каждого из конструкторов D принимая аргументы, соответствующие параметрам распределения, P должен иметь соответствующий конструктор, отвечающий тем же требованиям и принимать аргументы, идентичные по числу, типу и значениям по умолчанию. Более того, для каждой из функций-членов D которые возвращают значения, соответствующие параметрам распределения, P должна иметь соответствующую функцию-член с идентичным именем, типом и семантикой.

где D тип объекта функции распределения случайных чисел и P это тип, названный Dассоциируется param_type

#include <iostream>
#include <random>

typedef unsigned int uint32;

class Random {
public:
Random() = default;
Random(std::mt19937::result_type seed) : eng(seed) {}

uint32 DrawNumber();
uint32 DrawNumber(uint32 ub);

private:
std::mt19937 eng{std::random_device{}()};
std::uniform_int_distribution<uint32> uniform_dist{0, UINT32_MAX};
};

uint32 Random::DrawNumber()
{
return uniform_dist(eng);
}

uint32 Random::DrawNumber(uint32 ub)
{
return uniform_dist(eng, decltype(uniform_dist)::param_type(0, ub));
}

int main()
{
Random r;
std::cout << r.DrawNumber() << std::endl;
std::cout << r.DrawNumber(42) << std::endl;
}
6
По вопросам рекламы [email protected]