日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

取样问题

發(fā)布時間:2023/12/18 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 取样问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

問題描述:程序的輸入包含兩個整數(shù)m和n,其中m<n。輸出是0~n-1范圍內的m個隨機整數(shù),要求:每個數(shù)選擇出現(xiàn)的概率相等,且按序輸出。該題目是從《編程珠璣》的第12章看到的。

  學習過概率統(tǒng)計的同學應該都知道每一個數(shù)字被抽取的概率都應該為m/n. 那么我們怎么構造出這樣的概率呢?在《編程珠璣》上面是這樣解析的:

  依次考慮整數(shù)0,1,2,.....,n-1,并通過一個適當?shù)碾S機測試對每個整數(shù)進行選擇。通過按序訪問整數(shù),我們可以保證輸出結果是有序的。 假如我們考慮m = 2,n = 5的情況,那么選擇的每一個數(shù)字的概率都應該是2/5,我們怎么樣才能做到呢?不慌張,慢慢來。

  下面給出我的分析過程:在0,1,2,3,4這五個數(shù)字中,我們依次對每一個數(shù)進行分析,第一次遇到0時,它的選擇概率應該是2/5,如果選中了,我們開始測試第二個數(shù)1,這個時候因為1選中了,所以1這個數(shù)字的選中概率就變小了,變成1/4了,有人說這似乎不對吧,因為題目說讓每一個數(shù)字選中的概率是一樣大的,而現(xiàn)在?一個2/5,一個1/4,這怎么行呢?其實不是這樣的,認真思考一下就知道了,數(shù)字1選中的概率等于什么? 數(shù)字1選中的概率p(1) = 數(shù)字0選中的概率 * (1/4) + 數(shù)組0沒選中的概率*(2/4)這樣推算下 (2/5 * 1/4) + (3/5 * 2/4) = 8/20 = 2/5 。這不就一樣了嗎?呵呵!下面給出來自Knuth的《The Art of Computer Programming, Volume2:Seminumerical Algorithms》的偽代碼:

select = m remaining = n for i = [0,n)if (rand() % remaining) < selectprint iselect --remaining--

代碼很精簡,代碼遵守的規(guī)則應該是要從r個剩余的整數(shù)中選出s個,我們以概率s/r選擇下一個數(shù)。這個概率的選擇方式和我們上面證明的是一樣的。所以在程序結束的時候一定會打印出m個數(shù)字,且每一個數(shù)字的被選擇概率相同,為m/n。 (不要小看任何一段小代碼,其背后隱含著很多的意義!)

當然了,這個題目還有其他的解法,這是在網(wǎng)上看到的其他的解法。他們將這樣的問題抽象的定義為蓄水池抽樣問題。其思路是這樣的,先把前k個數(shù)放入蓄水池中,對第k+1,我們以k/(k+1)的概率決定是否要把它換入蓄水池,換入時我們可以隨機挑選一個作為替換位置,這樣一直到樣本空間N遍歷完,最后蓄水池中留下的就是結果。這樣的方法得到的結果也是正確的,且每一個數(shù)字被選擇的概率也是k/n。

證明:1) 當遍歷到到m+1個元素時, 該元素被保存在A’中的概率為 m/(m+1), 前面m個元素被保存在A’中的概率為 1- (m/m+1 * 1/m) = m/m+1
2) 當遍歷到第i個元素時,設前面i-1個元素被保存在A’中的概率為 m/(i-1)。根據(jù)算法, 第i個元素被保存在A’中的概率為m/i , 前面i-1各個元素留在A’中的概率為 m/(i-1) * (1-(m/i* 1/m) = m/i;
3)通過歸納,即可得到每個元素留在A’中的概率為 m/n;

參見:http://blog.csdn.net/hackbuteer1/article/details/6878627#reply?九樓smqjzzm1988?回復

?

這個問題其實還可以擴展一下:

  如何從n個對象(可以以此看到這n個對象,但事先不知道n的值)中隨機選擇一個?比如在不知道一個文本中有多少行,在這樣的情況下要求你隨機選擇文件中一行,且要求文件的每一行被選擇的概率相同。 在知道n這個總對象個數(shù)的情況下,誰都知道概率是1/n. 但是我們現(xiàn)在不知道,怎么辦呢?

  考慮這樣是不是可以,我們總是以1/i的概率去選擇每一次遍歷的對象,比如從1,2,3,4,5,6,....,N, 每一次遍歷到x時,總是以1/x的概率去選擇它.

整體思路如下:

  我們總選擇第一個數(shù)字(文本行),并以概率1/2選擇第二個(行),以1/3選擇第三行,也就是說設結果為result,遍歷第一個時result = 1,第二個時以1/2的概率替讓result = 2,這樣一直遍歷概率性的替換下去,最終的result就是你的結果。他被選擇的概率就是1/n。

  證明思路如下:

  第x個數(shù)被選擇的概率等于x被選擇的概率 * (x+1沒被選擇的概率) * (x+2沒有被選擇的概率) *......*(N沒有被選擇的概率) ?具體化一下

  2被選擇的概率 = 1/2 ?* 2/3 * 3/4 * 4/5 .....* (n-1/n) 我想你知道答案了吧? 對! 是1/n.這樣就可以在不知道N的大小的情況下等概率的去選擇任意一個對象了!

參考偽代碼如下:

i = 0 while more input lineswith probability 1.0/++ichoice = this input line print choice

由于本文章中的偽代碼思路很清晰,所以不必要貼出代碼了。

以上轉自:http://www.cnblogs.com/fxplove/archive/2012/07/25/2607544.html

?

現(xiàn)對取樣做一個小結:

1.輸出是0~n-1范圍內的m個隨機整數(shù),可重復。

void genRandoms1(int n,int m){for(int i=0;i<m;i++){int r=rand()%n;cout<<r<<' ';}cout<<endl; }

?

2.輸出是0~n-1范圍內的m個隨機整數(shù),不可重復。

//generate random digit in [l,u)
int rand(int l,int u){
//srand(time(0));
return rand()%(u-l)+l;
}


void
genRandoms2(int n,int m){int* a=new int[n];for(int i=0;i<n;i++){a[i]=i;}srand(time(0));for(int i=0;i<m;i++){int j=rand(i,n);swap(a[i],a[j]);cout<<a[i]<<' ';}cout<<endl;delete []a; }

?

3.輸出是0~n-1范圍內的m個有序的隨機整數(shù),可重復。

方法一,先生成可重復m個隨機整數(shù),然后排序。方法二,將生成的可重復m個隨機整數(shù)插入到非降序的集合中。

4.輸出是0~n-1范圍內的m個有序的隨機整數(shù),不可重復。

void genRandoms4(int n,int m){srand(time(0));for(int i=0;i<n;i++){if(rand()%(n-i)<m){cout<<i<<' ';m--;}}cout<<endl; }

轉載于:https://www.cnblogs.com/freewater/archive/2012/08/12/2635465.html

總結

以上是生活随笔為你收集整理的取样问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。