一个有关PHP随机数的坑...

4 篇文章 0 订阅

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高四倍。。。好吧,看来研究旧有问题和学习新鲜知识一个都不能少。。。


### 回答1: Java中的随机数可以使用Math类中的random方法来生成。该方法返回一个到1之间的double类型的随机数,包括但不包括1。可以通过乘以一个范围值并加上一个起始值来生成指定范围内的随机数。例如,生成1到100之间的随机数可以使用以下代码: int randomNum = (int)(Math.random() * 100) + 1; 其中,Math.random()生成到1之间的随机数,乘以100后得到到100之间的随机数,再加1后得到1到100之间的随机数。最后将结果强制转换为int类型即可。 ### 回答2: Java中,我们可以使用Math.random()方法生成一个随机数。这个方法返回的是一个double类型的数字,它的范围是0.0到1.0之间。这个数字的随机性很高,因此可以使用它来生成各种类型的随机数。 比如,如果我们想要生成一个1到100之间的整数随机数,可以使用以下代码: int num = (int)(Math.random() * 100) + 1; 这里,我们先将Math.random()生成的小数乘以100,得到一个0到100之间的小数。然后再将它转化为一个整数,即可得到1到100之间的随机整数。 除了生成整数随机数,我们还可以使用Math.random()生成其他类型的随机数,比如生成一个随机的布尔值,生成一个随机的字符,生成一个随机的日期等等。只需要根据需要选择不同的方法和逻辑即可。 需要注意的是,Math.random()生成的随机数是伪随机数,它的随机性是通过算法来模拟实现的,也就是说存在一定的规律性。因此,在一些安全性要求高的场景下,建议使用其他更加随机的方式来生成随机数,比如SecureRandom类。 ### 回答3: Java中的 Math.random() 方法可以生成一个0到1之间的随机数,这个随机数一个双精度(double)类型。我们可以通过一些变换来获得我们需要的随机数。 生成10以内的随机数 要生成10以内的随机数可以将生成的随机数乘以10,然后取整。代码如下: int r = (int) (Math.random() * 10); System.out.println(r); 生成 10 以内的随机数,我们可以利用 Math.random() * 10 生成一个 0 - 10 之间的随机数,接着再强制类型转换成 int 类型,就得到了一个 0 - 9 之间的随机整数。 生成区间内的随机数 如果需要生成一定范围内的随机数,需要进行一定的数学操作。比如需要生成3到12之间的随机数,可以用如下代码实现: int r = (int) (Math.random() * (12 - 3 + 1)) + 3; System.out.println(r); 这里的关键是理解数学公式:Math.random() * (12 - 3 + 1) 的结果是在 0 - 10 之间的随机数,再加上 3,结果就是在 3 - 12 之间的随机整数。 生成指定个数的随机数 如果需要生成指定个数的随机数,可以使用循环自动地生成多个随机数。比如生成6个1~30之间的随机数,可以使用如下代码: for(int i = 0; i < 6; i++) { int r = (int) (Math.random() * 30) + 1; System.out.println(r); } 这段代码通过一个 for 循环,可以生成6个1~30之间的随机数,输出到控制台。 Math.random() 方法可以广泛应用于生成随机数的场合,可以通过数学操作等方式对随机数进行后处理得到我们需要的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值