PHP的mt_rand()最小值是多少,以及如何在32位Linux机器上计算32位整数 [英] What is PHP's mt_rand() minimum value and how to calculate 32 bit interger on 32 bit Linux box
问题描述
mt_rand()
允许的最小值是多少? 32位和64位计算机的值是否相同?
mt_rand()
生成32位整数(请注意,它不需要是高度随机的)?
为什么要问:我有一个64位开发物理服务器和一个32位生产VPS.刚意识到生产服务器没有生成涵盖整个范围的PK.为了弄清楚发生了什么,我运行了以下脚本. 64位计算机从未(或者至少我从未亲眼目睹)匹配,但是32位计算机大约有50%的时间匹配.
<?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);
输出
mt_getrandmax()=2147483647 count=5034
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()
./p>
$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_INT_MIN
自PHP 7起可用,因此您需要在此之前为您的环境计算一个合适的最小值.
顺便说一句,注意getrandmax()
返回的是2 ^ 31-1.人们错误地认为,在64位计算机上,getrandmax()
将返回2 ^ 63-1.这不是真的. getrandmax()
返回算法将返回的最大整数,该整数始终为2 ^ 31-1.
What is the minimum value allowed for mt_rand()
? Is it the same value for 32 bit and 64 bit machines? How could I generate a 32 bit integer using mt_rand()
(note that it doesn't need to be highly random)?
BACKGROUND WHY I AM ASKING: I have a 64 bit development physical server and a 32 bit production VPS. Just realized the production server was not generating PKs spanning the full range. To figure out what is going on, I ran the following script. The 64 bit machine never (or at least I've never witnessed) matches, but the 32 bit matches about 50% of the time.
<?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);
output
mt_getrandmax()=2147483647 count=5034
TL;DR: To get a random integer in the full range of possible integers, use:
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);
}
For PHP 7, you can use random_int()
.
Under the hood (1, 2), PHP is doing this:
$number = random_number_between_0_and_0x7FFFFFFF_using_Mersenne_Twister;
$number = $min + (($max - $min + 1.0) * ($number / (0x7FFFFFFF + 1.0)));
Notice $max - $min
. When max is set to the top end and min is anything negative, an overflow occurs. Therefore, the maximum range is PHP_INT_MAX
. If your maximum value is PHP_INT_MAX
, then your minimum is necessarily 0
.
Now for the back story. PHP implements the 32-bit Mersenne Twister algorithm. This gives us random integers between [0, and 2^31-1). If you ask for any other range, PHP scales that number using a simple binning function. That binning function includes a subtraction that can lead to overflow, and this problem.
Thus if you want to get a range larger than could be represented by an integer in PHP, you have to add intervals together, like so:
mt_rand(PHP_INT_MIN, -1) + mt_rand(0, PHP_INT_MAX);
Note that PHP_INT_MIN
is available since PHP 7, so you'll need to calculate a suitable minimum for your environment before then.
As an aside, notice that 2^31-1 is what getrandmax()
returns. People mistakenly believe that on a 64-bit machine getrandmax()
will return 2^63-1. That's not true. getrandmax()
returns the maximum integer the algorithm will return, which is always 2^31-1.
这篇关于PHP的mt_rand()最小值是多少,以及如何在32位Linux机器上计算32位整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!