#include
int rand(void); // 回傳 0 到 RAND_MAX 間的偽隨機數
void srand(unsigned int seed); // 設定隨機種子
RAND_MAX 至少 32767 (15 位),具體值實作定義 (常見 2147483647)。
for (int i = 0; i < 10; i++) printf("%d ", rand() % 10);
// 每次執行輸出相同:1 7 4 0 9 4 8 8 2 4 ...
等同於 srand(1)。必須呼叫 srand() 設定種子。
srand(5);
for (int i = 0; i < 10; i++) printf("%d ", rand() % 10);
// 每次輸出固定:4 3 5 9 0 0 7 9 2 0 ...
#include
srand((unsigned)time(NULL)); // 以當前秒數為種子
for (int i = 0; i < 10; i++) printf("%d ", rand() % 10);
// 每次執行結果不同
注意:若程式在同一秒內多次啟動 (如腳本循環),種子相同 → 序列相同。高頻場景需結合 clock()、getpid()、/dev/urandom 等熵源。
rand() % (max - min + 1) + min; // 當 RAND_MAX 非 (max-min+1) 倍數時,分布不均
例如 RAND_MAX=32767,取模 10,0-6 出現 3277 次,7-9 出現 3276 次。小範圍影響微小,大範圍或嚴格均勻需求不可用。
int rand_range(int min, int max) {
int range = max - min + 1;
int limit = RAND_MAX - (RAND_MAX % range); // 最大可接受值
int r;
do {
r = rand();
} while (r >= limit); // 拒絕超出範圍的值
return min + r % range;
}
保證數學上完美均勻分布。
double rand_double(void) {
return (double)rand() / (RAND_MAX + 1.0); // +1.0 確保 < 1.0
}
<random> (C++ 標準庫,C 無原生支援)C 語言標準庫僅提供 rand/srand (線性同餘法,統計品質差、週期短、不可預測性弱)。嚴肅應用請使用:
random()/srandom() (BSD 改良)、drand48() 系列getrandom() (系統呼叫,密碼學安全)、/dev/urandomBCryptGenRandom() (CNG API)RAND_bytes()、PCG、xoshiro256++ (單頭文件庫)
static uint32_t xorshift_state = 1; // 必須非 0
uint32_t xorshift32(void) {
uint32_t x = xorshift_state;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return xorshift_state = x;
}
// 使用
srand(time(NULL)); xorshift_state = rand(); // 種子
for (int i = 0; i < 10; i++) printf("%u ", xorshift32() % 100);
週期 2³²-1,速度極快、統計特性良好、適合遊戲/模擬 (非加密用途)。
void shuffle(int *arr, int n) {
for (int i = n - 1; i > 0; i--) {
int j = rand_range(0, i); // 0 到 i 之間均勻
int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
}
}
原地、O(n)、無偏差。切勿用 for(i=0;i
void reservoir_sample(int *stream, int n, int *sample, int k) {
for (int i = 0; i < k; i++) sample[i] = stream[i];
for (int i = k; i < n; i++) {
int j = rand_range(0, i);
if (j < k) sample[j] = stream[i];
}
}
串流處理、記憶體 O(k)。
srand(12345) 確保測試可重現rand_range(min, max) 含邊界、無越界rand() 非執行緒安全 (全域狀態),多執行緒用 rand_r(&seed) (POSIX) 或各執行緒獨立生成器實例| 場景 | 建議 |
|---|---|
| 教學/簡單工具/原型 | srand(time(NULL)) + rand() + 拒絕採樣 rand_range |
| 遊戲/模擬/科學計算 | xorshift32/64、PCG、xoshiro (單頭文件,零依賴) |
| 密碼學/安全/金融 | OS 提供的 CSPRNG (getrandom, BCryptGenRandom, /dev/urandom) |
| 跨平台庫開發 | 抽象介面 random_bytes(void*, size_t),平台層實作 |
隨機數看似簡單,實則暗藏統計學與安全陷阱。選對工具、用對方法,才能讓「隨機」真正服務於你的程式邏輯。