だから私はランダムオブジェクトを持っています:
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);
}
分布の上限を(別の関数またはその他の方法で)変更できる最善の方法は何ですか?
(他のスタイルの問題についても喜んでアドバイスを受けます)
配布オブジェクトは軽量です。乱数が必要な場合は、新しい分布を作成するだけです。私はこのアプローチをゲームエンジンで使用しており、ベンチマーク後は、古き良きRand()
を使用するのと同等です。
また、GoingNative 2013ライブストリームで配信の範囲を変更する方法を尋ねたところ、標準委員会のメンバーであるStephen T. Lavavejは、パフォーマンスの問題ではないため、単に新しい配信を作成することを提案しました。
これが私があなたのコードを書く方法です:
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);
}
param()
メソッドを使用して、_std::uniform_int_distribution<uint32>::param_type
_を作成し、範囲を変更するだけです。テンプレートのノイズはdecltype
で削減できます。
_decltype(uniform_dist.param()) new_range (0, upper);
uniform_dist.param(new_range);
_
私の例では、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;
}
_