回 帖 发 新 帖 刷新版面

主题:--- rand()  --- 到底是否是绝对的随机?

程序用到了RAND(),但老感觉得到的结果不是真正的随机。

我想得到0-1间两位随机数,程序多个地方都使用了rand(),没有使用参数。

哪位大虾可以给些经验?

回复列表 (共26个回复)

11 楼

依目前经验看:短时间太频繁(如三四个语句的几个循环内)使用rand(-1)也不是好事,会造成概率值太接近甚至相等,不一定对,只是感觉。

所以目前可以尝试的办法是,在数量大的循环内,当循环达到一定数量时,才使用一次RAND(-1),并且可以让时间随机(随机长度,不要是整数,结核RAND(-1)、/3这样的能造成结果不规律的表达式去计算)停顿一阵,这样数值应该会随机平均一些。

12 楼

原来C罗是第三个人,明白了。

rand( )的参数是负数的时候,会利用系统时间做种子来获得一个随机序列,
其实序列都已经设置好了,(好比是已经固定了某个数组了)
后面的就可以使用参数(相当于数组下标)来读取随机数了。

只要种子相同,得到的随机序列是相同的。
也就是说,万一两次运行的时间是一模一样的(精确到百分之一秒),
得到的结果也会是相同的。
这样的机会微乎其微,所以没有必要多次使用rand(-1)
也可以打乱序列的顺序,来达到更乱的目的。

13 楼

既然都是计算出来的,那岂不是任何一种语言也无法做到随机? 

加一个循环去打乱时间和顺序:
FOR i=1 to x
IF mod (i,37)=1
FOR k=1 to 999999+int(999999*rand(-1))
    rand()
ENDFOR
ENDI
ENDFOR

14 楼

这个随机,不是你心目中的随机,但它确实可以成为现实中的随机.
当你不了解它的时候,你可以认为它是随机的,这种看法并没有错误.
你认为它不随机,是因为你太了解它了.

其实,没有必要心有芥蒂.

你要相信.

15 楼

琅拿度钻牛角尖了,呵呵。

16 楼

谢谢各位,只能尽量打乱,抽取一个算了。

17 楼

一般在程序初始化时用RAND(-1)获得随机数种子。
如果在程序中多次使用RAND(-1),种子碰撞(相同)的机会增大了,随机性反而更小了。

18 楼

[quote]你的感觉很对,呵呵,本来就没有产生真正随机数的函数,换句话说,RAND()是伪随机数。
早年学习FORTRAN语言(专门用于科学计算的语言),一个经典的程序就是编写产生伪随机数的函数。原理是先自行确定一个0到1之间任意的数X0(称为“种子”),然后拿它进行一番数学运算(这里把这一番数学运算称为一个随机算法),得到一个新的在0到1之间的数X1,这个X1作为产生的随机数。要得到下一个随机数,拿这个产生的随机数X1再次经过随机算法,又得到一个新的数X2,以此类推。随机算法保证每次计算结果尽可能平均分布在0到1之间。于是我们就有了得到随机数的函数,当然了,如果种子不变,得到的随机数系列必然是一致的,因此称它是伪随机。伪随机数算法有兴趣的话可在网上找到,并不难。Fox中的RAND()函数道理一样(注意,俺是说道理一样,即Fox实现的可能更复杂些,比如他的种子并不限定在0到1之间)。

当我们第一次执行RAND()的时候,如果不用参数(这参数就是种子),Fox用一个默认的种子100001得到第一个结果,后面再用RAND(),就拿第一个结果进行计算得到第二个结果,以此类推。从刚才的话,你可以推论出Fox会记住每次得到的结果,并用于下一次计算。由于默认种子是固定的,所以随机序列也是固定的,呵呵,伪随机。

做实验验证:命令窗口输入如下命令,全选中回车执行

FOR i=1 TO 5
?RAND()
ENDFOR 

主窗口显示产生的5个随机数(由种子100001产生的随机数系列的前5个),记住它。

退出Fox重新启动,再次执行上述命令,注意到产生的还是那5个数。

可能的疑问是:我能不能不退出Fox,再次执行上述命令?
答:可以,不过它将按照第一次执行后的结果继续这个随机系列,固定种子产生的固定系列在同一个Session(简单的说就是fox的一次启动直到退出)中保持下去。

知道了这个原理,就能解释你为什么感觉不是真正的随机。

要做到“真正的随机”,我们应该使用不同的种子即可达到这种效果。(俺加了引号,种子本身就不是随机产生的,是指定的,所以严格的说随机数系列还是伪的,不过已经能接近达到真正随机的效果)

习惯上在使用RAND()函数之前,经常执行一句:
=RAND(-1)
把-1作为参数,并不是拿-1做种子,Fox会利用系统时间产生一个数做为种子,我们不清楚具体Fox是怎么得到这个数(种子)的,但可以知道不同时刻,得到的数必然不同。注意这个句子是无变量赋值语句,即,把RAND(-1)得到的第一个随机数丢弃,目的主要是获取种子,保证后面用RAND()得到新随机数序列。

做实验验证:命令窗口输入如下命令,全选中回车执行

=RAND(-1)
FOR i=1 TO 5
?RAND()
ENDFOR 

主窗口显示产生的5个随机数

接下来不管是继续执行一遍还是退出Fox重启再次执行,你都会得到不同的随机数,呵呵,原因很简单,每次种子都变化了。

当然你也可以指定种子,比如Rand(9),拿9做种子,这样种子固定,并不好。

下面来个有趣的实验:
FOR i=1 TO 5
?RAND(-1)
ENDFOR 
看起来每次都用新种子,应该得到不同的随机数,呵呵,NO。为什么?想想看。

再来一个:
FOR i=1 TO 5
?RAND(i)
ENDFOR 
这回5个数不同,不过却失去了随机数的意义。为什么?想想看。
[/quote]


Ilikefox老师,继续讲下去啊,学习了!!!正研究学习这个函数!

19 楼

为了增强效果,我考虑加入:

Sleep(int(10*(rand())))

因为这个命令本身就延时不准确,再结合时间来取种,应该效果会好一点

20 楼

既然是随机,好像没有必要过于在乎它们之间的规律。
不太清楚你想把它应用在哪个方面,网上绝大部份人编这些关于随机数的,都想利用它来为自己的投注出一分力,就像人们看马报寻玄机一样,既然都是命运的偶然,哪来费那么工夫的必要。

你可能是需要在同一时刻里,获得几个不同的随机数,但却又担心它们之间会存在着某种联系,而造成不随机。
(是不是可以打个比如:想请几个人来做财务工作,却担心他们彼此认识互相勾结。)
你还去统计了它们的大小变化规律,也许是在产生随机数的过程中,为了看起来更“随机”一点,前面出了个数比较大的,后面就跟个比较小的数,你是担心会出这样的问题吧?那就打破这个顺序的规则就解决了。

用以下方法同时产生两个随机数,你是不是还能找得到它们之间的相对关系呢?
又或者,你有没有办法把电脑调到同一时刻去获得相同的序列呢?

?RAND(-1)
?RAND(MOD(SECONDS()*1000,100)*LOG(DATE()-{^1901-01-01})*100+DOW(DATE()))
?RAND(100*abs(cos(360*rand(SECONDS()*53789))))
其实更简单一些:
?rand(100*rand(100*rand(100*rand(.......

我来回复

您尚未登录,请登录后再回复。点此登录或注册