首页 > 解决方案 > 创建随机数并确保它是唯一的

问题描述

在我的系统中,每个客户都有自己的文件夹,其名称由 rand() 函数生成。

我想确保 $random 变量的值始终保持唯一。我创建了下面的代码,它应该:

  1. 生成随机数
  2. 检查具有唯一值的文件夹是否存在
  3. 如果存在生成新号码
  4. 如果不存在具有随机值名称的 mkdir

但我不确定它是否正常工作并且是执行上述步骤的有效方式。

$random = rand(pow(10, 3-1), pow(10, 3)-1);
$path_validator = 'build/'.$random;
if(is_dir($path_validator)) {
    $random = rand(pow(10, 3-1), pow(10, 3)-1);
}
else
{
   mkdir('build/crm/'.$random, 0777);
}

$random必须是随机的 3 位数字

标签: php

解决方案


预选赛

1)因为您已经在检查该值是否存在,所以就其比较器而言,它的唯一性并不重要。

2)因为你只想要一个“3位”数字,所以只有1000种可能性,这使得对唯一值的请求在事物的计算规模上毫无意义。

答案

因此您可以简单地使用mt_rand,因为:

许多旧 libcs​​ 的随机数生成器具有可疑或未知的特性并且速度很慢。mt_rand() 函数是旧 rand() 的直接替代品。它使用具有已知特性的随机数生成器,使用 » Mersenne Twister,生成随机数的速度比 libc rand() 提供的平均速度快四倍。

因为您正在寻找一组数字,您可以在mt_rand函数调用中简单地设置这个范围。

因此:

代码

// Below lines are only to show the parts to generate $random var. 
// $random = mt_rand(0,999); //generate random number between 0 and 999
// $random = sprintf('%03d', $random); //forces value to 3-digits. ie: 005
//
// Real code begins here:
do {
    $random = sprintf('%03d',mt_rand(000,999));
    $path_validator = 'build/'.$random;
    clearstatcache(); // the directory checker result is cached.
}
while(is_dir($path_validator) || !mkdir('build/crm/'.$random, 0777));

(另见sprinf

笔记:

  • 范围很小——1000 次迭代是微不足道的。平方这个数字。
  • 0777制作具有特权的文件夹时要格外小心。
  • 非常小心文件夹竞争条件,PHP 可以检查文件夹是否存在,然后在它被并行* PHP 进程(例如另一个实例)创建之前发现它不存在。
  • 检查文件夹是否存在时,请小心使用 PHP缓存结果
  • 虽然mt_rand随机性更大rand,但两个用户都将生成相同的 3 位数值的可能性仍然相对较高。被警告!!

推荐阅读