C C 隨機數函式

2021-10-04 07:25:46 字數 3185 閱讀 3412

學習了不同儲存類別的概念後,我們來看幾個相關的程式。

首先,來看 乙個使用內部鏈結的靜態變數的函式:隨機數函式。

ansi c庫提供了rand() 函式生成隨機數。生成隨機數有多種演算法,ansi c允許c實現針對特定機器 使用最佳演算法。

然而,ansi c標準還提供了乙個可移植的標準演算法,在不 同系統中生成相同的隨機數。實際上,rand()是「偽隨機數生成器」,意思是 可**生成數字的實際序列。但是,數字在其取值範圍內均勻分布。

為了看清楚程式內部的情況,我們使用可移植的ansi版本,而不是編譯器內建的rand()函式。可移植版本的方案開始於乙個「種子」數字。該函式使用該種子生成新的數,這個新數又成為新的種子。然後,新種子可用於生 成更新的種子,以此類推。該方案要行之有效,隨機數函式必須記錄它上一 次被呼叫時所使用的種子。這裡需要乙個靜態變數。

/* rand0.c --生成隨機數*/

/* 使用 ansi c 可移植演算法 */

static

unsigned

long

int next =1;

/* 種子 */

unsigned

intrand0

(void

)

在程式清單12.7中,靜態變數next的初始值是1,其值在每次呼叫rand0() 函式時都會被修改(通過魔術公式)。該函式是用於返回乙個0~32767之間 的值。注意,next是具有內部鏈結的靜態變數(並非無鏈結)。這是為了方便稍後擴充套件本例,供同乙個檔案中的其他函式共享。

/* r_drive0.c -- 測試 rand0()函式 */

/* 與 rand0.c 一起編譯*/

#include

extern

unsigned

intrand0

(void);

intmain

(void

)

該程式也需要多檔案編譯。程式清單 12.7 和程式清單 12.8 分別使用一 個檔案。程式清單 12.8 中的extern關鍵字提醒讀者rand0()被定義在其他檔案 中,在這個檔案中不要求寫出該函式原型。輸出如下:

16838

5758

10113

17515

31051

程式輸出的數字看上去是隨機的,再次執行程式後,輸出如下:

16838

5758

10113

17515

31051

看來,這兩次的輸出完全相同,這體現了「偽隨機」的乙個方面。每次主 程式執行,都開始於相同的種子1。可以引入另乙個函式srand1()重置種子來 解決這個問題。關鍵是要讓next成為只供rand1()和srand1()訪問的內部鏈結靜態變數(srand1()相當於c庫中的srand()函式)。把srand1()加入rand1()所在 的檔案中。程式清單12.9給出了修改後的檔案。

/* s_and_r.c -- 包含 rand1() 和 srand1() 的檔案  */

/*       使用 ansi c 可移植演算法   */

static

unsigned

long

int next =1;

/* 種子 */

intrand1

(void

)void

srand1

(unsigned

int seed)

注意,next是具有內部鏈結的檔案作用域靜態變數。

這意味著rand1()和 srand1()都可以使用它,但是其他檔案中的函式無法訪問它。使用程式清單 12.10的驅動程式測試這兩個函式。

程式清單12.10 r_drive1.c驅動程式

/* r_drive1.c -- 測試 rand1() 和 srand1() */

/* 與 s_and_r.c 一起編譯 */

#include

#include

extern

void

srand1

(unsigned

int x)

;extern

intrand1

(void);

897int

main

(void

)printf

("done\n");

return0;

}

編譯兩個檔案,執行該程式後,其輸出如下:

1

16838

5758

89810113

17515

31051

please enter next seed (q to quit)

:513

20067

23475

8955

20841

15324

please enter next seed (q to quit):q

done

設定seed的值為1,輸出的結果與前面程式相同。但是設定seed的值為 513後就得到了新的結果。

注意 自動重置種子

如果 c 實現允許訪問一些可變的量(如,時鐘系統),可以用這些值 (可能會被截斷)初始化種子值。例如,ansi c有乙個time()函式返回系統 時間。雖然時間單元因系統而異,但是重點是該返回值是乙個可進行運算的 型別,而且其值隨著時間變化而變化。time()返回值的型別名是time_t,具體 型別與系統有關。這沒關係,我們可以使用強制型別轉換:

#include

/* 提供time()的ansi原型*/

srand1((

unsigned

int)

time(0

));/* 初始化種子 */

一般而言,time()接受的引數是乙個 time_t 型別物件的位址,而時間值 就儲存在傳入的位址上。當然,也可以傳入空指標(0)作為引數,這種情 況下,只能通過返回值機制來提供值。

可以把這個技巧應用於標準的ansi c函式srand()和rand()中。如果使用 這些函式,要在檔案中包含stdlib.c標頭檔案。實際上,既然已經明白了 srand1()和rand1()如何使用內部鏈結的靜態變數,你也可以使用編譯器提供 的版本。我們將在下乙個示例中這樣做。

C C 產生隨機數的函式

c語言中有可以產生隨機數的函式,需要新增 stdlib.h 標頭檔案和 time.h 標頭檔案。srand unsigned time null 初始化隨機種子 for int i 0 i 10 i printf d rand 其中,rand 函式只能產生 0,rand max 範圍內的整數 ran...

C C 生成隨機數

01 include 02 include 03 04intmain intargc,char argv 05 10return0 11 01 02上述方法產生隨機數每次不同,但每次執行時產生的順序是相同的。原因是每次的種子都相同,所以會產生相同的隨機數列。一般使用時間作為種子保證每次的種子都不同。...

C C 產生隨機數

c c 產生隨機數 c c 產生隨機數用到兩個函式rand 和 srand 一.不指定範圍產生隨機數 用到函式rand 函式原型為int rand 無引數。此時會產生乙個介於0 rand max間的整數。rand max的大小可以檢視,在include資料夾 linux在usr目錄 windows在...