namespace std {
template<class RealType, std::size_t bits, class URBG>
RealType generate_canonical(URBG& g); // (1) C++11
template<class RealType, std::size_t digits, class URBG>
RealType generate_canonical(URBG& g); // (1) C++26
}
概要
実数区間[0.0, 1.0)に展開(事実上正規化)された一様分布乱数を得るための関数テンプレート。
テンプレート引数に与える RealType 型について、 bits だけの分解能を持つ仮数部を URBG gを必要な回数だけ繰り返し呼び出して生成する。
テンプレートパラメータ
class RealType: 生成する実数の型。size_t bits: 生成する実数における仮数部への分解能の最低要求。最大値はstd::numeric_limits<RealType>::digits- C++26で
digitsに名称変更
- C++26で
size_t digits: 生成する実数における基数非依存の桁数としての分解能の最低要求。最大値はstd::numeric_limits<RealType>::digits。class URBG: 一様乱数生成器の型。
関数パラメータ
- URBG& g : 一様乱数生成器。
効果
-
C++11からC++23まで : 以下の変数を定義する。
戻り値は
S/Rkとなる。ただし浮動小数点数の丸めにより、結果が1.0になる場合がある。 -
C++26 : 以下の変数を定義する。
r=numeric_limits<RealType>::radixR=g.max() - g.min() + 1d= min(digits,numeric_limits<RealType>::digits)k=Rk≥rdを満たす最小の整数x= ⌊Rk/rd⌋
以下の手順で乱数を生成する。
g()をk回呼び出して値Sを生成するS≥x·rdの場合、手順1に戻って再試行する(棄却法)- 戻り値は ⌊
S/x⌋ /rdとなる
この棄却法により、浮動小数点数の丸めで結果が1.0になる問題が解消され、戻り値は必ず0以上1未満となることが保証される。
例外
URBG g が例外を送出する場合はそれに準ずる。
備考
- C++23まではアルゴリズムの仕様上、浮動小数点数の丸めにより値
1.0が生成されることがあった - C++26では棄却法(reject-and-retry)方式が導入され、戻り値が[0.0, 1.0)の範囲内であることが保証されるようになった
例
#include <random>
#include <iostream>
#include <cstdint>
int main()
{
std::random_device seed_gen;
std::uint32_t seed = seed_gen();
std::mt19937 engine(seed);
for(int i = 0; i < 10; ++i) {
// floatの仮数部桁数で、範囲[0.0, 1.0)のランダムなfloat値を生成する
constexpr std::size_t bits = std::numeric_limits<float>::digits;
float result = std::generate_canonical<float, bits>(engine);
std::cout << result << std::endl;
}
}
出力
0.93695
0.880826
0.0535227
0.174785
0.989711
0.393811
0.588513
0.383415
0.920717
0.216669
バージョン
言語
- C++11
処理系
- Clang: 3.0 ✅
- GCC: 4.4 ✅
- ICC: ??
- Visual C++: ??
備考
- GCC 4.9時点において、
float型を指定した場合に、値1.0が生成されることがあるバグがある(Bug 63176) - Clang 3.3時点において、値
1.0が生成されることがある(Bug 18767)
参照
- P0346R1 A
<random>Nomenclature Tweak- URNGをURBGに変更
- P0952R2 A New Specification for
generate_canonical- C++26でテンプレートパラメータ名を
bitsからdigitsに変更し、棄却法による新しいアルゴリズムを導入
- C++26でテンプレートパラメータ名を