使用随机数的一些应用

666 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情

随机数生成器

随机数生成器几乎在任何编程语言里都有,这东西能生成伪随机数。之所以是伪随机数, 是因为计算机本身是不能产生一个随机数的,所有的伪随机数都是使用某种数学理论而产生的,这种伪随机数有一个特点:就是可以重复。

这是什么意思?

  • 首先随机数生成器需要设置一个种子(Seed),这个Seed一旦设定,那么后面产生的随机数,都已经被固定死了。重新运行程序,只要种子(Seed)一致,随机算法一致,那么后面的随机数就一致。

这一点看起来不好,但是我们有时候还真需要这种特性。请注意这个特性,下面要谈到。

随机数应用-对数组进行洗牌(Shuffle)

为什么要对数组进行洗牌?可能这个数组是你的播放列表,你想随机播放,此时就需要进行一次洗牌。

洗牌算法很简单,假设数组长度N:

  • 第一步:在范围[0,N2]在范围[0, N-2]内,找到一个随机数xx, 将xx下标与N1N-1下标交换。
  • 第二步:此时,我们忽略最后一个元素,将数组长度看成 N-1
  • 然后进行第一步
  • 然后反复进行这几个步骤

随机数生成用户ID

我们知道MySQL里有一个自增ID的概念,这个可以当做用户的ID。 这个ID有个特性:

  • 自增,就是每新增一个用户,这个ID就会加1

这个直接当做用户ID是可以的,但是如果这个ID不能直接展示给用户看,因为用户可以借由这个ID直接看出来你的数据库有多少人,这很明显是不好的。

所以我们需要随机一个数字,给用户看,可以当做用户那边的唯一标识。

直接随机法

可以这样做:每次有用户注册的时候,我们在程序里随机一个数,然后在数据库里查查,这个数是否已经被用过了,如果没有用过,我们就将这个数字当做用户的ID。如果用过了,我们就再随机一次。

看上去挺好的,但是有劣势:

  • 需要占用数据库额外的空间
  • 需要多查一次数据库

多提一下,这种办法,每次系统重启,随机种子需要重新设定,如果不重新设定,可能会一直重复以前生成过的数字。

随机种子法

我们知道,随机种子一旦设定了,后面生成随机数就会按照一个固定的顺序。

根据这种特性,我们可以这么做:

  • 设置一个固定的随机种子
  • 每次程序重启,我们都将查一遍当前用户数N,然后生成N次随机数。
  • 每有一个新用户注册,我们都再生成一个新的随机数。使用这个新的随机数当做用户的ID

等等,这不是有问题吗?这里没有查询数据库,怎么知道新生成的随机数不会重复呢?

😁,对,确实会重复,所以上面的方案不行。

改进:

这里需要对系统最大人数做一个预估:假设一千万。

我们程序启动的时候,先按照顺序,生成一个一千万的数组,里面存入:

就像这样1,2,3,4,......9999999,100000001,2,3,4, ...... 9999999, 10000000

然后设置随机种子(注意,这个随机种子必须每次都一致),然后对这个数组进行Shuffle

这个数组初始化好了之后,就可以用用户的自增ID当做下标,来上面的数组里来取真正的ID。

这里可以看出,随机种子每次必须都要一致,否则就乱套了。

一千万的数组生成然后Shuffle,十分快,根本察觉不到有这么一步。

所以在大部分公司,上面的方案是绝对可行的。

而且,在Shuffle数字的时候,可以在记录一下ID和自增ID的映射,这样从用户ID反查自增ID,也无需查数据库。

甚至,用户ID都不用存数据库,因为是一个程序可以计算得来的东西。