Я проверял случайность сгенерированных значений в 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 итераций.
У меня вопрос, я что-то здесь не так делаю? Из 4 миллиардов возможностей этот уровень частоты кажется слишком маловероятным.
Нет, это не удивительно, и в генераторе случайных чисел нет ничего плохого. Это проблема дня рождения. Если в комнате всего 23 человека, вероятность того, что двое из них имеют одинаковый день рождения, составляет 50%. Это, возможно, нелогично, пока вы не поймете, что существует 253 возможных пары из 23 человек, поэтому вы получите 253 снимка для двух человек с одинаковым днем рождения.
Вы делаете то же самое здесь. Вы не хотите видеть, когда вы достигаете определенного 32-битного значения. Вместо этого вы ищете совпадение между любыми двумя значениями, которые вы создали до сих пор, что дает вам гораздо больше шансов. Если вы рассмотрите шаг 100 000, у вас есть шанс 1 из 43 000 совпадений с одним из созданных вами чисел, а не 1 из 4 300 000 000 совпадений с определенным числом. В беге до 100 000, вы добавили много этих шансов.
Увидеть этот ответ здесь на stackoverflow для расчета 32-битного значения. В среднем вам нужно всего лишь около 93 000 значений, чтобы получить хит.
Кстати, использование CRC-32 на четырехбайтовом случайном значении здесь не имеет никакого отношения. Результат будет таким же с или без него. Все, что вы делаете, это однозначно сопоставляете каждое 32-разрядное число (один-к-одному и на) с другим 32-разрядным числом.
Других решений пока нет …