首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言區間隨機數生成:正確使用 srand/rand/time 避免常見陷阱

     編輯:關於C語言

核心 API

  • int rand(void):返回 [0, RAND_MAX] 偽隨機數 (RAND_MAX 通常 2147483647)。
  • void srand(unsigned seed):設置種子,**全程序只需調用一次**。
  • time_t time(time_t *t):獲取當前秒級時間戳,常作種子來源。

❌ 典型錯誤:循環中重複 srand


// 錯誤示範
for (int i=0; i<10000; i++) {
    srand((unsigned)time(NULL));  // time() 精度 1秒,循環極快 → 種子相同
    printf("%d\n", rand());       // 輸出全是同一個數!
}

✅ 正確模式:程序啟動時單次播種


#include 
#include 
#include 

int main() {
    srand((unsigned)time(NULL));  // 僅一次!
    for (int i=0; i<10; i++)
        printf("%d\n", rand());
    return 0;
}

生成指定區間隨機數

整數 [a, b] (含端點)


int rand_int(int a, int b) {
    return a + rand() / (RAND_MAX / (b - a + 1) + 1);
    // 或簡單但略有偏差:a + rand() % (b - a + 1)
}

取模法在 RAND_MAX 非 (b-a+1) 倍數時分布不均,除法法更均勻。

浮點數 [a, b)


double rand_double(double a, double b) {
    return a + (double)rand() / RAND_MAX * (b - a);
}

不重複隨機數(洗牌算法 / Fisher-Yates)

需從 N 個數中無放回抽取 k 個:


// 生成 0..N-1 的隨機排列,取前 k 個
void shuffle(int *arr, int n) {
    for (int i = n-1; i > 0; i--) {
        int j = rand_int(0, i);
        int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
    }
}
// 使用
int pool[10000];
for (int i=0; i<10000; i++) pool[i] = i;
shuffle(pool, 10000);
// pool[0..k-1] 即為 k 個不重複隨機數
  • 時間複雜度 O(N),空間 O(N)。
  • k << N 時可用蓄水池采樣 O(k) 空間。

線程安全版本:rand_r / drand48_r


unsigned int seed = (unsigned)time(NULL);
int r = rand_r(&seed);  // 可重入,每線程獨立 seed

高質量隨機數:/dev/urandom / C++11

  • 加密/安全場景:**禁用 rand()**,讀 /dev/urandom 或用 std::mt19937。
  • C11 可選支持 rand_s (Windows) / getrandom() (Linux)。

總結口訣

  1. srand 只調用一次,放在 main 開頭。
  2. 區間轉換用除法法減少偏差。
  3. 不重複用洗牌,別用「生成-查重」O(N²)。
  4. 多線程用 rand_r 或 C++ 。
  5. 安全場景用系統熵源。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved