随机字符串函数会产生许多重复项

时间:2014-07-03 07:45:05

标签: php windows random duplicates

我正在使用下面的函数为文件名生成随机字符串。我在Unix机器上没有遇到任何问题,但我在Windows上有很多重复。我刚做了一个测试并生成了100.000个字符串,结果是每个字符串出现227(??)次。有人能解释一下吗?即使使用rand()我也有重复项,但srand()似乎有效。

function generateRandomString($length = 6)
{
        $rows = array();
        array_push($rows, range('A', 'Z'));
        array_push($rows, range('a', 'z'));
        array_push($rows, range(0, 9));

        $signs = array();
        foreach ($rows as $row) {
            $signs = array_merge($signs, $row);
        }
        shuffle($signs);
        shuffle($signs);

        $password = '';
        for ($i = 0; $i < $length; $i++) {
            $password .= $signs[array_rand($signs, 1)];
        }
        return $password;
    }

1 个答案:

答案 0 :(得分:0)

嗯,首先,Windows文件名不区分大小写,因此您应该只在源数组中使用小写或大写字符,而不是两者都使用。

其余部分基本上取决于您正在使用的PHP处理器的实际实现,而不是Windows vs. * nix。也许它们依赖于定时器分辨率并且不保持内部状态 - 由于通常定时器分辨率大约为15ms,这并不是很糟糕。无论如何,它很可能是PHP实现的问题,而不是Windows本身,因为C#中的这段代码很好地说明了:

Random rnd = new Random();

byte[] buf = new byte[10 * 100000];

rnd.NextBytes(buf);

buf
   .Select((val, idx) => new { Index = idx, Value = val })
   .ToLookup(i => i.Index / 10)
   .Select(i => string.Join(string.Empty, 
                            i.Select(j => j.Value.ToString("X2")).ToArray()))
   .GroupBy(i => i)
   .Where(i => i.Count() > 1)
   .Dump();

这将创建10个20个字符(0F)的随机字符串,并查找重复项。在几百次测试中,我没有发生过一次碰撞。因此,如果您在PHP中使用随机生成器时遇到问题,请查看您正在使用的PHP的特定实现,而不是指责Windows :)

有趣的是,你的代码如何进行一些随机性传递(将$signs数组混洗两次,然后从中随机挑选?)。这样做最有可能减少数据的随机性,而不是增加它。似乎是一种愚蠢的尝试,隐藏密码生成机制背后隐藏的层次(然后开源......呃:D)。

至于密码(你的代码似乎表明它的用途是什么),你应该使用加密安全的randoms - 它们更不可预测,更随机,更不容易偏压。