在一些程式競賽或一些線上程式解題系統中,複雜的程式敘述常常有一些程式執行時間不得超過幾秒的規定,當然自己 Debug 的時候,應該都會有個底,但為了更加確認 C++ 計算程式效率,可以透過時間函數來取得程式正確的執行時間作為依據,來當作一個比較的基準。
前言
先透過簡單的小題目來測試執行時間,不過像這種小程式用膝蓋想一定不可能超過兩秒,但如果你在競賽過程中,程式的效率自己無法拿捏的時候,或許測試效率所得到的依據會是你很重要的參考指標。
備註:有部分程式編譯工具有提供程式結束後自動 pause 以及印出程式執行時間,例:Code::block、Orwell DevC++。
題目
請輸入正整數 n <= 20,輸出一個 n 層的倒三角形。例如,n = 5 時輸出如下:
5
#########
#######
#####
###
#
需要的表頭及函數
既然是談時間,當然少不了 <time.h> 了,函數的部分則是建置在其中的 clock() ,函數 clock() 會在程式一執行的時候按下碼表,也就是說程式一執行便會開始計時。
如何使用
現在知道 clock() 函數的功能是程式一執行到結束的時間,所以我們只需要在程式末端 return 之前加入。
cout << (double)clock() / CLOCKS_PER_SEC << "S";c
應該會有網友們好奇,為什麼要除上 CLOCKS_PER_SEC,事實上 CLOCKS_PER_SEC 是常數,其數值固定為 1000,由於 clock() 是以毫秒來計算程式所執行的時間,所以透過除上 CLOCKS_PER_SEC 來呈現我們熟悉的秒數。
是否有人開始質疑站長不太會寫程式,怎麼這麼簡單的程式執行效率這麼差,其實並不是這樣的,由於程式一執行就開始計時,同時包含視窗跳出以及手動輸入測資的時間都包含在內,所以站長刻意拖了約 15 秒鐘之後再輸入測資,而得到 15.419 S 的結果,至於略過輸入時間來檢視程式效率的方法,請往下看下去。
備註:下方是由 Code::Block 自動加入:
Process returnd 0 <0x0> execution time : 秒數 s
Press any key to continue.
解決辦法
透過浮點數或雙精度來宣告 START、END。
double START,END; START = clock();
/*---要計算的程式效率區域---*/
END = clock();
cout << (END - START) / CLOCKS_PER_SEC << endl;
double START,END; START = clock();
* 感謝網友 jerrylin 提出程式碼的錯誤修正 :)
透過上方的程式碼就可以檢測出某部分的程式效率,當然也可以用來檢測遞迴函數的執行效率,其原理是先將目前的時間存入浮點變數 START,再將程式結束的時間存入浮點變數 END 中,最後只需要將程式 END 減去 START,就可以獲得此段程式碼作業時間。
由於有除去常數 CLOCKS_PER_SEC,所以得結果如下。
程式所執行所花費:35.217 //單位為秒 相當於 35217毫秒
進行運算所花費的時間:0.005 //單位為秒 相當於 5毫秒
補充:若未除去常數 CLOCKS_PER_SEC,則直接得毫秒。
程式所執行所花費:35217 // 單位 ms
進行運算所花費的時間:5 // 單位 ms
備註:如果參加競賽使用此方法檢測,請記得在提交程式碼之前將印出的部分拿掉或註解掉。
Code
本題測試的題目解答,有興趣或有疑問的朋友們可以自行複製並測試。
#include <iostream>
#include <time.h>
using namespace std;
int main (){
int n = 5;
cin >> n;
if ( n > 20) {
cout << "Error";
return 1;
}
double START,END;
START = clock();
for (int i = 0 ; n >= 1 ; n--, i++){
for (int j = 1 ; j <= 1 + 2*(n-1) ; j++){
cout << "#";
}
cout << endl;
for (int j = 0 ; j <= i ; j++){
cout << " ";
}
}
END = clock();
cout << endl << "程式執行所花費:" << (double)clock()/CLOCKS_PER_SEC << " S";
cout << endl << "進行運算所花費的時間:" << (END - START) / CLOCKS_PER_SEC << " S" << endl;
return 0;
}
更新:
2019/2/19 更新: 由於部分程式碼因為樣式更新,產生跑版,以及 Url 編碼亂入問題,已經想辦法修正,但程式碼並沒有再次驗證是否有完全修復,如果出現錯誤,麻煩各位給予反饋,或是自行修復,謝謝。