谈谈无重复随机数的产生方法

 

说 到随机数,我也不知道机子是怎么产生的,英文叫rand,我也无法知道什么是真正的随机事件,感觉这世界上所有的事情当无法解释的时候,那就叫随机吧,当 我们掌握或可以彻底解释的话,它就不是随机的,之所以随机,是因为一点规律一点本质的区别也没有,不知道这样的理解算不算粗糙!

上 学期在学习过程中,犹其是组合数学的诡异的编程,玩弄数组的算法设计使我穷堪一时,主要原因是我懒,我笨,手上没有一本拿出来供参考的书,所以当我今天弄 懂一些的时候是这样的迟迟得其利害,以至于不想再让学习的同胞饱受此等痛苦。随机数的产生就是我看不惯同学和老师大肆渲染和其诡异的巨逼之下完成的。


1.matlab中的方法
matlab具有强悍的数组处理功能,这其中包括数组的初始化和编辑,其速度不知道怎么那么快。用C++的时候老是在Console下不大适应的原因,在可视化的编辑环境下,才领略到这些东西所蕴含的艺术。

关于随机数的产生,matlab提供了rand(n, m)这样的函数,其实用C++实现也是比较简单的。这里谈一下产生1~n个不重复的随机数,它到底是如何产生的?

搜一下matlab的关于randperm函数文件,果然搜到randperm.m
其解释如下:

function p = randperm(n);
%RANDPERM Random permutation.
%   RANDPERM(n) is a random permutation of the integers from 1 to n.
%   For example, RANDPERM(6) might be [2 4 5 6 1 3].
%  
%   Note that RANDPERM calls RAND and therefore changes RAND's state.
%
%   See also PERMUTE.

%   Copyright 1984-2002 The MathWorks, Inc.
%   $Revision: 5.10 $  $Date: 2002/04/09 00:26:14 $

[ignore,p] = sort(rand(1,n));

看到上面的解释,原来randperm又是基于rand和sort之上:即先随机产生n个数,当然这n个数可以相同,也可以相同,但并不影响排序,因为无论相等还是不相等还是可以排名的。

为了验证这个想法,当场实验一下:
>> y=rand(1, 6)

y =

    0.4103    0.8936    0.0579    0.3529    0.8132    0.0099

>> [ignore,p] = sort(y)

ignore =

    0.0099    0.0579    0.3529    0.4103    0.8132    0.8936


p =

     6     3     4     1     5     2

果然,我们看到0.009是最小,所以排序后,将它的下标,也就是它是第几个产生的(它是第6个产生的随机数,所以将它的下标6标进了第一个整型的随机数。

其次是0.0579它在原随机序列中是第3个产生的,所以排序后,将3放入第2个显示的位置。依次推,分别得到剩下的数字顺序。

果然是刁!

原来产生无重复随机数的原理是这样的:任何随机数,其产生的顺序必然是一整数序列:
即从1, 2, 3, ..., n产生了n个数,你且别管这n个数是不是重复的,反正是产生了n个数,这n个数都有自己对应的一个下标,这个下标就是它是第几个产生的。即一个随机数有两个特征:

1. 它的大小。
2. 它的下标,即它是第几个产生的。

无论有多少个重复的数,其总有一个排序结果,这个排序的结果所对应的数的下标即随机产生的数列。

当然在排序的过程中其下标要跟着置换变化。

2.置换方法

这个方法是看到网上一友写的。其大致内容摘抄如下:

 //产生一个随机数组
 //1: 把你最终需要的结果(不重复的数)预先放在一个数组中,
 //   因为rand函数产生的随机数会重复,我们不直接用,
 //   而是用来对应数组的下标
 //2: rand产生一个随机下标,我们就取出对应数组中的值
 //  (我们真正需要的随机数)
 //3: 然后用数组最后一个值来替换该下标数组中的值
 //4: 将产生随机下标的范围减少一
 //5: goto 2

 //   注: 3中所谓数组最后一个值是指产生随机下标范围内的最后一个.
     //   如产生随机下标0-9, 第一次就用array[9]替换,
 //   第二次就用array[8]替换.

/* 一种算法
#include
#include
#include

#define NUM 10

int main()
{
    int cont[NUM];
    int index, i;

    for (i=0; i

    srand((int)time(0));

    for (i=0; i

    return 0;
}
*/

如果现在搜的话,这个回复帖应该还在。

我需要加的解释是:

1. 先产生一个随机数模n,必是一个小于n的数。即x=rand(); y=x%n; y

3. 从2中得到的一个数取其下标,充当第一个随机数,并为了保证下次随机时能取到它所包含范围内的数,有必要置换出它的下标。

反复2~3,可以产生完n个依次为小于n, n-1, n-2, ..., 1的数。

a[1, 2, ..., n]=1, 2, ... ,n

如产生一个数,模n之后为3,就显示其数为3, 因为数3对应的下标为3, 再产生一个数,模n-1后为3,怎么办?

我们将a[3]与a[n]交换,即有a[3]=n, a[n]=3, 所以第二次产生的一个3,它对应的下标就是n了,所以显示这个随机数的时候就是3.

3.实验结果
对数据的处理均要格式化一样,这样才像matlab,这样才对齐吗!
看看下面一组数据:

98    74    10    17    36    32    64    16    57    24   
99    67    55    48    31    28    13    51    39    1    
70    91    60    26    9     3     92    86    49    29   
6     79    14    83    23    94    73    81    12    77   
35    40    50    4     27    8     43    44    62    58   
93    63    42    82    37    53    89    84    15    80   
33    100   68    69    7     88    90    78    52    59   
85    47    30    54    71    65    97    66    87    61   
46    19    5     20    34    2     11    22    96    25   
72    21    41    95    56    45    75    38    76    18   

哇,爽呀,对齐的卡卡的!
再按一下随机按钮又是一串,没有重复的,可以歇伙啦!

附图:


4. 感想
计 算机中的数学和数学中的计算都是奥妙无穷,有感于自己的一点点实践实在微不足道貌岸然。犹其是matlab的功能真强呀,而且快,主要是算法过硬吧!把人 类的某些智慧熔聚在一个叫matlab的软件里实属不易!当然其它的数学软件也牛,只不过我现在在学这个,所以暂只夸它。


小蛤蟆帅
15:25 2006-9-28


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/superdont/archive/2007/04/24/1581105.aspx

你可能感兴趣的:(matlab,permutation,random,算法,function,date)