У меня есть PHP-скрипт, который должен рандомизировать массив с согласованными результатами, чтобы он мог представить первые несколько элементов пользователю, и затем они могут извлечь больше результатов из того же перетасованного набора, если захотят.
То, что я сейчас использую, – это (на основе алгоритма Fisher Yates, который я считаю):
function shuffle(&$array, $seed) { mt_srand($seed); for ($a=count($array)-1; $a>0; $a--) { $b = mt_rand(0, $a); $temp = $array[$a]; $array[$a] = $array[$b]; $array[$b] = $temp; } }
Это отлично работает на моей локальной установке, но на сервере, на котором он должен работать, установлен Suhosin, который переопределяет mt_srand, то есть семя игнорируется, массив просто случайно перетасовывается, и пользователь получает дубликаты результатов.
Все, что я нашел в Google, предполагает, что мне нужно отключить suhosin.mt_srand.ignore (и suhosin.srand.ignore, не уверен, что последнее актуально), поэтому я поставил следующее в .htaccess:
php_flag suhosin.mt_srand.ignore Off php_flag suhosin.srand.ignore Off
У меня нет доступа к php.ini на этом сервере, поэтому AFAIK это единственный способ сделать это. Проблема в том, что эффект не имеет – phpinfo () все еще показывает обе настройки как On, тогда как я могу изменить другие настройки Suhosin, используя .htaccess, без проблем.
Поэтому я полагаю, что то, что я ищу, – это либо способ отключить suhosin.mt_srand.ignore (или причину, по которой он не работает), либо обходной путь для генерации генератора случайных чисел из PHP. Или мне просто нужно реализовать еще один RNG?
Любая помощь приветствуется. Благодаря!
Используя некоторые основные математики и несколько трюков, вы можете легко создать свою СОБСТВЕННУЮ случайную функцию, как я только что сделал 🙂
Извините, я не очистил его. Было бы намного лучше в классе, так как вы могли бы предотвратить необходимость повторного посева его с предыдущим семенем. Не используйте статическую переменную, поскольку она ограничивает вас использованием только одного семени за раз (или вручную отслеживания семян самостоятельно). ООП решит это. Сделайте то, что вам нравится, с помощью функции ниже, но дайте мне знать, если вы перепишете ее.
/** * returns a decimal between 0 and max_number, requires seeding every time and will ALWAYS return the same decimal for the same seed * @copyright scott thompson, all rights reserved * @license MIT (do what you like with this) * @param string $seed * @param int $max_number=100 adjust the maximum number range */ function random_number($seed, $max_number = 100) { //make sure there won't be any deadspace where random numbers will never fill if ($max_number > 0xFFFFFF) { trigger_error("Max random number was to high. Maximum number of " . 0xFFFFFF . " allowed. Defaulting to maximum number.", E_USER_WARNING); $max_number = 0xFFFFFF; } //hash the seed to ensure enough random(ish) characters each time $hash = sha1($seed); //use the first x characters, and convert from hex to base 10 (this is where the random number is obtain) $rand = base_convert(substr($hash, 0, 6), 16, 10); //as a decimal percentage (ensures between 0 and max number) return $rand / 0xFFFFFF * $max_number ; } $seed = 'hello'; print ($seed = random_number($seed)) . '<br />'; //66.779748605475 print ($seed = random_number($seed)) . '<br />'; //3.5753311857779 print ($seed = random_number($seed)) . '<br />'; //13.994396567011 print ($seed = random_number($seed)) . '<br />'; //70.344917198713 print ($seed = random_number($seed)) . '<br />'; //4.5583250855401
Надеюсь, это поможет, Скотт