int 取值范围_一定范围内的随机数
老司機(jī)的新問(wèn)題,取得[min, max]范圍的隨機(jī)數(shù)。
C版本的rand函數(shù)很不容易用對(duì),直接用rand() % (max - min + 1) + min,這個(gè)公式不對(duì)。這個(gè)公式與取最低位的算法相同,而隨機(jī)數(shù)的最低幾位不一定等概率。
Donald Knuth博士教導(dǎo)我們正確的用法是 rand() / ((RAND_MAX + 1U) / (max - min + 1)) + min,這把rand的所有可能的值分成max - min個(gè)桶,每個(gè)數(shù)落入0號(hào)到max - 1號(hào)桶的概率相等。
C++中有std::uniform_int_distribution<>,可以直接取一定范圍正態(tài)分布的隨機(jī)數(shù),我也沒(méi)有深究過(guò)上面那個(gè)公式是否不正確。
結(jié)果還真的不正確。
因?yàn)榇蠖鄶?shù)情況下,RAND_MAX / (max - min + 1) 都除不盡, 小數(shù)部分被舍去后,數(shù)值偏小。比如[RAND_MAX / 2, RAND_MAX / 2 + 1]這組,如果 RAND_MAX = 11,那么[0 - 4]的rand()被認(rèn)為是5,概率是5/11,而5-11被認(rèn)為是6,概率是6/11。
當(dāng)采樣次數(shù)與RAND_MAX同數(shù)量級(jí)時(shí),這個(gè)概率差就顯示出來(lái)了。這個(gè)值有時(shí)可能只有32767。大部分平臺(tái)上這個(gè)值 為INT_MAX。
做個(gè)游戲什么的,還沒(méi)有問(wèn)題,一但用于統(tǒng)計(jì)數(shù)據(jù),這就出錯(cuò)了。
stackoverflow上有人給出了正確的算法,注意這個(gè)算法是[0, max]的區(qū)間。
https://stackoverflow.com/questions/2509679/how-to-generate-a-random-integer-number-from-within-a-range#6852396?stackoverflow.com本質(zhì)上很簡(jiǎn)單,就是把RAND_MAX除不盡的部分從rand中消去。
long random_at_most(long max) {unsigned long// max <= RAND_MAX < ULONG_MAX, so this is okay.num_bins = (unsigned long) max + 1,num_rand = (unsigned long) RAND_MAX + 1,bin_size = num_rand / num_bins,defect = num_rand % num_bins;long x;do {x = random();}// This is carefully written not to overflowwhile (num_rand - defect <= (unsigned long)x);// Truncated division is intentionalreturn x / bin_size; }當(dāng)RAND_MAX不夠大時(shí)怎么辦,可以通過(guò)以下公式擴(kuò)展隨機(jī)數(shù)。
unsigned long newrand = rand() * ((unsigned long)RAND_MAX +1) + rand()注意RAND_MAX的取值,不要溢出了。
總結(jié)
以上是生活随笔為你收集整理的int 取值范围_一定范围内的随机数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 适用mac微信用户的免登陆多开防撤回插件
- 下一篇: oracle sql 排序