int rand(void);[0, RAND_MAX],包含兩端。| 平台/庫 | RAND_MAX | 備註 |
|---|---|---|
| glibc (Linux) | 2147483647 (2^31-1) | 31 位,高質量 |
| MSVC (Windows) | 32767 (2^15-1) | 15 位,質量較低 |
| musl libc | 2147483647 | 同 glibc |
| 嵌入式 newlib | 32767 或 65535 | 視配置 |
rand() % N 產生 [0, N-1]問題:若 RAND_MAX + 1 不能被 N 整除,分布不均勻(模數偏差)。
正確:拒絕採樣法
int rand_range(int n) { // [0, n-1]
int limit = RAND_MAX - (RAND_MAX + 1) % n;
int r;
do { r = rand(); } while (r > limit);
return r % n;
}
srand(time(NULL)) 多次調用問題:同一秒內多次調用產生相同序列。
正確:程序啟動時僅調用一次srand;高並發/多線程用 thread_local 種子或 rand_r。
(double)rand()/RAND_MAX問題:精度有限,無法覆蓋所有浮點數;RAND_MAX 較小時分布稀疏。
現代替代:C11 <random.h>(若支持)或第三方庫(PCG、xoshiro256**)。
rand_r
unsigned int seed = 12345;
int r = rand_r(&seed); // 可重入,每線程持有獨立 seed
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main() {
printf("RAND_MAX = %d\n", RAND_MAX);
printf("INT_MAX = %d\n", INT_MAX);
// 簡單分布測試
long long cnt[10] = {0};
for (int i = 0; i < 1000000; ++i) cnt[rand() % 10]++;
for (int i = 0; i < 10; ++i) printf("%d: %lld\n", i, cnt[i]);
return 0;
}
rand() 返回 [0, RAND_MAX],RAND_MAX ≥ 32767。<random>。/dev/urandom、CryptGenRandom 或專用 CSPRNG。