PHP中0到1之间的随机浮点数

47

如何在PHP中生成0到1之间的随机浮点数?

我正在寻找PHP中等同于Java的Math.random()的函数。


1
rand() 文档中有一些示例。 - Michael Berkowski
那不会返回一个整数吗? - Goaler444
1
Goaler 作为程序员,您的工作是使用算术操作将 int 值转换成 float 值。文档中有详细说明。@dystroy 在此为您提供了复制内容,以方便参考。 - Michael Berkowski
好的,谢谢 =) 对于任何不便我表示抱歉(我更习惯使用Java) - Goaler444
2
我不明白为什么这个问题被关闭了。在我看来,它似乎是完全合法的。我浏览了文档,但没有找到答案。提名重新开放。 - Erick Robertson
请参考 https://dev59.com/pc8D0IgBFxS5KdRjkOQA#14155720 和第一条评论。 - caw
13个回答

45
你可以使用标准函数:lcg_value()
以下是在rand()文档中提供的另一个函数:
// auxiliary function
// returns random number with flat distribution from 0 to 1
function random_0_1() 
{
    return (float)rand() / (float)getrandmax();
}

11
在 PHP 4 和 5 中,mt_rand() 被认为比 rand() 生成的随机数更加随机。翻译后的代码为:return (float) mt_rand() / (float) mt_getrandmax(); - Tim S.
8
在 PHP 7.1+ 中,rand 现在是 mt_rand 的别名。 - apokryfos
getrandmax和mt_getrandmax即使在64位系统上也返回2147483647。因此,您可以使用random_int(0, 999999999999999) / 1000000000000000来增加分辨率。 - Nommyde

25

文档示例:

function random_float ($min,$max) {
   return ($min+lcg_value()*(abs($max-$min)));
}

3
+1 这是一个更通用的方法,它将返回一个随机浮点数值,该值受给定的最小和最大浮点值的限制。 - Erick Robertson

8
class SomeHelper
{
     /**
     * Generate random float number.
     *
     * @param float|int $min
     * @param float|int $max
     * @return float
     */
    public static function rand($min = 0, $max = 1)
    {
        return ($min + ($max - $min) * (mt_rand() / mt_getrandmax()));
    }
}

7
rand(0,1000)/1000 returns:
0.348 0.716 0.251 0.459 0.893 0.867 0.058 0.955 0.644 0.246 0.292

如果您想在小数点后面有更多的数字,则可以使用更大的数字。


4
function mt_rand_float($min, $max, $countZero = '0') {
    $countZero = +('1'.$countZero);
    $min = floor($min*$countZero);
    $max = floor($max*$countZero);
    $rand = mt_rand($min, $max) / $countZero;
    return $rand;
}

例子:

echo mt_rand_float(0, 1);

result: 0.2

echo mt_rand_float(3.2, 3.23, '000');

结果:3.219

echo mt_rand_float(1, 5, '00');

结果:4.52

echo mt_rand_float(0.56789, 1, '00');

result: 0.69


4

更新:忘记这个答案,它不适用于 PHP -v > 5.3。

那么呢?

floatVal('0.'.rand(1, 9)); 

对我来说,这很完美,不仅适用于0-1的范围,例如在1.0-15.0之间也可以使用。

 floatVal(rand(1, 15).'.'.rand(1, 9)); 

2
至少有一个:D,但请注意,“数字构建”与算术无关,尽管它确实有效。 - john Smith
你遇到了什么错误?我刚刚尝试了5.4.36版本,我的第一个示例可以正常工作。 - john Smith
啊,我明白了。http://sandbox.onlinephpfunctions.com/code/65f71b02a4cfbda5698549892887fcb92f1edc6f - john Smith

3
$random_number = rand(1,10).".".rand(1,9);

3

PHP 7的解决方案。生成[0,1)范围内的随机数,即包括0但不包括1。

function random_float() {
    return random_int(0, 2**53-1) / (2**53);
}

感谢评论区的Nommyde指出我的错误。

>>> number_format((2**53-1)/2**53,100)
=> "0.9999999999999998889776975374843459576368331909179687500000000000000000000000000000000000000000000000"
>>> number_format((2**53)/(2**53+1),100)
=> "1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

1
(PHP_INT_MAX - 1) / PHP_INT_MAX 等于浮点数 1.0000。因此,如果您不想包含 1,则可以使用 15 位数字或更少: random_int(0, 999999999999999) / 1000000000000000 - Nommyde
@Nommyde 很好的发现...我以为那只是显示舍入,但事实证明它是真的。我会稍微调整我的答案。 - mpen

1
function frand($min, $max, $decimals = 0) {
  $scale = pow(10, $decimals);
  return mt_rand($min * $scale, $max * $scale) / $scale;
}

echo "frand(0, 10, 2) = " . frand(0, 10, 2) . "\n";

1
这个问题要求一个从0到1的值。对于大多数数学目的来说,这通常是无效的,尽管可能性非常小。标准分布按惯例为0 >= N < 1。您应该考虑是否真的需要包括1。
许多不经意间做这件事的东西会有一亿分之一的异常结果。如果你考虑把操作倒过来,这就变得很明显了。 (int)(random_float() * 10)将返回0到9之间的一个值,每个值的机会相等。如果在十亿次中有一次返回1,那么很少会返回10。
有些人会在事后修复它(决定10应该是9)。将其乘以2应该给出约50%的0或1的机会,但也会像Bender's dream中那样有约0.000000000465%的机会返回2。
说0到1的浮点数可能有点像错误地说0到10而不是从零开始的9个整数,当你想要十个值时。在这种情况下,由于可能的浮点值范围很广,所以更像是意外地说0到1000000000而不是0到999999999。
使用64位时,溢出非常罕见,但在这种情况下,一些随机函数在内部是32位的,因此发生那2.5亿分之一的机会并不是不可能的。
标准解决方案应该像这样:
mt_rand() / (getrandmax() + 1)

有时候分布会有微小的差异,通常是在0到9之间,由于精度问题,0可能比9稍微更容易出现。但这通常只存在于十亿分之一左右,不像上述问题那么严重,因为上述问题可能会导致计算结果超出范围从而无效。

Java的Math.random也永远不会产生值为1的情况。这部分原因在于解释它具体做什么很麻烦。它返回0到小于1的值。这就像是Zeno的箭,它永远不会到达1。这不是人们通常会说的东西。相反,人们倾向于说从0到1之间或者0到1之间,但这些都是错误的。

这在错误报告中有点好笑。例如,使用lcg_value的任何PHP代码如果没有考虑到这一点,可能会在大约20亿次中出现一次故障,如果它符合其文档说明,但这使得忠实地重现变得异常困难。

这种偏移一个错误是嵌入式设备中通常遇到的“只需关闭并重新打开”问题的常见来源之一。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接