對於階乘運算n!,採用遞迴形式編寫是非常容易理解的:
(define (factorial n)
(if (= n 1) 1
(* n (factorial (- n 1))
))
計算6!,其執行過程是這樣的:
(factorial 6)
(* 6 (factorial 5))
(* 6 (* 5 (factorial 4)))
(* 6 (* 5 (* 4 (factorial 3))))
(* 6 (* 5 (* 4 (* 3 (factorial 2)))))
(* 6 (* 5 (* 4 (* 3 (* 2 (factorial 1))))))
(* 6 (* 5 (* 4 (* 3 (* 2 1)))))
(* 6 (* 5 (* 4 (* 3 2))))
(* 6 (* 5 (* 4 6))
(* 6 (* 5 24)
(* 6 120)
720
可以看出,在計算n!過程中,推遲執行的乘法鏈條的長度,也就是為儲存其軌跡需要儲存的資料量,這個長度隨著n值而線性增長。
下面我們採用迭代形式來重構這個過程:
(define (newfac n)
(define (ite***c result counter)
(if (= counter n) (* n result)
(ite***c (* result counter) (+ counter 1))))
(ite***c 1 1)
)
這裡我們定義了兩個過程,ite***c是定義在newfac內部,只能被newfac呼叫。同樣,我們用來計算6!時,它的計算過程是這樣的:
(newfac 6)
(ite***c 1 1)
(ite***c 1 2)
(ite***c 2 3)
(ite***c 6 4)
(ite***c 24 5)
(ite***c 120 6)
720
迭代過程中,沒有任何儲存資料量的增長,對於任何乙個n,在計算過程中的每一步,我們需要儲存的就是result和counter。用乙個變數(eg. result)傳遞迭代過程中狀態的變化,這是迭代過程的核心!
下面給出乙個o(logn)複雜度的冪運算的迭代過程:
(define (newexp b n)
(define (even? n)
(= (remainder n 2) 0)
) (define (iterexp a k result)
(cond ((= k 1) result)
((even? k) (iterexp (* a a) (/ k 2) (* result result)))
(else (* (iterexp a (- k 1) result) a))
)) (iterexp b n b)
)
(even? n)用來判斷n是基數還是偶數,計算b^n時,我們採用的是這樣一種方法:
b^n = (b^2)^(n/2) (n是偶數時),b^n = b^(n-1)*b(n為奇數),result用來儲存計算結果,a用來儲存基數的變化。
Lisp 學習日誌
從噹噹買到了 實用common lisp教程 冰河譯 終於有本 新 的lisp書了。準備把學習過程中比較惱人的問題記在這裡。sbcl clisp都只有x86版,看著clozure cl 1.7 有win64版,因為用的win64,就選了ccl。嘗試 format nil r 999999999999...
ACSL競賽筆記 Lisp
acsl競賽考到的lisp控制符 1 car 保留list中第一部分 可能為乙個元素,也可能為乙個子list 2 cdr 去掉list中第一部分 3 reverse 把list中各個部分倒序輸出 4 setq 賦值運算子,把乙個變數賦值為乙個list 例題 setq x a b c d e b c ...
lisp學習總結(一)
lisp太簡單 lisp核心太簡單了只有幾個簡單的邏輯定理,簡單到你會認為他啥事都做不了。lisp語法太簡單了,只有符號,引數,以及括號,組成一種萬能的表示式。由於上述lisp的簡單,所以對於初學者來講,他太難了,因為要做事情,上面這些簡單的規則根本不足以讓初學者構造高樓大廈。所以構造高樓大廈的話學...