Lab-10 [第十週]電腦到底有多快? 我的程式可以跑多快?(我的演算法有多好?)
**考量有些同學本週還在期中考模式, 這週仍是給輕鬆的..
  就.. 測試並研究範例, 然後寫心得。
  P.S:前一題萬年曆還沒做好的請繼續完成!
 Purpose:
  (1)了解如何量測你的程式可以跑多快?
    之前介紹過 time( ) 這會引起Y2K38 problem 的系統函數,
    它是被宣告在 <time.h> 內! 其實, 程式員必須還要知道:
   <time.h> 中還有宣告一些與時間速度等相關的函數與符號常數。
  (2)了解 Recursive 程式有多慢? (Loop 比較快!)
   研究若 Recursive 函數很慢要如何解決?
    例如 recursive 的 Fibonacci 很慢, 有何替代方案?
   請參考範例 fibLoop.c
    註: 這裡用 array (table) 把以前算過的答案記起來,
     算是一種 Dynamic programming (請用 gogle.com 查看)
 Description: 
  現在大部分同學已經可以寫出大部份的程式, 可是除了寫得好看外,
  也要考慮方法(Algorithm; 演算法)是否恰當? 是否執行起來夠快?
  這次就用Fibonacci的兔子問題來研究 clock() 這函數的用法, 
  注意clock() 這函數它是以 tick (滴答)為單位, 可是.. tick 是啥?
  一個 tick 是多久呢? 不一定!!!但可在<time.h>找到答案。
  (a)找出 TC++, Dev-CPP, MSVC 或其他的 C/C++ 之 include 目錄下,
   (也找學長幫忙看看 FreeBSD 和 Linux  上的 gcc/g++ )
   對以下這兩個 Symbolic constant 的 #define 是 多少:
      CLK_TCK,   CLOCKS_PER_SEC 
   然後把各版本的值列比較表, post 到 e3.nctu 上本題的討論區。
    (演習課時可以舉手請助教幫忙連到 FreeBSD/Linux工作站看看  :)
  (b)測試並研究 fibRec.c, 和fibLoop.c 程式, 然後寫心得潑到 討論區 上。
   **注意: 還不太懂 Fibonacci Rabbits problem 的請先上網查詢。
  (c)在你自己的電腦與學校電腦測試 clockFib.c 這程式, 注意會測試很久喔!
    我們在主程式用了個小技巧讓它測很多想測的 n 值!
   記得要把測試心得寫到 e3.nctu 上。
   **注意也研究  clockFib.c 內的 #ifdef 與 #ifndef 寫
*** 附件夾檔: fibRec.c, fibLoop.c, clockFib.c
 
補充說明:
 *** Recursive 真的很好用 :  想完就寫好了 !
   例如:
     -- GCD(m, n): 若 n 是 0 阿答案就是 m , 否則 .. 請 ..
             你告訴我 GCD(n, m%n); 阿那就是你要的答案 :-)
     -- hanoi(n, ...): 你先幫我把 n-1 個搬到別處, 
          我自己搬最底下一個, 你再幫忙我把別處的 n-1個搬到目的地!
     -- Factorial(n) :  你告訴我 (n-1)階乘, 我叫告訴你 n 階乘 !
     -- Fibonacci 費氏數列:  
            ***告訴我 n-1 和 n-2 個月的兔子各有幾對,
            *** 我就告訴你第  n 個月有幾對的兔子 :
         long long fib(int n) { // 注意你的編譯器不一定可用long long
            if(n < 0) return 0; // 以前沒有兔子 
            if(n==0 || n==1) return 1; // 第 0 個月和第 1 個月
            return fib(n-1) + fib(n-2);
         }

 ***Recursive 真的是很簡單, 也真的是想完就寫完了!
  可是, 當 n 稍微大一些, 就會做很久 !  例如, fib(55) 可能就要算很久 !
  Why? 因為算 fib(55)就要先算 fib(54) 與 fib(53), 
   阿算 fib(54) 又要算 fib(53) 與 fib(52), ...

 *** 要如何量測程式的執行時間 (running time) 呢?
   time(0)傳回的是從 1970/01/01 00:00:00 到現在幾秒, 
  也就是誤差會大到一秒, 所以 time( ) 顯然不夠用!
   因差一秒就差很多了! 尤其是只有做很短時間的! 那要怎辦呢? 
  阿當然可以故意用 Loop 做很多次量出後再除以 Loop 次數, 可是..
   .. 其實, 最好 改用 clock( ) 啦, 
  若時間實在太短, 也是可用 Loop 跑很多次且用 clock( ) 量,
   或是,
    有些系統有更準的 function 如 nanotime( ) 等, 自己找看看!
  須注意 long clock( ) 傳回的是以 tick(滴答) 為單位!
  如何換算成秒 ?
 *** TC++ 沒有 long long
 *** long long 有些用 %lld   
   但有些用 %I64d (Dev-Cpp 或說 MINGW32)
   注意也研究  clockFib.c 內的 #ifdef 與 #ifndef 寫法! 
   不懂就舉手找助教過來問!

*** 下週預告: Sorting, 還有, 量測各種  sorting 的快慢 !
   請先用 http://gogle.com 查  "sorting"