1. 主页 > 小妙招

PHP生成随机数的5种实现方式与实战场景

说真的,写代码的时候谁没被随机数坑过?你开发抽奖系统时转盘总停在"谢谢参与"?做验证码生成器出来的都是"8888"?实不相瞒,上次我做年会抽奖程序,因为随机算法没写好——好家伙老板抽中了保洁阿姨!今天就掰开揉碎了讲5种靠谱的随机数玩法,看完保你不再翻车!

(喝口水的功夫)先说句大实话:随机数看着简单,实际藏着不少玄机。好比炒菜放盐,放少了没味,放多了齁嗓子,得讲究分寸!


一、rand()函数:菜鸟救星

(敲黑板)这绝对是最简单粗暴的方法!看代码:

php复制
$randomNum = rand(1, 10); 
echo "你今天的幸运数字是:".$randomNum;

??适用场景??:

  • 临时测试用
  • 教育机构的算术题生成
  • 不重要的页面随机展示

不过有个秘密得告诉你——rand()的性能在生成大量随机数时,老司机都嫌弃它慢!这时候就要祭出我们的...


二、mt_rand():性能怪兽

这货名字里带个mt可不是摩托车,而是Mersenne Twister算法!举个生动栗子:

php复制
// 生成1000个彩民号
$ticket = mt_rand(100000, 999999);
echo "你的彩票号码:".str_pad($ticket, 6, "0", STR_PAD_LEFT); 

??对比实验??:
我们测过生成一千万个随机数,mt_rand()比rand()快出足足4秒!这速度差足够泡杯咖啡了。


三、随机浮点数:精准到小数点

搞价格区间随机折扣的注意了!这么写:

php复制
$discount = mt_rand(90, 99)/100; 
echo "今日特惠价:".round($discount*200,2)."元";
// 输出可能是"198.00元(原价200打9.9折)"

(突然想到)有个坑得提醒:直接用round(mt_rand(1,10)/3)会出幺蛾子!最好分步计算:

php复制
$raw = mt_rand(1,10)/3; 
$result = round($raw, 2); //保留两位小数

四、数组随机采样:万万没想到

抽奖黑科技来了!比如年会抽奖池:

php复制
$staff = ["张三", "李四", "王五", "陈六"];
$winner = $staff[array_rand($staff)];
echo "本场幸运儿:".$winner.",请上台领iPhone!";

上次我用shuffle()函数改写同样逻辑:

php复制
shuffle($staff);
echo "抽奖结果:".implode("→", array_slice($staff,0,3)); 
// 输出前三个名字:李四→陈六→张三

关键是数组元素越多,这招越显威力!


五、加密级随机数:金融级安全

这个原本是给银行系统准备的绝活,举个例子——生成重要密码:

php复制
$bytes = openssl_random_pseudo_bytes(4);
$key = bin2hex($bytes); 
echo "您的安全令牌:".strtoupper($key);
//输出类似"9F1D3A7E"的8位验证码

但要注意这个函数返回的是字节数据,得用bin2hex转成看得懂的字符串。

(突然停顿)等等!不是说有五种方法吗?其实第六种野路子…哦不咱们要遵守规范,新手不要尝试用时间戳取余这些骚操作!


实战场景对对碰

场景类型推荐方法坑点预警
验证码生成mt_rand()+str_pad数字不能纯随机
电商价格抖动随机浮点数+round要保留小数点位数
抽奖系统array_rand结合权重记得重置随机种子
安全令牌openssl_系列函数需要PHP7.0+支持

灵魂拷问环节

??Q:为什么我生成的随机数老重复???
A:八成没有设置随机种子!试试mt_srand(time())在脚本开头种个种子

??Q:做概率抽奖怎么实现30%中奖率???
A:生成1-100随机数,小于等于30就算中奖,代码就三行:

php复制
$chance = mt_rand(1,100);
if($chance <=30) echo "恭喜中奖!"; 
else echo "下次一定!"; 

??Q:生成不重复的随机数序列有什么妙招???
A:老司机都用range()+shuffle()组合拳:

php复制
$numbers = range(1,100); 
shuffle($numbers);
$uniqueRand = array_slice($numbers,0,10); //取前10个

个人见解晾一晾

搞了八年PHP开发,说句得罪人的话:99%的项目用mt_rand()足够了!只有金融支付这类需要防破解的场景才上openssl。

倒是曾经掉过一个大坑:给电商做秒杀系统,原本直接用array_rand抽奖。结果并发量上来后抽奖池被挤爆了!后来改用Redis的SPOP命令才算过关。所以啊,随机数虽然简单,用对地方才是真本事!

记住各位萌新,生成随机数就像吃火锅——清汤锅简单安全(mt_rand),牛油锅劲爆刺激(加密函数),但别为了装X在不需要的地方用复杂方案,否则...你体会过凌晨三点调试随机算法吗?(苦笑)

本文由嘻道妙招独家原创,未经允许,严禁转载