Lisp實現有理數的運算

  編寫一個處理有理數的函數。這個是參考SICP上的一個章節來寫,其主要思想時將問題拆分成獨立的部分,然後利用這些部分構建整個過程。接下來載後面的過程中會增加正負號的判斷,並且自制打印函數,打印有理數。

(defun numer (x)
 "Get the numerator of a rational number."
 (car x))

(defun denom (x)
 "Get the denominator of a rational number."
 (cdr x))

(defun make-rat (n d)
 "Make a rational number according to number and denom."
 (cons n d))

;;; We define the operations of rational number. ;;;
;;; Including +, -, *, / ;;;
(defun add-rat (x y)
 "Add two rational numbers."
 (make-rat (+ (* (numer x) (denom y)) (* (numer y) (denom x)))
  (* (denom x) (denom y))))

(defun sub-rat (x y)
 "Substract rational numbers."
 (make-rat (- (* (numer x) (denom y)) (* (numer y) (denom x)))
  (* (denom x) (denom y))))

(defun mul-rat (x y)
 "Multiply two rational numbers."
 (make-rat (* (numer x) (numer y))
  (* (denom x) (denom y))))

(defun div-rat (x y)
 "Divide two rational numbers."
 (mul-rat x (make-rat (denom y) (numer y))))
  上述程序片段是簡單的實現,利用假設兩個最基本的操作,取分子和取分母,我們可以根據標準的公式來進行有理數的四則運算。

   但是我們很明顯就會發現一些問題

  1. 有理數構建的時候分母爲0情況
  2. 有理數構建的時候分子和分母存在約數的情況
  3. 有理數的四則運算後分子和分母的約數
  4. 有理數的構建和運算過程中的正負號問題

  現在讓我們來修復第一個問題:分母爲0的情況。

(defun make-rat (n d)
 "Make a rational number according to number and denom."
 (if (zerop d) (error "!!Denominator zero Wrong!!")
 (cons n d)))
  在上面的程序片段中,增加了關於分母是否是0的判斷,如果分母爲0,則顯示錯誤。
  爲了修正約數的問題,我們首先要編寫最大公約數的函數,lisp已經提供了。不過,我們嘗試自己編寫一個

(defun gcd-my (x y)
 "Calculate the greatest common divisor of x and y."
 (if (or (zerop x) (zerop y)) (return-from gcd-my 0)
   (progn
	(loop while (not (zerop (mod x y))) do
	(let ((z x)) (setf x y) (setf y (mod z y)))) y)))
  剩下的工作作爲練習留給大家。在這裏說一下lisp的循環。包括(dolist (var list) body), (dotimes (var times) body), (loop while () do body), (loop until () do body). loop還有一些高級用法,這裏就不展開講,大家感興趣可以去讀讀pratical common lisp。

  本文完。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章