|
楼主 |
发表于 2009-12-20 23:20
|
显示全部楼层
今天的学习内容,一起看看O(∩_∩)O~
VB随机数
相信很多人也用過VB 產生隨機數,因為在絕大部分的VB 課程中也會提及過,在部分參考書中這也是不可缺少的課題。 相信很多人也用过VB产生随机数,因为在绝大部分的VB课程中也会提及过,在部分参考书中这也是不可缺少的课题。
隨機數可以做出不少有趣的效果:如隨機轉換色彩、隨機選擇。 随机数可以做出不少有趣的效果:如随机转换色彩、随机选择。 究竟我們瞭解VB 隨機數多少呢? 究竟我们了解VB随机数多少呢? 讓我們來一起探討吧。 让我们来一起探讨吧。
Rnd 函數: Rnd函数:
Rnd 函數可以回傳一個資料型別為Single 的數值,此數值必定大過或等於0 及比1 小 ,但最大值是甚麼呢? Rnd函数可以回传一个资料型别为Single的数值,此数值必定大过或等于0及比1小 ,但最大值是什么呢? 因為那數值是Single 型別,有效位數是7﹝請參考「 電腦資料類型 」﹞,所以照理該是0.9999999,但實際上卻不是,這遲些再探討吧。 因为那数值是Single型别,有效位数是7﹝请参考「 电脑资料类型 」﹞,所以照理该是0.9999999,但实际上却不是,这迟些再探讨吧。
先看看最簡單的隨機數程式,在表單上設一CommandButton,然後嘗試執行以下程式: 先看看最简单的随机数程式,在表单上设一CommandButton,然后尝试执行以下程式:
Print Rnd Print Rnd
在我的電腦上所印出的結果是: 在我的电脑上所印出的结果是:
0.7055475 0.7055475
0.533424 0.533424
0.5795186 0.5795186
0.2895625 0.2895625
0.301948 0.301948
如果重新執行一次程式的話,隨機數的出現次序也會是一樣。如果重新执行一次程式的话,随机数的出现次序也会是一样。
為甚麼呢?为什么呢? 原來在電腦中有一樣東西叫「亂數表」,Rnd 函數只是要求亂數表給亂數,而亂數表會依序的把亂數給Rnd 函數,所以才會出現這現象。原来在电脑中有一样东西叫「乱数表」,Rnd函数只是要求乱数表给乱数,而乱数表会依序的把乱数给Rnd函数,所以才会出现这现象。 為了可以使隨機數在每一次也不同,我們都會給亂數表設定一個亂數種子,絕大部分的編程員更會以現在的時間作為亂數種子,以更新亂數表。为了可以使随机数在每一次也不同,我们都会给乱数表设定一个乱数种子,绝大部分的编程员更会以现在的时间作为乱数种子,以更新乱数表。 這樣每次執行程式時亂數表都會給不同的隨機數了。这样每次执行程式时乱数表都会给不同的随机数了。
而設定亂數種子可以用VB 內的Randomize 方法:而设定乱数种子可以用VB内的Randomize方法:
Randomize 方法的格式: Randomize方法的格式:
Randomize([Number]) Randomize([Number])
中括號內的參數是指可以不輸入,如果沒有輸入的話便會取其預設值,而Number 參數的預設值正是現在的時間﹝Timer﹞。中括号内的参数是指可以不输入,如果没有输入的话便会取其预设值,而Number参数的预设值正是现在的时间﹝Timer﹞。
Randomize Timer Randomize Timer
Print Rnd Print Rnd
用以上程式便可以在執行程式時印出不同的隨機數。用以上程式便可以在执行程式时印出不同的随机数。
好了,花了太多篇幅說明用VB 求亂數的基本概念,是時候入正題說一說如何應用了。好了,花了太多篇幅说明用VB求乱数的基本概念,是时候入正题说一说如何应用了。
1. 讀取某一範圍內的隨機整數: 1.读取某一范围内的随机整数:
假設我們要讀取0 ~ 10 內的隨機整數,資料類型為Integer,程式如下:假设我们要读取0 ~ 10内的随机整数,资料类型为Integer,程式如下:
Dim I As Integer Dim I As Integer
Randomize Timer Randomize Timer
I = CInt(Int(Rnd * 11)) I = CInt(Int(Rnd * 11))
* Int 函數可以除去小數的點數部分,如: * Int函数可以除去小数的点数部分,如:
Int(4.99) Int(4.99)
Int(4.11) Int(4.11)
兩個的回傳值也是4。两个的回传值也是4。
* CInt 函數可以使資料強迫性轉換成Integer 型別,因為Int 函數的回傳值的資料類型是Variant,因此它的型別會受它的參數影響,從以上程式,Int(Rnd * 11) 的回傳值的資料類型將會是Single。 * CInt函数可以使资料强迫性转换成Integer型别,因为Int函数的回传值的资料类型是Variant,因此它的型别会受它的参数影响,从以上程式,Int(Rnd * 11)的回传值的资料类型将会是Single。
因為Rnd 函數所回傳的值必定比1 少,所以Rnd * 11 必定不會等於11,因此加上Int 函數時,最大值將會是10;而下限當然是0,因此便可以隨機求出0 ~ 10 內的隨機整數了。因为Rnd函数所回传的值必定比1少,所以Rnd * 11必定不会等于11,因此加上Int函数时,最大值将会是10;而下限当然是0,因此便可以随机求出0 ~ 10内的随机整数了。
如果我們想要出1 ~ 10的的隨機整數的話,只要先求出0 ~ 9 的隨機整數,再將它們加1 便是1 ~ 10 了,所以程式是:如果我们想要出1 ~ 10的的随机整数的话,只要先求出0 ~ 9的随机整数,再将它们加1便是1 ~ 10了,所以程式是:
Dim I As Integer Dim I As Integer
Randomize Timer Randomize Timer
I = CInt(Int(Rnd * 10) + 1) I = CInt(Int(Rnd * 10) + 1)
因此我們得出以下求取隨機整數的公式:因此我们得出以下求取随机整数的公式:
變數= Int(Rnd * 隨機整數總數) + 下限 变数= Int(Rnd *随机整数总数) +下限
* CInt 函數是取決於該變數的資料類型。 * CInt函数是取决于该变数的资料类型。
2. 讀取某一範圍內的隨機數﹝帶有小數﹞: 2.读取某一范围内的随机数﹝带有小数﹞:
假設我們要讀取0 ~ 10 內的隨機數,及小數點後一位﹝有可能是整數﹞,程式如下:假设我们要读取0 ~ 10内的随机数,及小数点后一位﹝有可能是整数﹞,程式如下:
Dim S As Single Dim S As Single
Randomize Timer Randomize Timer
S = Round(Rnd * 10, 1) S = Round(Rnd * 10, 1)
*Round 函數的格式: *Round函数的格式:
Round(數值, [小數點後數位As Long]) Round(数值, [小数点后数位As Long])
*「小數點後數位」參數的預設值為0。 *「小数点后数位」参数的预设值为0。
Round(1.234, 2) Round(1.234, 2)
Round(1.567, 2) Round(1.567, 2)
Round(1.987, 2) Round(1.987, 2)
Round(1.999, 2) Round(1.999, 2)
以上的結果分別為1.23、1.57、1.99 與2。以上的结果分别为1.23、1.57、1.99与2。
因為Round 函數也是回傳Variant 型別,因此Round(Rnd * 10, 1) 便會回傳Single型別。因为Round函数也是回传Variant型别,因此Round(Rnd * 10, 1)便会回传Single型别。
因為Rnd * 10 的結果有可能是9.99x......,所以加上Round 函數後是有機會等於10。因为Rnd * 10的结果有可能是9.99x......,所以加上Round函数后是有机会等于10。
因此我們得出以下求取隨機小數的公式:因此我们得出以下求取随机小数的公式:
變數= Round(Rnd * 隨機整數總數- 1, 小數點後數位) + 下限 变数= Round(Rnd *随机整数总数- 1,小数点后数位) +下限
註:Round 函數在VB6 之前是沒有的,如果不能使用Round 函數的話可以選用Format 函數。注:Round函数在VB6之前是没有的,如果不能使用Round函数的话可以选用Format函数。 但這已超出了本章的範圍,請容許我不作解說,但大家還是可以在留言板中向我發問。但这已超出了本章的范围,请容许我不作解说,但大家还是可以在留言板中向我发问。
好了,現在大家可能在想Rnd 函數最多會有多少個變化吧,剛才我說過Rnd 函數的回傳值的上限一般是0.9999999,因此一般來說Rnd 函數是有10, 000, 000 ﹝一千萬﹞個變化,但其實此函數是有玄機的。好了,现在大家可能在想Rnd函数最多会有多少个变化吧,刚才我说过Rnd函数的回传值的上限一般是0.9999999,因此一般来说Rnd函数是有10, 000, 000 ﹝一千万﹞个变化,但其实此函数是有玄机的。
原來在亂數表中的亂數的有效位數是15,相等於Double 資料類型﹝請參考「 電腦資料類型 」﹞,即是說Rnd 函數未能完全發揮電腦亂數的彈性﹝雖然10, 000, 000 個變化已經十分多﹞,但其實是有辦法可以把Rnd 函數的傳回值在運算前將它轉換為Double 型別,方法是:原来在乱数表中的乱数的有效位数是15,相等于Double资料类型﹝请参考「 电脑资料类型 」﹞,即是说Rnd函数未能完全发挥电脑乱数的弹性﹝虽然10, 000 , 000个变化已经十分多﹞,但其实是有办法可以把Rnd函数的传回值在运算前将它转换为Double型别,方法是:
Print CDbl( Rnd ) Print CDbl( Rnd )
對!对! 只要用CDbl 函數將Rnd 由Single 型別轉換為Double 型別,那麼Rnd 函數的回傳值的上限便會增至0.999999999999999,同時亦可以產生1, 000, 000, 000, 000, 000 ﹝一千萬億﹞個變化了 。只要用CDbl函数将Rnd由Single型别转换为Double型别,那么Rnd函数的回传值的上限便会增至0.999999999999999,同时亦可以产生1, 000, 000, 000, 000, 000 ﹝一千万亿﹞个变化了 。
我花上了相當時間所求出的最大與最小的亂數分別是: 我花上了相当时间所求出的最大与最小的乱数分别是:
最大 :0.999999940395355 → 總共求了11, 529, 709 次才求到 最大 :0.999999940395355 →总共求了11, 529, 709次才求到
最小 :0.000241219997406006 → 總共求了125 次才求到 最小 :0.000241219997406006 →总共求了125次才求到
* 當然是由電腦代勞計算啊。 *当然是由电脑代劳计算啊。
字数超限,楼下继续,不是灌水O(∩_∩)O~ |
|