3

我正在使用随机数填充一个数组$blockhash[$i] = rand().time().rand()

然后,对于该数组中的每个随机数,我计算对应的 SHA512

$SecretKey = "60674ccb549f1988439774adb82ff187e63a2dfd403a0dee852e4e4eab75a0b3";
$sha = hash_hmac('sha512', $value, $SecretKey);

拆分它:

$pool  = str_split($sha, 2);

然后我从 $pool 数组中获取第一个数字,将 hex 转换为 dec 并将其限制在 1 和 50 内:

$dec = hexdec($pool[0]) % 50 + 1;

问题是这些数字不是那么随机,我不知道为什么。我从 1 到 50 计算每个数字的频率,但数字 1、2、3、4、5 和 6 比其他数字出现的频率更高。见图表

在此处输入图像描述

为什么会发生这种情况以及如何解决?谢谢!

4

3 回答 3

4

您要转换为十进制的 2 个十六进制字符将在 0-255 的范围内。您将其修改为 50 并添加 1,使 1-6(范围(0-5)+1)在 1-256 上出现 6 次,而其他每个数字仅出现 5 次。这将导致这些数字增加约 20%。

于 2013-04-03T17:46:32.240 回答
2

你得到 1-6 的频率更高,因为你从哈希中获取了两个十六进制数字。那是一个字节,所以它可以存储从0to 的值255。然后你使用模数50。结果你得到范围0-49, 50-99, 100-149, 150-199, 200-249and... 250-255。最后一个是导致结果中 1-6 的额外流行的原因。

解决方案:只需使用mt_rand(1,50);

[编辑]

如果您确实需要将数字从 0-255 范围转换为 1-50 范围,则解决方案将是缩放和舍入。

$number = round(($byteValue)/(255/49))+1; 
于 2013-04-03T17:50:05.567 回答
1

既不也不rand()生成mt_rand()真正的随机值。

如手册所述:

此函数不会生成加密安全值,并且不应用于加密目的。如果您需要加密安全值,请考虑openssl_random_pseudo_bytes()改用。

请参阅更好的随机生成 PHP以获得指向相同问题并有一些好的答案的 StackOverflow 问题。

于 2013-04-03T17:42:11.150 回答