亂數應用
先從最簡單的範例看起:
範例1:產生0~9的亂數 :::::::::::::::::::::::::::::::::::::::::::::: #include <stdio.h> #include <time.h> #include <stdlib.h> void main() { unsigned short int flag[10] = { 0 }; unsigned short int count = 10; //產生0~9,共10個 unsigned short int i , num ; //初始化亂數產生器(或亂數種子) srand ( (unsigned)time(NULL) ); do { num = rand() % 10; if( !flag[num] ) { flag[num] = 1; --count; printf("%d\n",num); } }while(count); } ::::::::::::::::::::::::::::::::::::::::::::::
(1)rand產生一個介於0~RAND_MAX之間的的亂數,RAND_MAX可在stdlib.h裡找到
/* Maximum value that can be returned by the rand function. */ #define RAND_MAX 0x7fff //32767
因rand函數所產生的亂數均是使用亂數種子的值來啟動產生亂數的演算法,故若亂數 種子的值是一樣的,每次程式開啟產生的亂數序列是一樣的,若亂數種子的值是不一樣的 那每次產生的亂數序列會不一樣,不相信,你將srand(...)中的值改為5,然後重新開 啟程式,你觀察是不是每次產生的亂數序列都是一樣的。所以才會利用時間做為亂數種子 的值,記得有編譯器會提供randomize()來代替初始化亂數種子,但其實randomize的定義:#define randomize() srand((unsigned)time(NULL))另外(unsigned)可加可不加,這是做轉型的動作,time()的回傳值是time_t,其實就是long, 而srand(...)的參數的型態是unsigned,所以加上(unsigned)做強制轉型的動作,但若沒有加 的話,編譯會幫你隱含的轉換。註: <1>implicit:隱含的(意指並非在程式原始碼中出現的) <2>explicit:明白的(意指程式原始碼中所出現的)(2)num = rand()%10:產生0~9的亂數。rand()%N,會產生0到N-1的數值,而有編譯器提供 一個random取亂數的函數,但其實定義就是:#define random(num) (rand() % num)
num = 0 + rand() % ( (9-0) + 1 )
那有樣學樣一次: num
= 90 + rand() % ( (100-90)
+ 1 )
首先你要清楚三個事情:最小數值、最大數值、最大數值與最小數值間總共有幾個數(包括頭尾)
最小數值:90
最大數值:100
最大數值與最小數值間總共有幾個數(包括頭尾):100
- 90 + 1
所以總共要產生幾個數值,是不是(100
- 90 + 1)個就可以了!再加上最小數值不就是你要的範圍嗎?
自己試試看囉!!!
接著試試自己寫函數的功力,寫一個產生start_value到end_value之間的亂數,函式宣告如下:
short int rand_range_generator(short int start_value,short int end_value);
使用如下:
範例2: :::::::::::::::::::::::::::::::::::::::::::::: #include <stdio.h> #include <time.h> #include <stdlib.h> short int rand_range_generator(short int start_value,short int end_value) { srand( time(NULL) ); //初始化亂數產生器(或亂數種子) return start_value + rand()%( (end_value-start_value) + 1 ); } void main() { int i; for(i=0;i<10;++i) printf("%d\n",rand_range_generator(90,100)); } ::::::::::::::::::::::::::::::::::::::::::::::
結果測了一下,數值都一樣,會不會是函數寫錯了呢?不會呀!!!問題在srand()的地方,由於電腦執行的
速度相當的快,當此程式迴圈範圍為N時,若花費的時間差距還不到1秒,以致於time(NULL)回傳的結果
都是一樣的,亦就是亂數種子一樣,而迴圈做了N次的結果,都會是一樣的。將迴圈範圍改至M時,若執行
時間相互差距大於1秒時,time(NULL)回傳值即亦改變,亂數種子就跟著改變。就是說,迴圈執行10次的
時間還不到1秒鐘,time(NULL)回傳的值都一樣,即亂數種子一樣,產生的值就一樣!這個程式只是告訴
大家srand(...)應該放在main()裡面或是公開的地方,才不致於發生這種情況。所以你將srand(...),放
到main()裡,就不會發生這樣的錯誤了!!!
介紹到此,你可以寫樂透程式、猜數字、…等。別客氣,絕對不難...
產生介於0到1之間的浮點亂數:
範例3:
::::::::::::::::::::::::::::::::::::::::::::::
float frandom()
{
int x = rand();
int y = rand();
if(x>y)
return (float)y/(float)x;
else if(y>x)
return (float)x/(float)y;
else
return 1.0f;
}
::::::::::::::::::::::::::::::::::::::::::::::
Written By James On 2004/02/08