#include <stdio.h>
#include <stdlib.h>
main() {
int i, roll[7] = {0}, m;
for (i = 0; i < 6000; i++) {
m = (int)(1 + rand(6)); // 錯誤:rand() 不接受參數
roll[m]++;
}
for (i = 1; i <= 6; i++)
printf("roll[%d]=%5d\n", i, roll[i]);
return 0;
}
錯誤訊息:error C2660: 'rand' : function does not take 1 parameters
| 函數 | 原型 | 說明 |
|---|---|---|
rand() | int rand(void) | 返回 0 到 RAND_MAX (至少 32767) 之間的偽隨機整數,無參數 |
srand() | void srand(unsigned int seed) | 設定隨機數生成器種子,程式啟動時呼叫一次 |
#include <stdio.h>
#include <stdlib.h>
#include <time.h> // time() 需要
int main() {
int roll[7] = {0}; // 索引 1-6 對應骰子點數,0 不用
int i, m;
// 1. 設定種子:使用當前時間,每次執行序列不同
srand((unsigned int)time(NULL));
// 2. 生成 6000 次
for (i = 0; i < 6000; ++i) {
// rand() % 6 產生 0-5,+1 變 1-6
m = rand() % 6 + 1;
roll[m]++;
}
// 3. 輸出統計
for (i = 1; i <= 6; ++i) {
printf("roll[%d] = %d\n", i, roll[i]);
}
return 0;
}
srand(time(NULL))?rand() 產生的是偽隨機序列,由種子決定。srand 時,預設種子為 1,每次執行產生相同序列。time(NULL) 返回當前 Unix 時間戳(秒),每秒變化,適合作種子。main 開頭。重複呼叫會重置序列,降低隨機性。rand() % 6 + 1 的分布特性RAND_MAX 通常為 32767 (2^15-1) 或 2147483647 (2^31-1)。RAND_MAX+1 時),但對 6 面骰子、6000 次樣本可忽略。
int uniform_d6() {
int x;
do {
x = rand();
} while (x >= RAND_MAX - (RAND_MAX + 1) % 6); // 拒絕多餘範圍
return x % 6 + 1;
}
roll[7] 索引 0-6,使用 1-6,roll[0] 永遠為 0。i=1; i<=6 正確對應骰子點數。<stdrandom.h>(提議中)與現代替代方案C 標準庫 rand/srand 品質較低(線性同餘法、週期短、低位隨機性差)。現代專案建議:
| 方案 | 特點 | 適用場景 |
|---|---|---|
| Mersenne Twister (mt19937) | 週期 2^19937-1、高品質、標準 C++ <random>、C 需第三方實作 | 科學模擬、遊戲、密碼學非敏感 |
| PCG (Permuted Congruential Generator) | 狀態小、速度快、統計特性優、單檔案 C 實作 | 嵌入式、遊戲、通用高品質 |
| xoshiro/xoroshiro | 極快、高品質、並行友好、C 單頭檔 | 高效能、並行模擬 |
| 系統熵源 | /dev/urandom (Linux)、BCryptGenRandom (Windows)、getrandom() (Linux 3.17+) | 密碼學、安全關鍵、種子生成 |
// 執行後觀察各面出現次數是否接近 1000 (6000/6)
roll[1] = 998
roll[2] = 1012
roll[3] = 987
roll[4] = 1005
roll[5] = 1003
roll[6] = 995
// 卡方檢定可量化驗證均勻性
| 錯誤代碼 | 問題 | 修正 |
|---|---|---|
rand(6) | rand 無參數 | rand() % 6 + 1 |
無 srand | 每次執行相同序列 | srand(time(NULL)) 在 main 開頭呼叫一次 |
迴圈中呼叫 srand | 重置種子,序列退化 | 移出迴圈,僅呼叫一次 |
rand() % n 當 n 較大 | 模偏差明顯 | 用拒絕採樣或高品質 RNG |
roll[6] 索引 0-5 | 輸出迴圈易混淆 | roll[7] 索引 1-6 對應業務語意 |
rand() 無參數,配合 srand(time(NULL)) 初始化種子,用 rand() % n + offset 映射到目標範圍。理解偽隨機本質、種子管理、模偏差,能寫出正確、可重現、統計特性可接受的隨機數代碼。生產級高品質需求請用 PCG、xoshiro 或系統熵源。