find
允许的最低值是多少? 32位和64位机器的值是否相同?如何使用mt_rand()
生成32位整数(请注意,它不需要高度随机)?
背景为什么我要求:我有一个64位开发物理服务器和一个32位生产VPS。刚刚意识到生产服务器没有产生跨越整个范围的PK。为了弄清楚发生了什么,我运行了以下脚本。 64位机器永远不会(或者至少我没见过)匹配,但32位匹配大约50%的时间。
mt_rand()
输出
<?php
date_default_timezone_set('America/Los_Angeles');
ini_set('display_errors', 1);
error_reporting(E_ALL);
$count=0;
for ($i = 0; $i <= 10000; $i++) {
$rand=2147483648+mt_rand(-2147483647,2147483647); //Spans 1 to 4294967295 where 0 is reserved
if($rand==2147483649){$count++;}
}
echo('mt_getrandmax()='.mt_getrandmax().' count='.$count);
答案 0 :(得分:3)
TL; DR:要获得整个可能整数范围内的随机整数,请使用:
function random_integer() {
$min = defined('PHP_INT_MIN') ? PHP_INT_MIN : (-PHP_INT_MAX-1);
return mt_rand($min, -1) + mt_rand(0, PHP_INT_MAX);
}
对于PHP 7,您可以使用random_int()
。
$number = random_number_between_0_and_0x7FFFFFFF_using_Mersenne_Twister;
$number = $min + (($max - $min + 1.0) * ($number / (0x7FFFFFFF + 1.0)));
注意$max - $min
。当max设置为高端且min为负值时,会发生溢出。因此,最大范围为PHP_INT_MAX
。如果您的最大值为PHP_INT_MAX
,那么您的最低值必须为0
。
现在回顾一下。 PHP实现了32位Mersenne Twister算法。这给出了[0和2 ^ 31-1]之间的随机整数。如果您要求任何其他范围,PHP 使用简单的分箱功能缩放该数字。该分箱功能包括可导致溢出的减法,以及此问题。
因此,如果你想获得一个比PHP中的整数更大的范围,你必须一起添加间隔,如下所示:
mt_rand(PHP_INT_MIN, -1) + mt_rand(0, PHP_INT_MAX);
请注意,从PHP 7开始,PHP_INT_MIN
可用,因此您需要在此之前为您的环境计算合适的最小值。
另外,请注意2 ^ 31-1是getrandmax()
返回的内容。人们错误地认为在64位机器上getrandmax()
将返回2 ^ 63-1。那不是真的。 getrandmax()
返回算法将返回的最大整数,该值始终为2 ^ 31-1。
答案 1 :(得分:2)
您可以像这样生成32位整数:
$rand = unpack("l", openssl_random_pseudo_bytes(4));
答案 2 :(得分:1)
这是PHP文档中提到的问题
这在64位Linux上运行良好:
<?php printf ("%08x\n", mt_rand (0, 0xFFFFFFFF)); ?>
但是在我们的32位Linux开发服务器上,它始终会产生
00000000
。在同一台机器上,这个:
<?php printf ("%08x\n", mt_rand (0, 0xFFFFFFF0)); ?>
似乎总是产生
00000000
或fffffff2
到ffffffff
范围内的数字。这个:<?php printf ("%08x\n", mt_rand (0, 0xFFFFFF00)); ?>
给出最后两位数字变化的数字,依此类推至少
0xF0000000.
但是,这个:
<?php printf ("%08x\n", mt_rand (0, 0x7FFFFFFF)); ?>
工作正常
添加了错误报告here。
目前还没有人说PHP是否正在解决这个问题。
在此期间,您可以使用mt_rand
之间的max_rand
功能,您应该没问题
使用示例
$rand=mt_rand(1,2147483647)+mt_rand(0,2147483647);