看到“首先提示輸入最大數int x(x>1)”,就知道是作業,別人不會幫你完成作業的。-------------- 如果你不是求作業,我可以拋磚引玉一下,談談“怎麼透過rand()生成任意範圍內的隨機數” --------------假設rand()的範圍是[0,3],現在要等機率的輸出[1,2]中的一個元素,那麼公式是 rand()/2+1。也就是在一個前提“[0,RAND_MAX]範圍 是 [1,x]範圍 的倍數”下,公式為 rand()/( (RAND_MAX+1)/x ) + 1。這就引來兩個子問題:a. 怎麼保證 RAND_MAX+1 大於 x ?b. RAND_MAX+1 不是 x 的倍數怎麼辦?第一個子問題很容易解決,若 RAND_MAX+1 < x 的話,可以用兩個rand()來擴張,兩個不夠還可以用3個,3個不夠用4個,……。比如 rand()的範圍是[0,RAND_MAX]而 rand()*(1+RAND_MAX) + rand() 的範圍就是[0,(RAND_MAX+1)*(RAND_MAX+1)-1],且依然是等機率分佈的(記住公式要保證“等機率分佈”)。第二個子問題無解,但有兩個不完美的妥協辦法:第一種妥協辦法是“捨棄掉rand()的一部分範圍,使得留下的範圍恰好是x的倍數”,虛擬碼是T t;for( ; t=rand(), t>=(RAND_MAX+1)/x*x; ); // 如果不在倍數範圍內,就重新獲得rand()return t/( (RAND_MAX+1)/x ) + 1;這種方法的缺點是無法預測for的迴圈次數,不符合計算機演算法的定義“耗費有限資源,經過有限步驟”,可能恰巧就有一次,等到頭髮都白了,for還在那裡迴圈。第二種妥協辦法是,假設 (RAND_MAX+1) 遠遠大於 x,則 (RAND_MAX+1)這個非常大的數就可以看成是x的倍數。這時候得用浮點數,公式為: (int)( rand()*(1.0/RAND_MAX) * (x-1) + 1 ) (原來的整數公式是不行的,因為畢竟不是整數倍,結果中可能出現x+1)這種方法的缺點是僅當 RAND_MAX 為無窮大時,(RAND_MAX+1)才真正是x的倍數,否則都只能算是“近似倍數”,也就是其結果不是完美的等機率分佈。
看到“首先提示輸入最大數int x(x>1)”,就知道是作業,別人不會幫你完成作業的。-------------- 如果你不是求作業,我可以拋磚引玉一下,談談“怎麼透過rand()生成任意範圍內的隨機數” --------------假設rand()的範圍是[0,3],現在要等機率的輸出[1,2]中的一個元素,那麼公式是 rand()/2+1。也就是在一個前提“[0,RAND_MAX]範圍 是 [1,x]範圍 的倍數”下,公式為 rand()/( (RAND_MAX+1)/x ) + 1。這就引來兩個子問題:a. 怎麼保證 RAND_MAX+1 大於 x ?b. RAND_MAX+1 不是 x 的倍數怎麼辦?第一個子問題很容易解決,若 RAND_MAX+1 < x 的話,可以用兩個rand()來擴張,兩個不夠還可以用3個,3個不夠用4個,……。比如 rand()的範圍是[0,RAND_MAX]而 rand()*(1+RAND_MAX) + rand() 的範圍就是[0,(RAND_MAX+1)*(RAND_MAX+1)-1],且依然是等機率分佈的(記住公式要保證“等機率分佈”)。第二個子問題無解,但有兩個不完美的妥協辦法:第一種妥協辦法是“捨棄掉rand()的一部分範圍,使得留下的範圍恰好是x的倍數”,虛擬碼是T t;for( ; t=rand(), t>=(RAND_MAX+1)/x*x; ); // 如果不在倍數範圍內,就重新獲得rand()return t/( (RAND_MAX+1)/x ) + 1;這種方法的缺點是無法預測for的迴圈次數,不符合計算機演算法的定義“耗費有限資源,經過有限步驟”,可能恰巧就有一次,等到頭髮都白了,for還在那裡迴圈。第二種妥協辦法是,假設 (RAND_MAX+1) 遠遠大於 x,則 (RAND_MAX+1)這個非常大的數就可以看成是x的倍數。這時候得用浮點數,公式為: (int)( rand()*(1.0/RAND_MAX) * (x-1) + 1 ) (原來的整數公式是不行的,因為畢竟不是整數倍,結果中可能出現x+1)這種方法的缺點是僅當 RAND_MAX 為無窮大時,(RAND_MAX+1)才真正是x的倍數,否則都只能算是“近似倍數”,也就是其結果不是完美的等機率分佈。