(PHP 8 >= 8.3.0)
Random\Randomizer::nextFloat — 半開区間 [0.0, 1.0) から、float の値を取得する
半開区間(左閉右開) に一様に分散した float を等確率に返します。
区間には 0.0
を含み、1.0
までですが、
1.0
そのものは含みません。
返される float の値が、指定された右開の部分区間にある確率は、
部分区間の大きさに比例します。
つまり、返される float が 0.5
より小さい
確率は50%ということです。これは float が 少なくとも
0.5
以上である確率と等しくなります。
同様に、返される float が、区間 0.2
から
0.25
未満までに収まる確率は、ちょうど 5% になります。
この性質を使うと、Random\Randomizer::nextFloat() を活用して返される float が指定された確率 より小さい ことをチェックすることで、 指定された確率でランダムな boolean 値を生成することが可能になります。
注意:
Random\Randomizer::nextFloat() が返す可能性がある float の値の範囲は、
Randomizer::getFloat(0.0, 1.0, IntervalBoundary::ClosedOpen)
と同じです。ですが、内部的な Random\Randomizer::nextFloat() の実装はより効率的です。
乗算や加算(いわゆるアフィン変換)を使って、 この関数の戻り値を異なる区間に拡大/縮小すると、 結果の値に偏りが出るかもしれません。 なぜなら、浮動小数点数は数直線上で均一に分布するわけではないからです。 全ての値が浮動小数点数によって正確に表現できるとは限らないので、 アフィン変換の結果が暗黙の丸め処理によって求める区間から外れた値になってしまう可能性もあります。 アフィン変換の結果生じる問題の 詳細な説明 は、Random\Randomizer::getFloat() のドキュメントに説明があります。
任意の区間内でランダムな float の値を生成するには、 Random\Randomizer::getFloat() を使います。任意の区間内でランダムな整数を生成するには、 Random\Randomizer::getInt() を使います。
この関数にはパラメータはありません。
半開区間 [0.0, 1.0) (IntervalBoundary::ClosedOpen
)
に一様に分散した float を等確率に返します。
返される値には 0.0
を含みますが、
1.0
は含みません。
Random\Randomizer::$engine
に存在する
Random\Engine::generate() メソッド
がスローした、あらゆる Throwable がスローされます。
例1 Random\Randomizer::nextFloat() の例
<?php
$r = new \Random\Randomizer();
// 返される bool 値は、指定された確率で true になります
$chance = 0.5;
$bool = $r->nextFloat() < $chance;
echo ($bool ? "You won" : "You lost"), "\n";
?>
上の例の出力は、 たとえば以下のようになります。
You won
例2 アフィン変換を使った間違った拡大演算
<?php
final class MaxEngine implements Random\Engine {
public function generate(): string {
return "\xff";
}
}
$randomizer = new \Random\Randomizer(new MaxEngine);
$min = 3.5;
$max = 4.5;
// 以下は絶対やらないで!:
//
// 以下のコードは nextFloat() が 1を絶対に含まない半開区間からサンプリングしたに
// も関わらず、4.5 を出力します。
printf("Wrong scaling: %.17g", $randomizer->nextFloat() * ($max - $min) + $min);
// 正しくは、以下のようにします:
// $randomizer->getFloat($min, $max, \Random\IntervalBoundary::ClosedOpen);
?>
上の例の出力は以下となります。
Wrong scaling: 4.5