Я заполняю массив случайными числами, используя $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 чаще появляются, чем другие. См. График
Почему это происходит и как это исправить? Благодаря!
Вы получаете 1-6 чаще, потому что вы получаете две шестнадцатеричные цифры из хэша. Это один байт, поэтому он может хранить значения от 0
до 255
. Затем вы используете modulo 50
. В результате вы получаете диапазоны 0-49
, 50-99
, 100-149
, 150-199
, 200-249
и … 250-255
. Этот последний отвечает за дополнительную распространенность 1-6 в ваших результатах.
Решение: просто используйте mt_rand(1,50);
[редактировать]
Если вам действительно нужно преобразовать число из диапазона 0-255 в диапазон 1-50, решение будет масштабироваться и округлять.
$number = round(($byteValue)/(255/49))+1;
два шестнадцатеричных символа, которые вы преобразуете в десятичный, будут находиться в диапазоне 0-255. вы измените это на 50 и добавьте 1, сделав 1-6 (диапазон (0-5) +1), 6 раз по 1-256, а каждый другой номер – всего 5 раз. Это приведет к увеличению на 20% роста этих цифр.
Ни rand()
ни mt_rand()
генерируют действительно случайные значения.
Как говорится в руководстве:
Эта функция не генерирует криптографически безопасные значения и не должна использоваться для криптографических целей. Если вам требуется криптографически безопасное значение,
openssl_random_pseudo_bytes()
вместо этого использоватьopenssl_random_pseudo_bytes()
.
См. Better Random Generating PHP для вопроса StackOverflow, который указывает ту же проблему и имеет некоторые хорошие ответы.