線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2760
推到 Plurk!
推到 Facebook!

關於程式效率的問題

答題得分者是:tonytop
poemkevin
初階會員


發表:26
回覆:77
積分:30
註冊:2002-10-19

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-12-02 11:45:53 IP:210.202.xxx.xxx 未訂閱
請教各位前輩, 下面二種方法那一種的效率比較高啊 小弟看是應是第一種, 只是程式運行時間一直沒測出來 所以不太明白用那種方式好! 希望能得到前輩們的指導,謝謝!!    
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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-12-02 17:14:47 IP:210.64.xxx.xxx 未訂閱
以演算法的觀念來說,這兩種方式效率是一樣滴,因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

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-12-02 19:27:43 IP:61.221.xxx.xxx 未訂閱
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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-12-03 01:09:26 IP:61.229.xxx.xxx 未訂閱
另用 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

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-12-03 09:52:06 IP:210.202.xxx.xxx 未訂閱
shieh2700大大: 謝謝您的指導!! 關於您的測試, 證明出用迴圈的效率比用CASE及IF..THEN效率還好!! 那麼是否以後小弟寫程式時, 就要注意要多用數學的方法, 多用迴圈來做, 盡量追求簡短精悍的程式碼.... 推理: 演算法的好壞, 影響著程式執行的效率... 程式碼的長短, 對於程式的可讀性及是否有效率, 有相當的影響. 事前的多下點時間對程式做規劃, 總比事後的補救好的多, 程式的修修補補, 只會造成程式的碼的冗長及效率不彰. 雖答案不完全能解釋小弟心中的疑惑, 還是很感謝tonytop兄與shieh2700兄的指導^^ =========================== 沉思, 再沉思! 學習, 再學習! 生活隨喜, 簡單自在^^ ===========================
roviury
一般會員


發表:3
回覆:49
積分:15
註冊:2008-08-28

發送簡訊給我
#6 引用回覆 回覆 發表時間:2009-05-18 20:09:28 IP:203.186.xxx.xxx 訂閱
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;
系統時間:2024-04-27 10:45:52
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!