關於產生數個不同的亂數........ |
答題得分者是:geniustom
|
A_DALA
一般會員 發表:1 回覆:1 積分:0 註冊:2004-10-25 發送簡訊給我 |
想請問各位:
我所想問的問題是,假使已達成產生了一個1到100的亂數了,但如果想達到產生五個不同1到100間的亂數呢??
procedure TForm1.Button1Click(Sender: TObject);
var
r:integer;
begin
randomize;
r:=random(42);
edit1.text:=IntToStr(r);
end; end.
上面是目前所學到的程度,也希望給予尚缺失的指點,不好意思請教各位了,謝謝..... 發表人 - A_DALA 於 2004/11/11 22:11:15
|
jeffreck
高階會員 發表:247 回覆:340 積分:197 註冊:2003-01-23 發送簡訊給我 |
|
A_DALA
一般會員 發表:1 回覆:1 積分:0 註冊:2004-10-25 發送簡訊給我 |
|
geniustom
版主 發表:100 回覆:303 積分:260 註冊:2003-01-03 發送簡訊給我 |
一般人看到【取亂數不重複】..很直接的想法就是一直取,每次取完之後在跟之前的比較..
其實這樣的效率極差!取N個不重複的亂數需要做N階乘次比對..
有學過資料結構的應該都知道..在複雜度裡面..N階乘算是【極差】
取亂數可以使用洗牌法..
意思就是說..
1..假設剛買來的牌..有52張..分別照順序排好...
2..你只需要把52張牌全部攤開..隨便選2張交換...
3..交換52次之後..可以做出很平均的亂數處理..
所以..如果要產生A~B不重複的亂數..演算法如下..
var Nums: array of integer; i,j,k,temp: integer; begin randomize; 灑下亂數種子 setlength(Nums,B-A) //產生B-A張牌 for i := 0 to (B-A)-1 do Nums[i] := i; //產生一副新牌..都是照順序排好的 for i := 0 to (B-A)-1 do begin j := random(B-A 1); //隨便選兩張牌(索引) 取出0~(B-A)的亂數 k := random(B-A 1); temp := Nums[j]; //交換兩張隨便取的牌 Nums[j] := Nums[k]; Nums[k] := temp; end; for i := 0 to (B-A)-1 do Nums[j]:=Nums[j] A; //最後..把這邊的排全部變成A~B的值 end; 假如您要取5個.. 那只要選Nums[0]~Nums[4]..就是一組很漂亮的亂數.. 效率極佳..只需要O(n)次... 而一般人想到那種差勁的演算法..差不多到100..程式就要死當了供參考 =程式是一種藝術 也是訓練自己的分析規劃= =是段落分明 或是雜亂無章= =是一言以敝 或是廢話連篇= =是一目了然 或是艱深難懂= 體會這份藝術 您會了解另一份喜悅與成就 發表人 - |
change.jian
版主 發表:29 回覆:620 積分:439 註冊:2003-06-02 發送簡訊給我 |
受教了 <>< face="Verdana, Arial, Helvetica">引言:
一般人看到【取亂數不重複】..很直接的想法就是一直取,每次取完之後在跟之前的比較..
其實這樣的效率極差!取N個不重複的亂數需要做N階乘次比對..
有學過資料結構的應該都知道..在複雜度裡面..N階乘算是【極差】
取亂數可以使用洗牌法..
意思就是說..
1..假設剛買來的牌..有52張..分別照順序排好...
2..你只需要把52張牌全部攤開..隨便選2張交換...
3..交換52次之後..可以做出很平均的亂數處理..
所以..如果要產生A~B不重複的亂數..演算法如下..
var Nums: array of integer; i,j,k,temp: integer; begin randomize; 灑下亂數種子 setlength(Nums,B-A) //產生B-A張牌 for i := 0 to (B-A)-1 do Nums[i] := i; //產生一副新牌..都是照順序排好的 for i := 0 to (B-A)-1 do begin j := random(B-A 1); //隨便選兩張牌(索引) 取出0~(B-A)的亂數 k := random(B-A 1); temp := Nums[j]; //交換兩張隨便取的牌 Nums[j] := Nums[k]; Nums[k] := temp; end; for i := 0 to (B-A)-1 do Nums[j]:=Nums[j] A; //最後..把這邊的排全部變成A~B的值 end; 假如您要取5個.. 那只要選Nums[0]~Nums[4]..就是一組很漂亮的亂數.. 效率極佳..只需要O(n)次... 而一般人想到那種差勁的演算法..差不多到100..程式就要死當了供參考 =程式是一種藝術 也是訓練自己的分析規劃= =是段落分明 或是雜亂無章= =是一言以敝 或是廢話連篇= =是一目了然 或是艱深難懂= 體會這份藝術 您會了解另一份喜悅與成就 發表人 - >>< face="Verdana, Arial, Helvetica"> |
jeffreck
高階會員 發表:247 回覆:340 積分:197 註冊:2003-01-23 發送簡訊給我 |
|
visor
一般會員 發表:5 回覆:12 積分:3 註冊:2003-09-09 發送簡訊給我 |
這樣的做法並不是最好的 有更好的做法可以將牌洗的更亂
複雜度也是 O(n)
假設我們有 52 張牌 srand(time(NULL)); //取亂數種子
for(i=0;i<52;i )
num[i] = i 1; //初始化 52 張牌 1~52
for(i=0;i<52;i ) //洗牌動作
{
j = rand()R; //隨機取 0~51 當索引
tmp = num[i]; //交換兩張牌
num[i] = num[j];
num[j] = tmp;
} 這樣子 num[] 就已經是一個不重覆且是雜亂的陣列了
你要取幾張牌 只要從頭開始取就可以了 演算法概要
首先需要兩組 index i,j
i 從 0~51
j 則是隨機 0~51
取出後做交換 這樣子每張牌都跟隨機一張牌做過交換動作 就可以達成洗牌動作了 --
Visor
元智大學資訊工程所
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |