如何在PHP中生成0到1之间的随机浮点数?
我正在寻找PHP中等同于Java的Math.random()
的函数。
大多数答案都使用mt_rand
。然而,mt_getrandmax()
通常只返回2147483647
。这意味着您只有31位信息,而双精度浮点数具有52位的尾数,这意味着在0和1之间的数字至少有2^53
的密度。
这种更复杂的方法将为您提供更好的分布:
function rand_754_01() {
// Generate 64 random bits (8 bytes)
$entropy = openssl_random_pseudo_bytes(8);
// Create a string of 12 '0' bits and 52 '1' bits.
$x = 0x000FFFFFFFFFFFFF;
$first12 = pack("Q", $x);
// Set the first 12 bits to 0 in the random string.
$y = $entropy & $first12;
// Now set the first 12 bits to be 0[exponent], where exponent is randomly chosen between 1 and 1022.
// Here $e has a probability of 0.5 to be 1022, 0.25 to be 1021, etc.
$e = 1022;
while($e > 1) {
if(mt_rand(0,1) == 0) {
break;
} else {
--$e;
}
}
// Pack the exponent properly (add four '0' bits behind it and 49 more in front)
$z = "\0\0\0\0\0\0" . pack("S", $e << 4);
// Now convert to a double.
return unpack("d", $y | $z)[1];
}
$z = "\0\0\0\0\0\0" . pack("S", $e << 4);
与其大端兄弟:
$z = pack("S", $e << 4) . "\0\0\0\0\0\0";
只有在函数被调用大量次数时才会有明显的差异:10^9
或更多。
测试是否有效
很明显,尾数遵循一个漂亮的均匀分布近似,但是一个大量这样的分布之和(每个分布具有累计减半的机会和振幅)是均匀的,这一点不太明显。
正在运行:
function randomNumbers() {
$f = 0.0;
for($i = 0; $i < 1000000; ++$i) {
$f += \math::rand_754_01();
}
echo $f / 1000000;
}
生成一个输出值为0.49999928273099
(或接近0.5的类似数字)。
$a = random_bytes(8); $a[0] = "\x3f"; $a[1] = $a[1] | "\xf0"; return unpack('E', $a)[1] - 1.0;
- Nommyde我在PHP.net上找到了答案。
<?php
function randomFloat($min = 0, $max = 1) {
return $min + mt_rand() / mt_getrandmax() * ($max - $min);
}
var_dump(randomFloat());
var_dump(randomFloat(2, 20));
?>
float(0.91601131712832)
float(16.511210331931)
所以你可以这样做
randomFloat(0,1);
或者简单一点
mt_rand() / mt_getrandmax() * 1;
这个怎么样:
echo (float)('0.' . rand(0,99999));
可能会很好地工作...希望能对你有所帮助。
rand()
文档中有一些示例。 - Michael Berkowski