大佬们,生成随机数这样加多个函数有意义吗

339 天前
 way2create

场景

单机的小项目,后台内部用,不需要开放,要求就是给数据生成一个 8 位纯数字的序列号,本身不需要包含什么含义,只要能通过序列号找到这个数据,不重复。 数据量也很小,可能一年都不会超过 1000 个,所以我在数据库设置了唯一索引后直接就用生成随机数的函数了,如下:

mt_rand(10000000,99999999);

但刚好我同事看到,说建议我改成:

str_shuffle(mt_rand(10000000,99999999));

说这样更好,更随机,重复的概率更低。 感觉不太对劲,我个人感觉这样不会更随机吧?但我对函数的底层的东西没什么深入研究。

我 google 了一下,但我可能搜索姿势不太对没找到完全相同的场景,但我看到有类似的代码,答案有提到说 str_shuffle 不会增加额外的熵。

是不是就是意思这样做不会增加随机性也不会让重复的概率变低?

所以发这个贴子来问问大家,谢谢!如果有相关的资料可以让我加深理解就更好了!

1964 次点击
所在节点    程序员
27 条回复
way2create
339 天前
@CodeCodeStudy 我的工作场景经常都是 mt_rand 就够了 你不提这个函数 用的少我都给忘了 你一提我去看了下才想起之前有用过相关的 random_bytes 与其说需要更好的 不如说我是很好奇他加个打乱函数是否真的有优化还是负优化
way2create
339 天前
@afeiche 谢谢 是我描述的不太清楚 有个要求是不要有规律的所以不能顺序 而且因为数量太小了 就如我说的可能一年都没 1000 个 其次这个是后台用的要求低一些 也做了错误处理了 不过肯定有非常多更好的方法 我只是结合场景图省事了
dode
339 天前
zhoushiyi
339 天前
mt_rand 取得值最终都是 10000000-99999999 区间的有序数字,只是先用那个数字的顺序不一样吧,是不是意味着记录数大于 99999999 条后,就不会再有随机数可用了,感觉 shuffule 应该起到了 0 开头的作用,随机数可用的范围多了,例如: 随机数 11223300 -> 00223311 rand 是不会产生 00223311 这样的随机数的
CodeCodeStudy
339 天前
https://github.com/php/php-src/blob/master/ext/standard/string.c#L5630

```c
PHPAPI bool php_binary_string_shuffle(const php_random_algo *algo, php_random_status *status, char *str, zend_long len) /* {{{ */
{
int64_t n_elems, rnd_idx, n_left;
char temp;

/* The implementation is stolen from array_data_shuffle */
/* Thus the characteristics of the randomization are the same */
n_elems = len;

if (n_elems <= 1) {
return true;
}

n_left = n_elems;

while (--n_left) {
rnd_idx = algo->range(status, 0, n_left);
if (EG(exception)) {
return false;
}
if (rnd_idx != n_left) {
temp = str[n_left];
str[n_left] = str[rnd_idx];
str[rnd_idx] = temp;
}
}

return true;
}
```

https://github.com/php/php-src/blob/master/ext/random/random.c#L423

```c

PHPAPI zend_long php_mt_rand_range(zend_long min, zend_long max)
{
return php_random_algo_mt19937.range(php_random_default_status(), min, max);
}

```


可以看出,都是调用某个算法的 range 函数,所以 str_shuffle 和 mt_rand 的底层都是相似的,差别可能就是算法不一样
way2create
339 天前
@CodeCodeStudy 说到这个 我看过源码早期版本的 rnd_idx = algo->range(status, 0, n_left);这行甚至直接就是调用的 php_rand() 而更旧版本的 php_rand() 好像还不如 php_mt_rand() 有些版本 php_rand 就等同于 php_mt_rand()了 但我不太懂 C
CodeCodeStudy
338 天前
@way2create #26 对,旧版本的一样的

https://www.php.net/manual/en/function.rand.php

As of PHP 7.1.0, rand() uses the same random number generator as mt_rand().

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1003355

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX