一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情。
随机数生成器
随机数生成器几乎在任何编程语言里都有,这东西能生成伪随机数。之所以是伪随机数, 是因为计算机本身是不能产生一个随机数的,所有的伪随机数都是使用某种数学理论而产生的,这种伪随机数有一个特点:就是可以重复。
这是什么意思?
- 首先随机数生成器需要设置一个种子(Seed),这个Seed一旦设定,那么后面产生的随机数,都已经被固定死了。重新运行程序,只要种子(Seed)一致,随机算法一致,那么后面的随机数就一致。
这一点看起来不好,但是我们有时候还真需要这种特性。请注意这个特性,下面要谈到。
随机数应用-对数组进行洗牌(Shuffle)
为什么要对数组进行洗牌?可能这个数组是你的播放列表,你想随机播放,此时就需要进行一次洗牌。
洗牌算法很简单,假设数组长度N:
- 第一步:内,找到一个随机数, 将下标与下标交换。
- 第二步:此时,我们忽略最后一个元素,将数组长度看成 N-1
- 然后进行第一步
- 然后反复进行这几个步骤
随机数生成用户ID
我们知道MySQL里有一个自增ID的概念,这个可以当做用户的ID。 这个ID有个特性:
- 自增,就是每新增一个用户,这个ID就会加1
这个直接当做用户ID是可以的,但是如果这个ID不能直接展示给用户看,因为用户可以借由这个ID直接看出来你的数据库有多少人,这很明显是不好的。
所以我们需要随机一个数字,给用户看,可以当做用户那边的唯一标识。
直接随机法
可以这样做:每次有用户注册的时候,我们在程序里随机一个数,然后在数据库里查查,这个数是否已经被用过了,如果没有用过,我们就将这个数字当做用户的ID。如果用过了,我们就再随机一次。
看上去挺好的,但是有劣势:
- 需要占用数据库额外的空间
- 需要多查一次数据库
多提一下,这种办法,每次系统重启,随机种子需要重新设定,如果不重新设定,可能会一直重复以前生成过的数字。
随机种子法
我们知道,随机种子一旦设定了,后面生成随机数就会按照一个固定的顺序。
根据这种特性,我们可以这么做:
- 设置一个固定的随机种子
- 每次程序重启,我们都将查一遍当前用户数N,然后生成N次随机数。
- 每有一个新用户注册,我们都再生成一个新的随机数。使用这个新的随机数当做用户的ID
等等,这不是有问题吗?这里没有查询数据库,怎么知道新生成的随机数不会重复呢?
😁,对,确实会重复,所以上面的方案不行。
改进:
这里需要对系统最大人数做一个预估:假设一千万。
我们程序启动的时候,先按照顺序,生成一个一千万的数组,里面存入:
就像这样
然后设置随机种子(注意,这个随机种子必须每次都一致),然后对这个数组进行Shuffle。
这个数组初始化好了之后,就可以用用户的自增ID当做下标,来上面的数组里来取真正的ID。
这里可以看出,随机种子每次必须都要一致,否则就乱套了。
一千万的数组生成然后Shuffle,十分快,根本察觉不到有这么一步。
所以在大部分公司,上面的方案是绝对可行的。
而且,在Shuffle数字的时候,可以在记录一下ID和自增ID的映射,这样从用户ID反查自增ID,也无需查数据库。
甚至,用户ID都不用存数据库,因为是一个程序可以计算得来的东西。