標準庫 rand() 僅提供 0~32767 範圍,無法滿足大範圍隨機需求。本文系統分析五種擴展方案,證明「按位組合 + 捨棄法」能同時滿足大範圍與等概率要求,並給出完整 C 實現代碼。
range 內的隨機整數(含 0,不含 range)rand() 基礎範圍 0~32767,假設其均勻分佈rand() * rand()範圍可達 ~10 億,但嚴重破壞等概率:大質數永不出現,合數頻率極高,不可用。
將上限轉為十進位位數,逐位生成 0~9 隨機數拼湊。例:上限 999,999,999 生成 9 位數。但若上限非 999... 形式(如 60,000),生成的 97,863 會超出範圍,需後續處理。
生成數 % range結果落在範圍內,但概率不均。以 60,000 為例,0~39,999 出現概率 2/100,000,40,000~59,999 僅 1/100,000。
逐位生成 0~對應上限位數值。上限 51,782 時,第二位上限為 1,導致 33,216 等數永不可生成,失效。
按位組合生成指定位數數值,若超出 range 則捨棄重生。數學證明:捨棄無效樣本不改變有效樣本相對概率,完美保證等概率。
// 生成 0~9 單位隨機數
static __inline int min_rand() {
return rand() % 10;
}
/**
* 生成 [0, range) 等概率隨機數
* @param range 上限(不包含)
* @return 隨機整數
*/
int my_rand(const int range) {
short bit = 0;
int tempt = range;
int rand_data = 0;
// 計算十進位位數
while (tempt > 0) {
bit++;
tempt /= 10;
}
// 按位組合生成隨機數
while (bit--)
rand_data = 10 * rand_data + min_rand();
// 捨棄法:超出範圍遞歸重生
if (rand_data >= range)
return my_rand(range);
return rand_data;
}
若需 [min, max) 區間,只需 min + my_rand(max - min) 即可。
本文出自「鄒輝」博客,轉載請保留出處:原文鏈接