Генерация 0 и 1, псевдослучайная строка длиной 16 символов

Мне нужно сгенерировать строку длиной 16 символов (из хэша SHA1), которая содержит только 0 и 1, с вероятностью 50% (статистически в большинстве случаев такое же количество 1 в строке равно количеству 0).

Поэтому я написал тест и попытался преобразовать каждый символ $ hash в двоичный файл.
Результаты плохие, я имею в виду, если я добавляю ведущие нули в двоичный преобразованный хэш, правильная вероятность далека от правильной.
Когда я не добавляю начальные нули в двоичное преобразование, вероятность близка к правильной:

Percentage all 0 or all 1: 0.0012%
Percentage all 0 or all 1 except 1 character : 0.0146%
Percentage all 0 or all 1 except 2 characters: 0.0812%

Но это все еще далеко от истинно правильной вероятности того, что код, приведенный ниже, должен произвести что:

Percentage all 0 or all 1: 0.003%
Percentage all 0 or all 1 except 1 character : 0.048%
Percentage all 0 or all 1 except 2 characters: 0.376%

Как я узнаю его правильную вероятность? Я менял двоичное преобразование на простое mt_rand (0,1) шестнадцать раз (и другие подтверждающие тесты).

Он должен быть сгенерирован из хэша sha1, чтобы быть детерминированным по этому хешу.
У кого-нибудь есть идея, как исправить мой код, чтобы получить правильные результаты вероятности? Я пробовал уже 10 часов подряд.

    function binary($text){
$list = '';
$temp = '';
$i = 0;
while ($i < 16){
if (is_numeric($text[$i])){
$list .= decbin( $text[$i] );//sprintf( "%08d", decbin( $text[$i] ));
} else {
$temp = ord($text[$i]);
$list .= decbin( $temp );
//                      $list .= sprintf( "%08d", decbin( $temp ));// substr("00000000",0,8 - strlen($temp)) . $temp;
}
$i++;
}
return $list;
}

$y = 0;
$trafien = 0;
$trafien1= 0;
$trafien2= 0;
$max = 500000;
while ($y < $max){

$time = uniqid()  . mt_rand(1,999999999999);
$seed = 'eqm2890rmn9ou8nr9q2';
$hash = sha1($time . $seed);

$last4 = substr($hash, 0, 40);
$binary =  binary($last4);
$final = substr($binary, 0,16);

$ile = substr_count($final, '0');
$ile2= substr_count($final, '1');
if ($ile == 16 || $ile2 == 16){
echo "\n".$last4 ." " . 'binary: '. $binary .' final: '. $final;
$trafien += 1;
}

if ($ile == 15 || $ile2 == 15){
$trafien1 += 1;
}

if ($ile == 14 || $ile2 == 14){
$trafien2 += 1;
}

$y++;
}

$procent = ($trafien * 100)  / $max;
$procent1= ($trafien1 * 100) / $max;
$procent2= ($trafien2 * 100) / $max;
echo "\nPercentage all 0 or all 1: ". $procent . "%";
echo "\nPercentage all 0 or all 1 except 1 character : ". $procent1 . "%";
echo "\nPercentage all 0 or all 1 except 2 characters: ". $procent2 . "%";

0

Решение

Я думаю, я не понимаю, почему вам нужно заново изобретать колесо или использовать sha1 (), когда вы используете только 4 символа и конвертируете в двоичный файл. Кажется, это работает нормально:

$n = null;
for ($i=1; $i<=16; $i++) {
$n .= mt_rand(0,1);
}

Вот эталонный скрипт, который я написал:

// $app for number of appearances
$app[0] = 0;
$app[1] = 0;
$sample = 10000;

for ($t=1; $t<=$sample; $t++) {

$n = null;
for ($i=1; $i<=16; $i++) {
$n .= mt_rand(0,1);
}

$app[0] += substr_count($n, 0);
$app[1] += substr_count($n, 1);
}

print_r($app);
echo "Probability of 0: ".($app[0] / ($sample * 16))."\n";
echo "Probability of 1: ".($app[1] / ($sample * 16))."\n";

Выход с размером выборки 10000:

Array
(
[0] => 80079
[1] => 79921
)
Probability of 0: 0.50049375
Probability of 1: 0.49950625

Выход с размером выборки 100000:

Array
(
[0] => 799390
[1] => 800610
)
Probability of 0: 0.49961875
Probability of 1: 0.50038125
0

Другие решения

Хорошо, я решил это, я переутомился из-за недостатка знаний. Вы можете использовать прямой необработанный двоичный вывод функции sha1 sha1 (data, true). Тогда у вас есть истинная детерминистическая случайность 0/1 🙂

0

По вопросам рекламы [email protected]