PHP shuffle函数使用的算法
php shuffle函数使用的算法是什么,或者在哪里可以获得它的代码。我必须用C语言实现它。我已经用C语言实现了fisher-yates算法,但并没有像php shuffle函数所显示的那样得到很好的结果。到底是什么构成了“不好的结果” Fisher-Yates洗牌将以相同的概率生成所有排列,但前提是正确生成随机数。这里有三个问题需要注意。首先,您需要一个好的伪随机数生成器。C标准库PHP shuffle函数使用的算法,php,Php,php shuffle函数使用的算法是什么,或者在哪里可以获得它的代码。我必须用C语言实现它。我已经用C语言实现了fisher-yates算法,但并没有像php shuffle函数所显示的那样得到很好的结果。到底是什么构成了“不好的结果” Fisher-Yates洗牌将以相同的概率生成所有排列,但前提是正确生成随机数。这里有三个问题需要注意。首先,您需要一个好的伪随机数生成器。C标准库rand通常不是一个好的PRNG(尽管它取决于您的C库实现)。如果您在POSIX平台上,请考虑使用 LRAND4
rand
通常不是一个好的PRNG(尽管它取决于您的C库实现)。如果您在POSIX平台上,请考虑使用<代码> LRAND48 < /代码>。您的系统可能有其他RNG。如果你在你的平台上没有任何东西,一个非常好的RNG在很小的代码中就是G.Marsaglias KISS generator——你可以找到代码。其次,如果您仍然决定使用rand
,请注意它将生成介于0和rand\u MAX
之间的随机数。对于许多实现,RAND_MAX
仅为32767,因此如果count
大于32768,通常的RAND()%count
将有一个非常明显且严重的偏差。第三,rand()%count
(或lrand48()%count
或任何类似的)实际上也是一个坏主意,因为它也引入了偏见。如果count
不是2的幂,则某些数字的概率将高于其他数字。此外,在许多生成器中,低阶位的随机性要比高阶位小得多。您可以尝试使用(long-long)rand()*count/rand_MAX
或类似的方法来解决这个问题,但实际上您最好使用一个好的RNG
生成0(包括)和k(排除)之间的无偏随机数的正确方法是:首先,获得一个适当的PRNG,该PRNG为您提供足够大的随机数(例如32个随机位)。然后降低到比k
大2的下一次幂。最后,如果该值大于或等于k
,请重试。这是一种完全无偏的方法,将给出尽可能好的PRNG结果。代码如下所示:
static unsigned int random(unsigned int k)
{
// You can get rid of this loop using bit tricks, but I keep it for clarity
unsigned int n, nextpow2 = 1;
while (nextpow2 < k)
nextpow2 *= 2;
do {
n = random32() & (nextpow2 - 1); // random32 is your 32-bit RNG
} while (n >= k);
return n;
}
static unsigned int random(unsigned int k)
{
//你可以使用一些小技巧来摆脱这个循环,但为了清晰起见,我保留了它
无符号整数n,nextpow2=1;
while(nextpow2=k);
返回n;
}
什么是“不好的结果”
Fisher-Yates洗牌将以相同的概率生成所有排列,但前提是正确生成随机数。这里有三个问题需要注意。首先,您需要一个好的伪随机数生成器。C标准库rand
通常不是一个好的PRNG(尽管它取决于您的C库实现)。如果您在POSIX平台上,请考虑使用<代码> LRAND48 < /代码>。您的系统可能有其他RNG。如果你在你的平台上没有任何东西,一个非常好的RNG在很小的代码中就是G.Marsaglias KISS generator——你可以找到代码。其次,如果您仍然决定使用rand
,请注意它将生成介于0和rand\u MAX
之间的随机数。对于许多实现,RAND_MAX
仅为32767,因此如果count
大于32768,通常的RAND()%count
将有一个非常明显且严重的偏差。第三,rand()%count
(或lrand48()%count
或任何类似的)实际上也是一个坏主意,因为它也引入了偏见。如果count
不是2的幂,则某些数字的概率将高于其他数字。此外,在许多生成器中,低阶位的随机性要比高阶位小得多。您可以尝试使用(long-long)rand()*count/rand_MAX
或类似的方法来解决这个问题,但实际上您最好使用一个好的RNG
生成0(包括)和k(排除)之间的无偏随机数的正确方法是:首先,获得一个适当的PRNG,该PRNG为您提供足够大的随机数(例如32个随机位)。然后降低到比k
大2的下一次幂。最后,如果该值大于或等于k
,请重试。这是一种完全无偏的方法,将给出尽可能好的PRNG结果。代码如下所示:
static unsigned int random(unsigned int k)
{
// You can get rid of this loop using bit tricks, but I keep it for clarity
unsigned int n, nextpow2 = 1;
while (nextpow2 < k)
nextpow2 *= 2;
do {
n = random32() & (nextpow2 - 1); // random32 is your 32-bit RNG
} while (n >= k);
return n;
}
static unsigned int random(unsigned int k)
{
//你可以使用一些小技巧来摆脱这个循环,但为了清晰起见,我保留了它
无符号整数n,nextpow2=1;
while(nextpow2=k);
返回n;
}