SICP §2.4(抽象データの多重表現 その1[複素数の表現])

いつもセクションの情報をまとめるときは、全体をざっと読んでからまとめ方の方向性何かを決めているんだけど、今回はちょっと長くて全部読んでない。
でもとりあえずまとめられそうなのでアウトプットしちゃおうと思う。


最初は「複素数」を題材にして、「複数の表現」を持たせた場合の扱い方について。ではまとめていこう。


複素数についての詳細はここを見てもらうとして・・・おっと、読み進んじまってたぜ。。数学ってロマンがあるよねぇ。


さて、複素数の表現の仕方として、次の2種があるわけだ。


一つは直交座標形式のこれ。



もう一つが極座標形式のこれ。


二つの表現は似ても似つかないくせに、驚くべき事にどちらの表現を使用しても「まったく同じ値の複素数」を表現することになる。証明もできるぞ。詳細はやらないけど。
ではこの二つの異なる表現の複素数に対し、それぞれを扱う手続きを定義してみよう。

直交座標形式

;==============================
;構成子
;==============================
;実部と虚部から複素数を生成
(define (make-from-real-imag x y)
  (cons x y))

;半径と角度から複素数を生成
(define (make-from-mag-ang r a)
  (cons (* r (cos a)) (* r (sin a))))


;==============================
;選択子
;==============================
;実部
(define (real-part z)
  (car z))
;虚部
(define (imag-part z)
  (cdr z))
;半径
(define (magnitude z)
  (sqrt (square (real-part z))
	(square (imag-part z))))
;角度
(define (angle z)
  (atan (imag-part z) (real-part z)))

極座標形式

;==============================
;構成子
;==============================
;実部と虚部から複素数を生成
(define (make-from-real-imag x y)
  (cons (sqrt (square x) (square y))
	(atan y x)))

;半径と角度から複素数を生成
(define (make-from-mag-ang r a)
  (cons r a))


;==============================
;選択子
;==============================
;実部
(define (real-part z)
  (* (magnitude z) (cos (angle z))))
;虚部
(define (imag-part z)
  (* (magnitude z) (sin (angle z))))
;半径
(define (magnitude z)
  (car z))
;角度
(define (angle z)
  (cdr z))

複素数の四則演算

上述の2種類の複素数表現、及びその操作手続きは、名前が競合するため同時に扱うことはできないが、どちらを選択しても次の四則演算手続きはそのまま使用できる。
なぜならば、これらの四則演算手続きが内部で見るオブジェクトは「複素数」オブジェクトであり、それを扱うための手続きは完全に上述の方法で用意されているから。

;==============================
;四則演算
;==============================
;複素数の加算
(define (add-complex z1 z2)
  (make-from-real-imag (+ (real-part z1) (real-part z2))
		       (+ (imag-part z1) (imag-part z2))))

;複素数の減算
(define (sub-complex z1 z2)
  (make-from-real-imag (- (real-part z1) (real-part z2))
		       (- (imag-part z1) (imag-part z2))))

;複素数の乗算
(define (mul-complex z1 z2)
  (make-from-mag-ang (* (magnitude z1) (magnitude z2))
		     (+ (angle z1) (angle z2))))

;複素数の除算
(define (div-complex z1 z2)
  (make-from-mag-ang (/ (magnitude z1) (magnitude z2))
		     (- (angle z1) (angle z2))))