友情提示:380元/半年,儿童学编程,就上码丁实验室。
随机数在游戏和动画中十分有用。在很多程序中,我们需要打乱一些项的次序。
例如,将1-10的数字生成一个随机的排列。那么,如何完成这个功能呢。一般情况下,我们会要求将排列后的数字放在一个列表中。
简单地生成随机数并加入列表是不可行的,因为这样很容易出现数字重复的情况,得到不重复的结果的机率是很低的(对于10个数字来说,机率大约为1/2755)。
所以我们就需要考虑使用什么样的方法了。
//////////
基于这个想法,程序的主体如下
其中用于找到一个可用数字的子程序如下:
生成一个数字N,看是否已存在在列表中,如果不存在,则退出子程序。如果已存在于列表中,则另外生成一个随机数。
可以想像,为了找到不重复的数字,程序需要进行很多次尝试,如果需要生成的列表很大,就会花费较多的时间。
既然上一个方法中,我们的大部分时间都花在找生成的随机数是否已存在于列表中,那么是否可能使用其它的方式呢。
假设第一次生成了一个随机数1,则之后就不再需要生成1了,只需要在2到9之间生成随机数就可以了。换句话说,也就是在剩下的9个数中取一个就可以了。根据这个想法,我们就能够设计出另外一个方法。
这个方法需要使用两个列表,一个是原始列表,一个是结果列表。先将1到10放在原始列表中,随机从中取出一个,加入结果列表,之后在原始列表中删除刚取出的项。反复运行直到将原始列表的所有项取出。
程序如下:
因为每次只需要在剩余的列表项中选择出一项,这个方法的运行速度快,使用也很方便。
那么还有没有其它的方法呢?我们还有一个很有趣的方法。
这个方法是基于交换的,如果我们在生成列表后,随机对列表内的两个项进行交换,也是可以得到随机列表的。
程序如下:
其中变量i和j是两个随机生成的下标,借助t对列表中的两项进行交换。大家可能马上会想到,需要交换多少次才够呢?
10个数学的全排列有10!=3628800种。一次交换能够生成两个不同的排列,2次交换能够生成2的2次方种分布。N次交换可能能够生成2的N次方种(考虑到一些情况,实际能够生成的排列要小于这个数字)。那么需要至少2^N>10!。
这时N等于22。所以至少需要22次,我们可以在程序中取大于22的数,基本可以保证得到随机可用的列表。
总结
1 得到打乱的列表是一个常用的功能。
2 文章中提出了三种不同的方式,每种都有自己的特点,可以按需使用。从速度上来说,一般来说第2个方法最快。
3 有很多时候参数的确定需要进行数学的分析。