程序生成随机数的方法

在编写游戏程序时,以及在计算机模拟等情况下,经常使用随机数。随机数也是用程序来表示人类的直觉及念头的一种方法。计算机模拟指的是利用计算机模拟实际试验的方式。经常被用于建筑物的耐震实验等实际难以进行的实验中。使用随机数的计算机模拟有时也称为“蒙特卡洛法”,来源于因赌博而闻名的城市──蒙特卡洛。

随机数色子是用来产生随机数的一种工具,每个色子有20 面。晃动随机数色子后,出现在正面的数字就是随机数。由于计算机没法晃动随机数色子,因此程序一般会通过生成类似于随机数的数值公式来得到随机数。

在C 语言中,虽然该公式的实体是隐藏的,但只要调用rand() 函数,就可以得到结果(随机数)。不过,由于借助公式产生的随机数具有一定的规律性,因此并不是真正的随机数,通常称为伪随机数。不过,虽然是伪随机数,仍然十分有用。

作为参考,这里向大家介绍一个获取伪随机数的公式。该公式称为 线性同余法。除了线性同余法以外,还有其他获取伪随机数的方法。如可以获得更接近“真实随机数”的“乘同余法”、“M 系法”以及能够快速生成随机数的“Knuth 减算法”等。

如果把Ri 作为当前随机数的话,那么下一个出现的随机数Ri + 1 就可以用下面的公式来获取。

Ri + 1 = (a × Ri + b) mod c

公式中出现的mod,是整除后取余的意思。同C 语言的% 运算符的功能是一样的。对a、b、c 各参数设定合适的整数后,可以从该公式获得的随机数的范围就是0 到c(不包含)。因为是用c 来进行取余,所以得到这个范围也是理所当然的。

我们不妨做一下尝试,把a 设定为5,b 设定为3,c 设定为8,获得的随机数就如表。

蒙特卡洛随机抽样java实现_蒙特卡洛随机抽样java实现

不过,产生8 次随机数后,下8 次产生的随机数就和前面的数值相同了。这种周期性是伪随机数的特征,也是为什么不是真随机数的原因。

C 语言的rund() 函数中,也肯定通过某些公式生成了伪随机数。假如使用的是线性同余法的话,就需要提前设定Ri、a、b、c 的数值,用time(NULL) 来获取当前时间的参数,来设定Ri、a、b、c 的数值。

由于每次启动程序时的当前时间都是变化的,因此Ri、a、b、c 的数值也会随之发生
变化。Ri、a、b、c 的数值就称为 随机数的种子,这一点大家要有个印象。

而假如在不运行srand(time(NULL)); 的情况下重复调用rand() 函数的话,会出现什么情况呢?因为Ri、a、b、c 的数值都有默认值,因此每次都会生成以相同方式出现的随机数。这样一来,游戏以及计算机模拟就都无法成立了。当然也就无法表示人类的思考了。