1. 程式人生 > >個人對rand()、srand()函式之間的關係及其內部實現原理的猜測

個人對rand()、srand()函式之間的關係及其內部實現原理的猜測

歡迎轉載,轉載請註明出處,謝謝

//首先我們先只看rand()函式,有函式如:
int main(int argc,char* argv[])
{
	int tmp=0;
	for(int i=0;i<50;++i)
	{
		// 獲取 0~19 的偽隨機數,存入tmp中
		tmp=rand()%20;
		cout<<tmp<<'\t';
	}
	cout<<endl;
	cin.get();
	cin.get();
	return 0;
}


其執行結果如下圖:

多執行幾次,你會發現該隨機數表與時間是無關的,到這裡我們還沒有什麼思路可以猜測其內部

實現原理,只知道沒有用srand()設定時間種子的rand()函式返回的其實是可記錄的值

//現在我們再來看下面的函式執行結果
int main(int argc,char* argv[])
{
	// time(0);返回的是從格林尼治時間到當前時間的間隔(單位:秒)
	srand((unsigned int)time(0));
	int tmp=0;
	for(int i=0;i<50;++i)
	{
		// Mark .
		// 獲取 0~19 的偽隨機數,存入tmp中
		tmp=rand()%20;
		cout<<tmp<<'\t';
	}
	cout<<endl;
	cin.get();
	cin.get();
	return 0;
}

OK,現在我們發現每次執行輸出的隨即數列是不一樣的,這說明srand()和rand()直接存在一定的聯絡(這不廢話麼,嘿嘿)現在關鍵的步驟來了,將上面的srand((unsigned int)time(0));函式剪下到Mark行下面,再編譯執行,發現所有的輸出值都是一樣的;為什麼會這樣呢,你先關掉程式,再重新執行,發現輸出序列仍然是一樣的,但是值和上一次不同了,這時候我們就可以來猜想一下它的內部實現方式了;

先複習一下高中數學對函式的定義之一:對於給定的自變數(可以是多元函式),只有一個因變數與之對應的方程才能稱之為函式,例如以x為自變數,y為因變數則x^2 + y^2 =1 就不是函式,x=0時,y有兩個值與之對應,現在開始將正文。我個人的猜想是這樣的:rand()函式每次只得出一個特定的值(因變數),但是得出這個值需要依賴於某個或某些變數(即是前面講的自變數)的值,而如果我們沒有設定時間種子的話程式 第一次 執行rand函式,自變數的初始值都是同一個定值,所以每次執行程式輸出的隨機值都一一對應。但是為什麼rand()在同一次程式執行時能夠生成不同的數呢(偽隨機數列),我個人分析是這樣:rand()在計算出返回值,且在返回它之前會通過某種演算法改變因變數的值所以在下一次呼叫rand()函式時,由於因變數的值與上次不一樣了,所以計算出的返回值自然也就很可能不同;那srand()函式與rand()函式有什麼關係?我認為srand函式可以改變rand函式依賴的自變數的值,所以設定時間種子後,rand函式依賴的自變數值與預設的或設定其它時間種子所得到值不一樣,當呼叫rand函式計算返回值時,由於自變數不同,故而返回值不同,但是請注意,rand函式返回值之前仍然會呼叫某個演算法來改變自變數的值,從而導致同一次程式執行中呼叫rand的返回值與上次呼叫返回的值不同。

//為了驗證srand和rand之間確實有共享資料(因變數)
//我寫了個簡單的測試程式:
int main(int argc,char* argv[])
{
	int tmp=0;
	for(int i=0;i<50;++i)
	{
		srand(0);
		// 獲取 0~19 的偽隨機數,存入tmp中
		tmp=rand()%20;
		cout<<tmp<<'\t';
	}
	cout<<endl;
	cin.get();
	cin.get();
	return 0;
}
//輸出結果每次都是一樣的,這說明儘管rand改變了因變數的值

//但是srand都會用0將因變數重置(不一定是將0賦值給因變數)

//所以每次輸出都是一樣的,這也可以很好的解釋在上面我們將

//srand((unsigned int)time(0));剪下至Mark處為什麼每次輸出

//都一樣,這是因為程式執行很快,以至於每次time(0)返回的都

//是同一個數,故rand返回值也就一樣咯。

所以我們自己也可以寫個rand函式來產生“隨機數”,不過改變因變數的演算法及計算返回值的演算法要好一點

以上全都是個人的猜想(不過我認為原理上應該是這樣的),如果有什麼不對,還望各位指正。