核心:讓每個數被選中的概率都為k/n.
隨機取出乙個數,剩下的裡面再取出乙個數,重複k次。
方法一:利用洗牌的原理,將n個數(0至n-1)按次序排好,讓最後乙個數和乙個隨機(0~n-1)挑選出的位子進行互換,再讓倒數第2個數和(0~n-2)位置中挑選出來的位置進行互換,依次執行k次,陣列中的最後k個數就是得出的隨機數。
方法二:來自knuth的《the art of computer programming, volume2:seminumerical algorithms》的偽**:
select = m
remaining = n
for i = [0,n)
if (rand() % remaining) < select
print i
select--
remaining--
**理解:針對第乙個數使得它被選中的概率為k/n,第二個數使得它被選中的概率為k/n * (k-1)/(n-1) + (n-k)/n * k/(n-1),表示第乙個數被選中後,第二個數被選中的概率+第乙個數沒被選上後,第二個數被選上的概率,……
錯誤方法:
利用洗牌的原理,將n個數(0至n-1)按次序排好,依次讓每個數和乙個隨機挑選出的位子進行互換,這樣肯定不會重複,而且次序被打亂,具有隨機性。 只用交換k次,就可以取出k個小於n的互不相同的隨機數。
原因:假設k=2,n=5,針對陣列中的第乙個元素,分析它被選取的概率:第一次執行,被選取的概率為1/5;第二次執行,首先第乙個第一次不能不選取的概率為4/5,被換到陣列中的第二個位置的概率為1/5,換到其他位置的概率和為3/5,如果在第二個位置被選取的概率為2/5,其他位置被選取的概率為1/5,總和為1/5 + 1/5 * 2/5 + 3/5 * 1/5 = 2/5。
針對陣列中的第二個元素,第一次被選取的概率為1/5,第二次被選取的概率為:第一次沒選到4/5 * 第二次選到的概率2/5= 8/25,總和為1/5 + 8/25 = 13/25,被選中概率增大。
生成互不相同隨機數的一種演算法
c 中常用rand 和srand 函式相結合來生成每次執行都不相同的一組隨機數,常見的寫法如下 cpp view plain copy include include include include using namespace std int tmain int argc,tchar argv ...
C 生成指定數目的互不相同的隨機數
dotnet.frameword中提供了乙個專門產生隨機數的類system.random,計算機並不能產生完全隨機的數字,它生成的數字被稱為偽隨機數,它是以相同的概率從一組有限的數字中選取的,所選的數字並不具有完全的隨機性,但就實用而言,其隨機程度已經足夠了。在使用隨機數時,要先初始化乙個隨機數發生...
生成全不相同的隨機數
定義乙個陣列,有是個成員,儲存10個不同的從0 9的隨機數,如下。在g 下測試通過。include include include using std cout using std endl const int nrnum 10 void get rand void void get rand in...