我对生成随机字符的两种算法感到困惑。我有四种字符类型,小写,大写,数字和特殊字符。根据请求的随机字符的类型,它应该产生字符。例如:
- 如果请求的是纯小写、大写、数字或特殊字符,则应仅从每种类型中随机选择该值。
- 如果请求的是小写和数字,则应从这两种类型的混合字符串中选择。
- ETC
我对混合字符类型采用的算法如下:
- 从每种类型中选择具有所需字符长度的随机字符串。
- 连接这些字符串,然后从新字符串中再次选择随机字符。
我认为该算法确保了样本空间中每种类型可用的概率相等。但是,在某些情况下,混合类型的结果字符串可能没有字符串中显示的任何一种类型,并且在某些许多情况下,我们可能会得到一些重复的字符。
还有另一种算法依赖于在选择随机字符串之前预先混合类型,但是,更可能出现一种类型的缺失,但减少了重复。
我需要知道是否有另一种算法可以在每种类型的呈现和减少重复之间提供平衡?
以下是实现我首先提到的算法的代码。它是 CakePHP 1.2.x 组件,可以在这里找到一个工作示例:
<?php
class RandomStringComponent extends Object{
var $name = 'RandomString';
var $lowerCase = 'qwertyuiopasdfghjklzxcvbnm';
var $upperCase = 'ASDFGHJKLQWERTYUIOPZXCVBNM';
var $numbers = '9874563210';
var $specialChars = '!@#$%)-+/}[<>~=,;:|`{.?]^&*(';
var $outputForm = 'LcUcNuSp';
var $settings = array();
var $controller = null;
var $_defaults = array(
'outputForm' => 'LcUcNuSp',
'length' => 6
);
function initialize(&$controller, $settings){
$this->settings = array_merge($this->_defaults, $settings);
}
function getRand($l = null){
if (is_null($l)) $l = $this->settings['length'];
switch ($this->settings['outputForm']){
case 'Lc':
return $this->_Lc($l);
break;
case 'Uc':
return $this->_Uc($l);
break;
case 'Sp':
return $this->_Sp($l);
break;
case 'Nu':
return $this->_Nu($l);
break;
case 'LcUc':
return $this->_setRand($this->_Lc($l).$this->_Uc($l),$l);
break;
case 'LcNu':
return $this->_setRand($this->_Lc($l).$this->_Nu($l),$l);
break;
case 'UcNu':
return $this->_setRand($this->_Uc($l).$this->_Nu($l),$l);
break;
case 'LcUcNu':
return $this->_setRand($this->_Lc($l).$this->_Uc($l).$this->_Nu($l),$l);
break;
default:
return $this->_setRand($this->_Lc($l).$this->_Uc($l).$this->_Nu($l).$this->_Sp($l),$l);
break;
}
}
function _Lc($l){
$output = '';
for ($i = 0; $i < $l; $i++){
$output .= $this->lowerCase[mt_rand(0, strlen($this->lowerCase)-1)];
}
return $output;
}
function _Uc($l){
$output = '';
for ($i = 0; $i < $l; $i++){
$output .= $this->upperCase[mt_rand(0, strlen($this->upperCase)-1)];
}
return $output;
}
function _Sp($l){
$output = '';
for ($i = 0; $i < $l; $i++){
$output .= $this->specialChars[mt_rand(0, strlen($this->specialChars)-1)];
}
return $output;
}
function _Nu($l){
$output = '';
for ($i = 0; $i < $l; $i++){
$output .= $this->numbers[mt_rand(0, strlen($this->numbers)-1)];
}
return $output;
}
function _setRand($str, $l){
$output = '';
for ($i = 0; $i < $l; $i++){
$output .= $str[mt_rand(0, strlen($str)-1)];
}
return $output;
}
}
?>