32

だから私は Random オブジェクトを持っています:

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);
}

分布の上限を (別の関数またはその他の方法で) 変更できる最善の方法は何ですか?

(他のスタイルの問題についても喜んでアドバイスします)

4

3 に答える 3

53

配布オブジェクトは軽量です。乱数が必要な場合は、新しい分布を構築するだけです。私はこのアプローチをゲーム エンジンで使用しています。ベンチマーク後、古き良き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);
}
于 2013-09-26T18:52:37.580 に答える
14

メソッドstd::uniform_int_distribution<uint32>::param_typeを使用して範囲を作成し、変更するだけです。param()次の方法でテンプレートのノイズを削減できますdecltype

decltype(uniform_dist.param()) new_range (0, upper);
uniform_dist.param(new_range);
于 2013-09-26T19:33:06.937 に答える
7

私は私の例のDrawNumber関数publicを作っています。上限を取るオーバーロードを提供し、次に newuniform_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られた によって命名された型ですDparam_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;
}
于 2013-09-26T18:54:52.987 に答える