2012-02-28 29 views
4

我有一个PHP脚本,它需要随机化一个具有一致结果的数组,因此它可以向用户呈现前几个项目,然后他们可以从相同的洗牌集合中提取更多结果(如果他们愿意的话)。suhosin.mt_srand.ignore在PHP中一致地洗牌数组的方法?

我目前使用的是什么(基于费舍尔耶茨算法我相信):

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,意味着种子被忽略,数组只是随机洗牌并且用户获得重复的结果。

的一切,我在谷歌发现表明我需要禁用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,而我可以使用.htaccess更改其他Suhosin设置没有问题。

所以我想我正在寻找的是要么真正禁用suhosin.mt_srand.ignore(或其原因为什么它不工作),或从PHP内种子随机数发生器的解决方法。或者我只需要自己实施另一个RNG?

任何帮助将不胜感激。谢谢!

+0

缓存结果数组的地方,不重新创建它的每一个请求...... – KingCrunch 2012-02-28 13:05:43

+0

好像那将会引入很多问题的东西,应该是相当简单的,虽然。就其性质而言,它需要重新洗牌(它基于搜索,每次用户搜索它重新洗牌),每个洗牌可能最多只能使用2到3次。它是网站中一个被大量使用的部分,所以我会为不同的用户缓存很多不同结果数组的不同混合版本,可能在很多情况下,同样的结果会以不同的方式改变,然后我需要处理存储以及保留每个阵列的时间和所有这些。 – alexz 2012-02-28 14:48:10

+0

这真的是一个需求,_every_用户_必须看到_completely_不同的版本,或者不能为多个用户使用一个洗牌集? – KingCrunch 2012-02-28 18:38:18

回答

2

使用一些基本的数学和一些技巧,你可以很容易地创建自己的随机函数,就像我刚才做:)

对不起,我没有清理了。在课堂上,这样会好得多,因为你可以避免与前一个种子重新播种。不要使用静态变量,因为它限制您一次只使用1个种子(或者手动自行跟踪种子)。 OOP会解决这个问题。按照下面的功能做你喜欢的事情,但是如果你改写它,请告诉我。

/** 
* 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 

希望这会有所帮助,

+0

谢谢,但必须承认,这是我的第二种方法><第一次我尝试使用散列中每个字符的ord()值,但是这给了我只有0.5和0.6之间的数字,我没有看到来!所以最后采取了一种不同的方法,通过剔除哈希的前面,这恰好是一个十六进制值......它工作并且实际上比我原本想象的要好。 – VBAssassin 2012-10-26 00:22:13