主题:--- rand() --- 到底是否是绝对的随机?
琅拿度
[专家分:2820] 发布于 2009-07-27 11:36:00
程序用到了RAND(),但老感觉得到的结果不是真正的随机。
我想得到0-1间两位随机数,程序多个地方都使用了rand(),没有使用参数。
哪位大虾可以给些经验?
回复列表 (共26个回复)
沙发
琅拿度 [专家分:2820] 发布于 2009-07-27 11:44:00
abc=iif(rand()<=thisform.tgl1.value/100,'a',iif(rand()<=thisform.tgl2.value/(thisform.tgl2.value+thisform.tgl3.value+thisform.tgl4.value),'b',iif(rand()<=thisform.tgl3.value/(thisform.tgl3.value+thisform.tgl4.value),'c','d')))
根绝概率,取值:a\b\c\d之一
板凳
moz [专家分:37620] 发布于 2009-07-28 02:00:00
1.最好使用变量,不要直接用那么多的属性。
2.你用了四个rand(),好像不恰当,应该用一个变量代替
3.如果仅仅是abcd这个四字母,用substr()会更方便
t0=rand( )
t1=thisform.tgl1.value / 100
t2=thisform.tgl2.value / ( thisform.tgl2.value + thisform.tgl3.value + thisform.tgl4.value)
t3=thisform.tgl3.value / ( thisform.tgl3.value + thisform.tgl4.value )
abc=substr(t0<=t1,"a",t0<=t2,"b",t0<=t3,"c","d")
4.因为我不太清楚你为什么要用到这四个文本框的值,如果纯粹是随机abcd,我会这样做:
abc=substr("abcd",rand()*4+1,1)
3 楼
moz [专家分:37620] 发布于 2009-07-28 02:01:00
哦,顺便问个小白的问题。
C罗指的是琅拿度?还是琅拿颠奴?还是别人?
4 楼
Ilikefox [专家分:5770] 发布于 2009-07-28 10:15:00
你的感觉很对,呵呵,本来就没有产生真正随机数的函数,换句话说,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个数不同,不过却失去了随机数的意义。为什么?想想看。
5 楼
琅拿度 [专家分:2820] 发布于 2009-07-28 10:22:00
[quote]哦,顺便问个小白的问题。
C罗指的是琅拿度?还是琅拿颠奴?还是别人?[/quote]
C罗就是朗拿度前面加上C (个人不欣赏他)
朗拿度一般指罗纳尔多 R9
朗拿颠奴一般指小罗
你应该知道的吧,拿我来笑,最希望能看见R9重新穿上黄装啊,可惜机会渺茫,连5大联赛都不在,看比赛的机会都少了
6 楼
琅拿度 [专家分:2820] 发布于 2009-07-28 10:29:00
很高兴得到两位的指点,我自己做实验体会一下,消化还是需要时间啊。
7 楼
琅拿度 [专家分:2820] 发布于 2009-07-28 11:37:00
FOR i=1 TO 5
?RAND()
ENDFOR
如果不执行 RAND(-1)的话, RAND()的值只跟从启动程序后执行RAND()的次数有关。所以没有随机意义。
FOR i=1 TO 5
?RAND(-1)
ENDFOR
如果想通过RAND(-1)取得随机值的话,但时间间隔太短,RAND(-1)跟时刻有关,或许是因为这个时刻的最小单位比一个语句的执行时间大好多,所以也没有随机意义。
=RAND(-1)
FOR i=1 TO 5
?RAND()
ENDFOR
这样可以产生5个相对随机的随机数。但是如果是这样呢?有意义也不大了吧?
FOR J=1 TO 2
=RAND(-1)
FOR i=1 TO 5
?RAND()
ENDFOR
ENDFOR
不知道上面的理解对不对,如果对的话,是否就意味着短时间无法产生很多随机数呢?如果是的话,那么如果想在尽量短的时间内得到尽量随机的数,这个时间间隔要多少呢?
8 楼
琅拿度 [专家分:2820] 发布于 2009-07-28 11:55:00
只能这样解决吗?
FOR J=1 TO 2
=RAND(-1)
FOR i=1 TO 5
?RAND()
ENDFOR
WAIT 'waiting...' window at -1,-1 timeout 0.001
ENDFOR
9 楼
琅拿度 [专家分:2820] 发布于 2009-07-28 14:11:00
真是有趣的实验,当间隔的时间是恒定时,能看到一定的规律:
FOR J=1 TO 2
=RAND(-1)
FOR i=1 TO 3
?RAND()
ENDFOR
for k=1 to 9999
a=1
endfor
ENDFOR
?''
如果是9999的话,有时候(大概1/5的机会),第一个随机数和第四个随机数差0.02,第三个随机数和第六个随机数差0.01,如果是99999的话,依然有很大机会是这样。但如果是999999的话,我的实验就好象没出现过。
所以怀疑如果用一定时间间隔去隔开,得到的随机数仍然是有规律的,这个间隔大概是多少才不会有那么明显的规律呢?
如何让这个间隔时间也是一个随机的时间,这样可以得到数量更多、更随机的数值呢?
10 楼
bbssem [专家分:10] 发布于 2009-07-28 16:55:00
FOR J=1 TO 2
=RAND(-1)
FOR i=1 TO 5
?RAND()
ENDFOR
WAIT 'waiting...' window at -1,-1 timeout 0.001
ENDFOR
这个行的,但不一定要用这个,还有其他方法的
我来回复