微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

php – 为什么这个随机字符串生成器表现如此糟糕?

我发现这段PHP代码用于生成随机字符串(字母,字母数字,数字和十六进制).

<?PHP
function random($length = 8, $seeds = 'alpha') {
  // Possible seeds
  $seedings['alpha'] = 'abcdefghijklmnopqrstuvwqyz';
  $seedings['numeric'] = '0123456789';
  $seedings['alphanum'] = 'abcdefghijklmnopqrstuvwqyz0123456789';
  $seedings['hexidec'] = '0123456789abcdef';

  // Choose seed
  if (isset($seedings[$seeds])) {
    $seeds = $seedings[$seeds];
  }

  // Seed generator
  list($usec, $sec) = explode(' ', microtime());
  $seed = (float) $sec + ((float) $usec * 100000);
  mt_srand($seed);

  // Generate
  $str = '';
  $seeds_count = strlen($seeds);

  for ($i = 0; $length > $i; $i++) {
    $str .= $seeds{mt_rand(0, $seeds_count - 1)};
  }

  return $str;
}
?>

如果我使用认参数运行此函数(因此它生成8个字符串,仅按字母顺序排列)并生成1,000,000个字符串,我认为我的碰撞率会很低:

26^8 = 208,827,064,576
1,000,000 / 208,827,064,576 ~= 0.0004%

实际上,当我在我的机器上运行时,我得到90%的碰撞率!我生成的字符串中只有10%是唯一的.

实际上,它接近10%.生成多组1,000,000个随机字符串,我发现每个集合生成

> 100,032个独特的字符串
> 100,035个独特的字符串
> 100,032个独特的字符串
> 100,028个独特字符串
> 100,030个独特的字符串
>你明白了……

什么给出了什么?显然它与我如何播种mt_srand,或PHP如何实现mt_rand或其他东西有关.

所以…

为什么这段代码不能生成有用的随机字符串?

什么是更好的方法

解决方法:

除非您知道自己在做什么,否则请不要设置种子:

Note: There is no need to seed the random number generator with
srand() or mt_srand() as this is done automatically.

以下代码几乎获得了一组100%唯一字符串

<?PHP
  function random($length = 8, $charset = 'alpha'){
    $list = [
      'alpha' => 'abcdefghijklmnopqrstuvwqyz',
      'numeric' => '0123456789',
      'alphanum' => 'abcdefghijklmnopqrstuvwqyz0123456789',
      'hexidec' => '0123456789abcdef'
    ];

    if(!isset($list[$charset])){
      trigger_error("Invalid charset '$charset', allowed sets: '".implode(', ', array_keys($list))."'", E_USER_NOTICE);
      $charset = 'alpha';
    }

    $str   = '';
    $max   = strlen($list[$charset]) - 1;

    for ($i = 0; $length > $i; $i++) {
      $str .= $list[$charset][mt_rand(0, $max)];
    }

    return $str;
  }

  $loop = 1000000;

  for($i=0;$i<$loop;$i++){
    $arr[random()] = true;
  }

  echo $loop - count($arr), " dupes found in list.";
?>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐