程式計算中有個技巧,叫做Memoization,避免重複計算相同的工作。
以下分別用C/Python/Haskell來當範例
C Language
以Fibonacci Number來說,遞迴的表示式這樣。
lang: c1 2 3 4 5
| int fib(int n) { if (n < 2) return n; return fib(n - 1) + fib(n - 2); }
|
加上Memoization的程式碼會變這樣
lang: c1 2 3 4 5 6 7 8
| int _fib[100]; int fib(int n) { if (n < 2) return n; if (_fib[n] != -1) return _fib[n]; return (_fib[n] = fib(n - 1) + fib(n - 2)); } memset(_fib, -1, sizeof(fib));
|
Python
至於Python版Recursive的程式碼也相當相似
lang: python1 2 3 4 5
| def fib(n): if n in [0,1]: return n else: return fib(n - 1) + fib(n - 2)
|
不過由於Python將Function當First-Class Function,可以寫出像這樣的程式碼。
lang: python1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| def memoize(fn): stored = {} def memoized(*args): try: return stored[args] except: result = fn(*args) stored[args] = result return result return memoized
def fib(n): if n in [0,1]: return n else: return fib(n - 1) + fib(n - 2)
fib = memoize(fib)
|
更甚者可以使用Python的Decorator來簡化程式碼
lang: python1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| def memoize(fn): stored = {} def memoized(*args): try: return stored[args] except: result = fn(*args) stored[args] = result return result return memoized
@memoize def fib(n): if n in [0,1]: return n else: return fib(n - 1) + fib(n - 2)
|
Haskell
Haskell反而是裡面最麻煩的,因為他是個純Pure Functional Language。同樣的先來看Recursive版本。
lang: haskell1 2 3 4
| fib :: Int -> Integer fib 0 = 1 fib 1 = 1 fib n = fib (n - 1) + fib (n - 2)
|
而Memorize版的方法不少,不過比起上面兩種反而難以理解。
lang: haskell1 2 3 4 5
| memoized_fib :: Int -> Integer memoized_fib = (map fib [0 ..] !!) where fib 0 = 0 fib 1 = 1 fib n = memoized_fib(n - 2) + memoized_fib(n - 1)
|
果然各種程式語言個有所長,看情況決定該用些什麼語言解決問題才是。