亂數應用
先從最簡單的範例看起:
範例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,會產生0N-1的數值,而有編譯器提供
一個random取亂數的函數,但其實定義就是:
	#define random(num) (rand() % num)
現在假設要產生90100的亂數要怎麼處理呢?能不能從上面的說明有樣學樣呢?你可以把上式這樣看

    num = 0 + rand() % ( (9-0) + 1 )

那有樣學樣一次:    num = 90 + rand() % ( (100-90) + 1 )
首先你要清楚三個事情:最小數值、最大數值、最大數值與最小數值間總共有幾個數(包括頭尾)
最小數值:90
最大數值:100
最大數值與最小數值間總共有幾個數(包括頭尾)100 - 90 + 1
所以總共要產生幾個數值,是不是(100 - 90 + 1)個就可以了!再加上最小數值不就是你要的範圍嗎?
自己試試看囉
!!!
接著試試自己寫函數的功力,寫一個產生start_valueend_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()裡,就不會發生這樣的錯誤了!!!

介紹到此,你可以寫樂透程式、猜數字、…等。別客氣,絕對不難...

產生介於01之間的浮點亂數:

        範例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 

 

Hosted by www.Geocities.ws

1