關於程式效率的問題 |
答題得分者是:tonytop
|
poemkevin
初階會員 ![]() ![]() 發表:26 回覆:77 積分:30 註冊:2002-10-19 發送簡訊給我 |
請教各位前輩, 下面二種方法那一種的效率比較高啊
小弟看是應是第一種, 只是程式運行時間一直沒測出來
所以不太明白用那種方式好!
希望能得到前輩們的指導,謝謝!!
procedure TForm1.Button1Click(Sender: TObject); var nCount: array [0..9] of integer; i: integer;//存儲所有幾個數字的出現次數 nFreq: array [0..9] of Double;//存儲幾個數字的頻率 S:string; nowtime:real; begin S:='123234556234354757568686967979780800809098998'; nowtime:=GetTickCount(); //取得目前時間 fillchar(nCount, SizeOf(integer) * 10, 0);//將所有存儲區域清 0 for i := 1 to Length(S) do if S[i] in ['0'..'9'] then//判斷是否數字 Inc(nCount[Ord(S[i]) - Ord('0')]);//按照字符的ASCII碼轉換為數組下標 if Length(S) <> 0 then for i := 0 to 9 do nFreq[i] := nCount[i] / Length(S); //計算出現頻率 nowtime:=GetTickCount()-nowtime; showmessage(format('%f',[nowtime])); end; procedure TForm1.Button2Click(Sender: TObject); var str1:array[0..9] of integer; i:integer; nowtime:real; s:string; begin S:='123234556234354757568686967979780800809098998'; nowtime:=GetTickCount(); //取得目前時間 for i:=0 to 9 do str1[i]:=0; for i:=1 to (length(s)) do begin if S[i] in ['0'..'9'] then //判斷是否數字 case strtoint(s[i]) of 0: inc(str1[0]); 1: inc(str1[1]); 2: inc(str1[2]); 3: inc(str1[3]); 4: inc(str1[4]); 5: inc(str1[5]); 6: inc(str1[6]); 7: inc(str1[7]); 8: inc(str1[8]); 9: inc(str1[9]); end; end; // for i:=0 to 9 do // showmessage('數字' inttostr(i) ':出現' inttostr(str1[i]) '次'); nowtime:=GetTickCount()-nowtime; showmessage(format('%f',[nowtime])); end;=========================== 沉思, 再沉思! 學習, 再學習! 生活隨喜, 簡單自在^^ =========================== |
tonytop
中階會員 ![]() ![]() ![]() 發表:6 回覆:114 積分:89 註冊:2003-12-04 發送簡訊給我 |
以演算法的觀念來說,這兩種方式效率是一樣滴,因for迴圈一樣跑了56次,
其他指令所花的時間接近於零可乎略不計,除非你有非常非常大量的資料才
能分出哪個較好,為了證明兩者花的時間是一樣的,我在兩邊的for迴圈end前
加入Sleep(50); 還有您nowtime要除1000才是毫秒唷!
showmessage(FloatToStr(nowtime/1000));//這樣可看到小數點第三位
我把字串長度增加到二百多個字元,得到的結果都一樣,
ps.要多跑幾次,且跑時不能執行其他程式,不然會不公平失去準確性,
//button 1 for i := 1 to Length(S) do begin //1-46 if S[i] in ['0'..'9'] then //判斷是否數字 Inc(nCount[Ord(S[i]) - Ord('0')]); //按照字符的ASCII碼轉換為數組下標 Sleep(50); //====加這行 end; //button 2 for i := 1 to (length(s)) do begin //1-46 if S[i] in ['0'..'9'] then //判斷是否數字 Inc(str1[strtoint(s[i])]); //===這樣也行 Sleep(50); end;我正確的mail:h832214@hotmail.com |
poemkevin
初階會員 ![]() ![]() 發表:26 回覆:77 積分:30 註冊:2002-10-19 發送簡訊給我 |
tonytop兄:
小弟本身有試過給它一篇文章來做測試,
只是怎麼測, 時間都是相同的. 之前有用過查表法的方式與迴圈式的程式做過比較,
資料量少的時候, 迴圈式的似乎比較簡便,
但若資料量大時, 用查表法會比較省時而有效率. 而有人說第二個比較沒有效率,
我不太明白為什麼會比較沒有效率
雖然第一個程式碼比第二個程式碼, 看起來比較簡短精悍,
但它用到二個迴圈及幾個迴數. 而第二個程式碼
for i:=0 to 9 do str1[i]:=0;應可以省略改為 const str1:array[0..9] of integer =(0,0,0,0,0,0,0,0,0,0) ; 剩下的大概只能比較case與if及for之間那種的效率比較快吧 不知是否有前輩做過這方面的研究 =========================== 沉思, 再沉思! 學習, 再學習! 生活隨喜, 簡單自在^^ =========================== |
shieh2700
高階會員 ![]() ![]() ![]() ![]() 發表:0 回覆:127 積分:100 註冊:2002-06-13 發送簡訊給我 |
另用 Console Application 改寫測試程式, 測試結果顯示第一種應該會比較快.
測試程式內容:
program P1; {$APPTYPE CONSOLE} uses SysUtils,windows; var nowtime:real; counter,sc,tc:integer; procedure f1; var nCount: array [0..9] of integer; i: integer;//存儲所有幾個數字的出現次數 nFreq: array [0..9] of Double;//存儲幾個數字的頻率 S:string; begin S:='123234556234354757568686967979780800809098998'; fillchar(nCount, SizeOf(integer) * 10, 0);//將所有存儲區域清 0 for i := 1 to Length(S) do if S[i] in ['0'..'9'] then//判斷是否數字 Inc(nCount[Ord(S[i]) - Ord('0')]);//按照字符的ASCII碼轉換為數組下標 if Length(S) <> 0 then for i := 0 to 9 do nFreq[i] := nCount[i] / Length(S); //計算出現頻率 end; procedure f2; var str1:array[0..9] of integer; i:integer; s:string; begin S:='123234556234354757568686967979780800809098998'; for i:=0 to 9 do str1[i]:=0; for i:=1 to (length(s)) do if S[i] in ['0'..'9'] then //判斷是否數字 inc(str1[strtoint(s[i])]); end; begin //Function 1 test: Write(#13#10 'Function1='); for tc := 1 to 6 do begin nowtime:=GetTickCount(); //取得目前時間 for counter := 1 to 5000 do for sc := 1 to 10 do f1; nowtime:=GetTickCount()-nowtime; Write(format('%f',[nowtime]) ', '); end; //Function 2 test: Write(#13#10 'Function2='); for tc := 1 to 6 do begin nowtime:=GetTickCount(); //取得目前時間 for counter := 1 to 5000 do for sc := 1 to 10 do f2; nowtime:=GetTickCount()-nowtime; Write(format('%f',[nowtime]) ', '); end; end. |
poemkevin
初階會員 ![]() ![]() 發表:26 回覆:77 積分:30 註冊:2002-10-19 發送簡訊給我 |
shieh2700大大:
謝謝您的指導!!
關於您的測試, 證明出用迴圈的效率比用CASE及IF..THEN效率還好!!
那麼是否以後小弟寫程式時, 就要注意要多用數學的方法,
多用迴圈來做, 盡量追求簡短精悍的程式碼....
推理: 演算法的好壞, 影響著程式執行的效率...
程式碼的長短, 對於程式的可讀性及是否有效率, 有相當的影響.
事前的多下點時間對程式做規劃, 總比事後的補救好的多, 程式的修修補補, 只會造成程式的碼的冗長及效率不彰. 雖答案不完全能解釋小弟心中的疑惑, 還是很感謝tonytop兄與shieh2700兄的指導^^ ===========================
沉思, 再沉思! 學習, 再學習!
生活隨喜, 簡單自在^^
===========================
|
roviury
一般會員 ![]() ![]() 發表:3 回覆:49 積分:15 註冊:2008-08-28 發送簡訊給我 |
delphi中的case只是多個if
不相信就看看asm asm才是追求效率的 asm:ctrl alt c 效率來說,這是最快的寫法 var str1:array[0..9] of integer; i:integer; nowtime:cardinal; s:string; begin S:='123234556234354757568686967979780800809098998'; nowtime:=GetTickCount(); //取得目前時間 //fillchar(nCount, SizeOf(S) , 0); //這是無意義的,初始化array時必定會清0 for i:=0 to length(s)-1 do if S[i 1] in ['0'..'9'] then inc(str1[ord(s[i 1])-$30]); nowtime:=GetTickCount()-nowtime; showmessage(format('%f',[nowtime])); end; |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |