的確是偽隨機

2021-07-09 17:36:51 字數 2359 閱讀 8802

c語言的 裡 rand() 函式可以產生 0 ~ rand_max (包括)之間的隨機數,通常是經過 srand() 函式進行初始化後再使用。

rand_max 的值預設是 32767 即 2^15-1 ,在 裡的定義是 #define rand_max 0x7fff;

所以如果需要求 [a, b] (顯然要有 b <= rand_max)之間的隨機數就可以這樣:

value = rand() % (b - a + 1) + a;

然而這樣做會出現乙個小問題,雖然影響不大,但還是值得談談。

舉個例子,假如需要產生 [1, 6] 之間的隨機數,用上面的方法計算就是

ans = rand() % 6 + 1;

即把乙個隨機數對 6 取模,產生乙個 0~5 的值,將這個值加上 1 並返回。但是,如果隨機數生成函式所返回的最大值是 32767,那麼這些值就不是「概率相等」。從 0~32765 返回的值所產生的 0~5 之間各個值的概率相等,都是 5461/32768。但是,最後兩個值,32766 和 32767 的返回值將分別是 0 和 1,這使它們的出現概率有所增加(是 5462/32768)。由於我們需要的答案的範圍很窄,所以這個差別是非常小的。

如果這個函式試圖產生乙個範圍在 [1, 30000] 之間的隨機數時,那麼前 2768 個值的出現概率將是後面那些值的兩倍!做個實驗,我們要產生 10000000 個 [1, 30000] 之間的隨機數;按照之前的說法,1~2768 之間的數出現的概率是 2/32768,而 2769~30000 之間的數出現的概率是 1/32768;因此 1~2768 之間的數出現的次數約為 10000000 * (2 / 32768) = 610 次,而 2768~30000 之間的數出現的次數約為 10000000 * (1 / 32768) = 305 次。

源**:

#include #include #include #include #define maxn   30000   /* 隨機數範圍 */

#define n 10000000 /* 試驗次數 */

int count[maxn+2];

/* 設定隨機種子 */

void seed()

}/* 計算 beg~end 的隨機數*/

int cal_rand1(int beg, int end)

int main()

for(i = 1; i <= maxn; i++)

printf("%d: %d\n", i, count[i]);

return 0;

}

結果為:(顯示一部分)

的確如此!那如果需要每個數出現的概率必須相同怎麼辦?有乙個簡單的方法:

比如要產生的最大隨機數是 b,則令 t = ((rand_max + 1) % b) * b - 1,那只要 rand() 函式一旦出現大於 t 的數就重新產生隨機數(其實就是把多出來的那部分去掉~),直到產生的數不大於 t。

修改後的程式:

#include #include #include #include #define maxn   30000   /* 隨機數範圍 */

#define n 10000000 /* 試驗次數 */

#define max_ok_rand \

(int)((((long)rand_max +1) / maxn) * maxn - 1) /* 允許產生的隨機數最大值 */

int count[maxn+2];

/* 設定隨機種子 */

void seed()

}/* 計算 beg~end 的隨機數*/

int cal_rand2(int beg, int end)

while(value > max_ok_rand);

return value % (end - beg + 1) + beg;

}int main()

for(i = 1; i <= maxn; i++)

printf("%d: %d\n", i, count[i]);

return 0;

}

理論上產生 10000000 個 [1, 30000] 之間的隨機數,每個數出現的次數約為 

10000000 * (1 / 30000) = 333 次,結果為:(顯示一部分)

還是比較接近的,這雖然是個小問題,但也是說大不大,說小不小的問題,既然發現就記錄下(來自《c 和指標》第 16 章課後習題)。。。

抄的確是經典

1 乙個人炫耀什麼,說明內心缺少什麼。2 乙個人越在意的地方,就是最令他自卑的地方。3 人都有以第一印象定好壞的習慣,認為乙個人好時,就會愛屋及烏,認為乙個人不好時,就會全盤否認。4 人越是得意的事情,越愛隱藏,越是痛苦的事情越愛小題大作。5 這個世界既不是有錢人的世界,也不是有權人的世界,它是有心...

python的確是個好工具

最近研究了一下python,覺得他這種問答式的介面特別適合學習程式設計,下面就舉兩個例子。1.快速排序的演算法描述 def qsort al if al return else aller x for x in al 1 if x al 0 比al 0 大 或相等 的部分 return qsort ...

需求分析的確是有難度的

今天對,招聘的簡歷管理模組和招聘專員又進行了溝通.發現,對方腦子裡已經有了乙個想法了.非要強加給我 給我的已經是細節了.真正的目的是什麼,他卻迴避.比較困擾.還有就是,找不到人.天哪另乙個部門的頭,今天都不在的說.我到 去談呀.團隊,倒是滿有意思.說是時間不夠.乙個會組織了3天了.天天拖終於定下明天...