php中获取随机数的方法很简单,使用rand函数就可以了
int rand ( int $min , int $max )
一句调用就可以获得指定范围的随机数。但是大家都知道,计算机中使用的随机数实际是 伪随机数,一般来说,为了增加随机性,我们还会习惯在调用之前设置一下随机种子:
void srand ([ int $seed ] )
按照其他语言的习俗,会在 srand的参数里传递一个时间值,一般会传递当前时间的毫秒值或者微秒值进去。虽然从PHP4.2开始,调用rand的时候会自动调用srand,所以srand调用是一个并非必须的操作。
PHP中可以使用microtime()函数来获取随机数。于是,在一个一般性随机数需求场景下,我们就可以使用下述代码获取随机数了
<?php
srand(microtime());
echo rand(1, 25).PHP_EOL;
echo rand(1, 25).PHP_EOL;
?>
执行代码,我们得到了两个随机数。看似不错,但是再次执行,却发现得到的随机数和上次的一模一样。
这是啥状况?我们明明已经设置srand种子为当前时间的毫秒值了。
查阅文档,才发现其中的问题,原来在不带参数的情况下,mircotime函数会以"msec sec" 的格式返回一个空格分隔的字符串,经过自动类型转换,srand实际得到的参数值是0,在固定随机种子的情况下,会得到固定的随机序列,因此每次执行脚本都会得到相同的随机数。
从PHP5开始,microtime增加了一个$get_as_float
参数,通过传递true,可以让microtime返回一个当前毫秒的float值,由于返回值小数点之前是当前的秒值,因此对结果再乘以1000把小数点扩展到毫秒级别,这样就可以安全的获取随机数了:
<?php
srand(microtime(true) * 1000);
echo rand(1, 25).PHP_EOL;
echo rand(1, 25).PHP_EOL;
?>
连续访问两次,得到了不同的随机数,再写一个bash脚本:
for i in $(seq 1 1 100)
do
curl http://127.0.0.1/rnd.php
echo
done
连续跑100次,测试通过。
其实。。。
前例中的代码会报告一个
PHP Notice: A non well formed numeric value encountered
警告。但是如果脚本是跑在服务或者后台进程中,则可能不容易发现问题。
或者。。。
PHP中已经有了一个mt_rand()的函数用来替换古老的rand,可以自动播种并且效率比rand高四倍。。。好吧,看来研究旧有问题和学习新鲜知识一个都不能少。。。