Heim >Backend-Entwicklung >PHP-Tutorial >为什么PHP生成的随机数分布极不均匀?

为什么PHP生成的随机数分布极不均匀?

WBOY
WBOYOriginal
2016-06-06 20:48:071414Durchsuche

PHP生成随机数时,如果区间上限太大,生成出来的随机数都是非常大的数,这是为什么呢?

测试代码:

<code><?php for ($i = 0; $i < 10; $i++) {
        echo  mt_rand(0, PHP_INT_MAX), "\n";
}
</code></code>

结果:

<code>4821547998934728704
8090071897066176512
1549819806092361728
6955922199861526528
5792595325231300608
8322538479430926336
8261190596798971904
3595679043195764736
5711588226234318848
3693958636641452032
</code>

我运行了几十次这段代码,结果都是如此,产生的随机数都是10^17或者10^18这个量级的大数(64位系统上,PHP_INT_MAX是9223372036854775807,即9*10^18)

rand, mt_rand都是这样,每次mt_rand()生成随机数之前,执行mt_srand()也还是这样,PHP官方手册说了,自PHP 4.2起,已经不需要手工执行t_srand()了。

众所周知,计算机生成的随机数都不是真正的随机数,PHP官方也说了是伪随机数(pseudo-random ),但是,为什么会向PHP_INT_MAX倾斜得这么厉害?


问题补充:如果不加参数直接调mt_rand(),得到的随机数分布也很不均匀,小的(几百几千)和大(介于2^32和2^64之间)的都没有:

<code>1261931578
1210152279
777575697
198885548
1179641824
955196642
306582590
654301368
501653301
469521205
</code>

再补充,我希望得到的随机数组是这样的:

<code>Array
(
    [31] => 301487779840
    [57] => 10457165676412928
    [32] => 2516742
    [16] => 786840
    [39] => 2142457578485972992
    [81] => 16
    [27] => 5472146880987136
    [24] => 4979452
    [6] => 24912932785618944
    [48] => 930
    [82] => 9223372036854775807
)
</code>

很大的,很小的,都有。我已经有办法生成分布略均匀的随机数了,只是想请教一下大家,为什么PHP内置的随机数函数做不到这样。

附:我改良的mt_rand(0, PHP_INT_MAX)

<code><?php function randomBigNumber() {
        return mt_rand(0, 1 << mt_rand(1, 8 * PHP_INT_SIZE - 2));
}
</code></code>

--- 题外话 ---
@沙渺 在解答问题的同时说:

所以用这么几个破数据就说“不均匀”,这是对数学的极大蔑视。非常希望提问者下次能够尊重科学,拿出可以按统计学解读的论据,而不是只凭一些粗浅的直观感觉说事,以免再出现常识性的笑话。

讨论技术问题嘛,人人都有认识不深的领域,即使再熟练,也会有一时想不清楚的时候。我用PHP多年,也在本站解答了很多问题,碰到这个问题,表面看起来与我的预期不符,努力改进和思考了,也想不通,我就来请教了。

同时我自己也做了几十次的验证,使用了Google和StackOverFlow,也想了办法得到我想要的数字位数更加均衡的随机数,说明我也是做了一些努力的,不是一碰到超级低级的问题就上来发贴坐等答案,更没有拿着不成熟的结论上来喷【PHP引擎做得不够好】。

想起个小故事:

<code>- 三点水加个来读什么?
- 不知道。
- 还读lai呀!
- 这样啊,认字认半边
- 那三点水加个去读什么呢?
- 读qu!
- 读fa哦,亲
- (拍大腿)哎呀!是的!读fa!我认识的!!!
</code>

我想多数人都有过这样的经历吧,也许是在技术上,也许是在生活上。

所以,谢谢大家帮我解答问题,也请大家不要因为我这个问题太生气,我这个人水平确实不高,平时也很浮躁,在这个问题上对概率的认识是很粗浅。但这次发贴子,态度还是比较端正的,说“破问题”、“蔑视”就太夸张啦,对我而言,这是一个好问题,困扰我几天的问题,我也没有蔑视数学和PHP引擎的主观意愿和本事。

回复内容:

PHP生成随机数时,如果区间上限太大,生成出来的随机数都是非常大的数,这是为什么呢?

测试代码:

<code><?php for ($i = 0; $i < 10; $i++) {
        echo  mt_rand(0, PHP_INT_MAX), "\n";
}
</code></code>

结果:

<code>4821547998934728704
8090071897066176512
1549819806092361728
6955922199861526528
5792595325231300608
8322538479430926336
8261190596798971904
3595679043195764736
5711588226234318848
3693958636641452032
</code>

我运行了几十次这段代码,结果都是如此,产生的随机数都是10^17或者10^18这个量级的大数(64位系统上,PHP_INT_MAX是9223372036854775807,即9*10^18)

rand, mt_rand都是这样,每次mt_rand()生成随机数之前,执行mt_srand()也还是这样,PHP官方手册说了,自PHP 4.2起,已经不需要手工执行t_srand()了。

众所周知,计算机生成的随机数都不是真正的随机数,PHP官方也说了是伪随机数(pseudo-random ),但是,为什么会向PHP_INT_MAX倾斜得这么厉害?


问题补充:如果不加参数直接调mt_rand(),得到的随机数分布也很不均匀,小的(几百几千)和大(介于2^32和2^64之间)的都没有:

<code>1261931578
1210152279
777575697
198885548
1179641824
955196642
306582590
654301368
501653301
469521205
</code>

再补充,我希望得到的随机数组是这样的:

<code>Array
(
    [31] => 301487779840
    [57] => 10457165676412928
    [32] => 2516742
    [16] => 786840
    [39] => 2142457578485972992
    [81] => 16
    [27] => 5472146880987136
    [24] => 4979452
    [6] => 24912932785618944
    [48] => 930
    [82] => 9223372036854775807
)
</code>

很大的,很小的,都有。我已经有办法生成分布略均匀的随机数了,只是想请教一下大家,为什么PHP内置的随机数函数做不到这样。

附:我改良的mt_rand(0, PHP_INT_MAX)

<code><?php function randomBigNumber() {
        return mt_rand(0, 1 << mt_rand(1, 8 * PHP_INT_SIZE - 2));
}
</code></code>

--- 题外话 ---
@沙渺 在解答问题的同时说:

所以用这么几个破数据就说“不均匀”,这是对数学的极大蔑视。非常希望提问者下次能够尊重科学,拿出可以按统计学解读的论据,而不是只凭一些粗浅的直观感觉说事,以免再出现常识性的笑话。

讨论技术问题嘛,人人都有认识不深的领域,即使再熟练,也会有一时想不清楚的时候。我用PHP多年,也在本站解答了很多问题,碰到这个问题,表面看起来与我的预期不符,努力改进和思考了,也想不通,我就来请教了。

同时我自己也做了几十次的验证,使用了Google和StackOverFlow,也想了办法得到我想要的数字位数更加均衡的随机数,说明我也是做了一些努力的,不是一碰到超级低级的问题就上来发贴坐等答案,更没有拿着不成熟的结论上来喷【PHP引擎做得不够好】。

想起个小故事:

<code>- 三点水加个来读什么?
- 不知道。
- 还读lai呀!
- 这样啊,认字认半边
- 那三点水加个去读什么呢?
- 读qu!
- 读fa哦,亲
- (拍大腿)哎呀!是的!读fa!我认识的!!!
</code>

我想多数人都有过这样的经历吧,也许是在技术上,也许是在生活上。

所以,谢谢大家帮我解答问题,也请大家不要因为我这个问题太生气,我这个人水平确实不高,平时也很浮躁,在这个问题上对概率的认识是很粗浅。但这次发贴子,态度还是比较端正的,说“破问题”、“蔑视”就太夸张啦,对我而言,这是一个好问题,困扰我几天的问题,我也没有蔑视数学和PHP引擎的主观意愿和本事。

你的范围是19位的整数(大概是,不想深究了)。而你看到的“非常大”其实不过是“非常长”,占满了19位而已。

但所有(10^19-10^18) / 10^19 = 90%之多。

也就是说,如果要按照你所期待的那种“长短不一”的分布,只有概率向10%的一边严重倾斜才能做到。这反而是荒谬的。

统计,统计,只有数量非常大了才叫统计。要实际检验随机函数分布的均匀性,经验上要用10^7以上的数据量来跑,得出误差在5%之内都可以接受才行。

所以用这么几个破数据就说“不均匀”,这是对数学的极大蔑视。非常希望提问者下次能够尊重科学,拿出可以按统计学解读的论据,而不是只凭一些粗浅的直观感觉说事,以免再出现常识性的笑话。

第一,你的样本确实太小。 第二,程序中的随机数确实好像是伪随机数,随机到最后还是算法算出来的,无限趋向于随机数的伪随机数。

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn