sicp每日一題[2.79]

再思即可發表於2024-11-16

Exercise2.79

Define a generic equality predicate equ? that tests the equality of two numbers, and install it in the generic arithmetic package. This operation should work for ordinary numbers, rational numbers, and complex numbers.


這道題也挺簡單的,分別在一般數字、有理數和複數包裡實現這個函式就行了,以下程式碼複數部分在 2.77 的基礎上新增,一般數字和有理數在書上 2.5.1 的基礎上新增

(define (equ? x y) (apply-generic 'equ? x y))

; 一般數字
(put 'equ? '(scheme-number scheme-number) =)

; 有理數
(define (equ? x y)
  ;; 先化簡為最簡有理數
  (let ((simple-x (make-rat (numer x) (denom x)))
        (simple-y (make-rat (numer y) (denom y))))
    (and (= (numer simple-x) (numer simple-y))
         (= (denom simple-x) (denom simple-y)))))

(put 'equ? '(rational rational)
     (lambda (x y) (equ? x y)))

; 複數,只用在 install-complex-package 裡新增就行
(define (equ? z1 z2)
  (and (= (real-part z1) (real-part z2))
       (= (imag-part z1) (imag-part z2))))

(put 'equ? '(complex complex)
     (lambda (z1 z2) (equ? z1 z2)))


; 測試
(install-scheme-number-package)
(define n1 (make-scheme-number 5))
(define n2 (make-scheme-number 10))
(define n3 (make-scheme-number 10))
(equ? n1 n2)
(equ? n2 n3)

(newline)
(install-rational-package)
(define r1 (make-rational 5 5))
(define r2 (make-rational 10 10))
(define r3 (make-rational 10 20))
(equ? r1 r2)
(equ? r2 r3)

(newline)
(install-rectangular-package)
(install-polar-package)
(install-complex-package)
(define z1 (make-complex-from-real-imag 3 4))
(define z2 (make-complex-from-real-imag 3 4))
(define z3 (make-complex-from-real-imag 3 5))
(equ? z1 z2)
(equ? z2 z3)

; 結果如下
'done
#f
#t

'done
#t
#f

'done
'done
'done
#t
#f

看了一下別人的答案,有理數部分可以透過十字相乘來使得答案更簡單。

(define (equ? x y) 
   (= (* (numer x) (denom y)) (* (numer y) (denom x)))) 

相關文章