C 標準庫的 rand() 產生的並非真正隨機數,而是偽隨機數。它基於一個種子,透過特定遞推公式生成數列。當數列足長時,統計分布近似常態分布。電腦啟動後預設種子固定,若不干預,每次執行產生的序列完全相同。
srand() 設種子,rand() 取值void srand(unsigned int seed):設定種子。常用 time(NULL) 取當前時間作種子,確保每次執行序列不同。int rand(void):返回 0 到 RAND_MAX(至少 32767)間的偽隨機整數。#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main(void) {
srand((unsigned)time(NULL)); // 初始化種子
// 1. 產生 0~RAND_MAX 間的隨機數
for (int i = 0; i < 10; ++i)
printf("%6d\n", rand());
// 2. 產生指定範圍 [min, max] 的隨機整數
int min = 0, max = 100;
for (int i = 0; i < 10; ++i) {
int val = min + (int)((double)rand() / (RAND_MAX + 1) * (max - min + 1));
printf("%6d\n", val);
}
return 0;
}
| 需求 | 推薦寫法 | 說明 |
|---|---|---|
| [0, 1] 浮點數 | rand() / (RAND_MAX + 1.0) | 避免整數除法截斷 |
| [min, max] 整數 | min + rand() % (max - min + 1) | 簡單但分布略有偏差(RAND_MAX+1 不整除範圍大小時) |
| 均勻分布整數 | 拒絕採樣法 | 丟棄超出範圍的值,嚴格均勻 |
random()/randomize()random(num) 直接返回 0 到 num-1,randomize() 自動以時間設種子。但它們非 ANSI C 標準,僅部分編譯器(如舊版 Turbo C、Borland C)支援,不可用於跨平台程式碼。請堅持使用標準 rand/srand。
// Fisher-Yates 洗牌:產生 1~512 的隨機排列
int a[513];
for (int i = 1; i <= 512; ++i) a[i] = i;
for (int i = 512; i >= 1; --i)
swap(&a[i], &a[rand() % i + 1]); // 注意 +1 避免索引 0
此法時空複雜度 O(N),適用於抽獎、洗牌等需不重複隨機序列的場景。
srand() 設種子,推薦 srand((unsigned)time(NULL))。rand() 返回 int,範圍 [0, RAND_MAX]。random()/randomize()。