php - PHP伪随机有多随机,4个字节

标签 php hash cryptography crc32

我一直在测试 PHP 中生成值的随机性,并一直在考虑用 32 位十六进制表示给定时间范围内的唯一状态。

我写了这个简单的测试脚本:

$checks = [];
$i = 0;

while (true) {
    $hash = hash('crc32b', openssl_random_pseudo_bytes(4));

    echo $hash . PHP_EOL;

    if (in_array($hash, $checks)) {
        echo 'Copy: ' . $i . PHP_EOL;
        break;
    }

    $i++;

    $checks[] = $hash;
}

令我惊讶的是(对我来说)这个脚本在不到 100,000 次迭代中生成了一个副本,并且低至 1000 次迭代。

我的问题是,我在这里做错了吗?在 40 亿种可能性中,这种频率水平似乎不太可能。

最佳答案

不,这并不奇怪,随机数生成器没有任何问题。这是 birthday problem .一个房间里只有 23 个人,其中两人生日相同的概率为 50%。这可能是违反直觉的,直到您意识到 23 个人有 253 种可能的配对,所以您可以对生日相同的两个人进行 253 次拍摄。

你在这里做同样的事情。您不希望看到何时达到特定的 32 位值。相反,您正在寻找迄今为止创建的任意两个值之间的匹配项,这为您提供了更多机会。如果您考虑第 100,000 步,您有 43,000 分之一的机会匹配您目前创建的一个数字,而不是 4,300,000,000 分之一的机会匹配特定数字。在达到 100,000 的过程中,您已经积累了很多这样的机会。

参见 this answer here on stackoverflow用于计算 32 位值。平均而言,您只需要大约 93,000 个值即可获得成功。

顺便说一句,在四字节随机值上使用 CRC-32 与此处无关。不管有没有它,结果都是一样的。您所做的只是将每个 32 位数字唯一地(一对一地)映射到另一个 32 位数字。

关于php - PHP伪随机有多随机,4个字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29990118/

相关文章:

php - MySQL查询从多个表中选择,显示全部来自table1 +来自table2的一些数据

ruby - 如何使用新的哈希语法?

c# - 如何改进短字符串的散列以避免冲突?

java - JDK 中的加密提供者

hash - 如何从sha512消化物中提取盐?

php - Mysql 对具有不同值的表进行分组

php - 是否使用 PHP 框架?

php - MySQL- 无法跳转到 MySQL 结果索引的第 0 行

c++ - 在 C++ 中散列原始字节?

ssl - 在一次握手消息中发送 `Encrypted Extension` 和 `Server Finished`。 TLS1.3 中是否强制?