問題2-1

負の有理数を正規化するmake-ratを作成する問題です。簡単だと甘く見ていたら、最初は上手くいきませんでした。

(define (gcd a b)
  (if (= b 0)
      a
      (gcd b (remainder a b))))

(define (make-rat n d)
  (let ((g (gcd n d)))
    (cond ((and (> 0 n) (> 0 d)) 
           (cons (* -1 (/ n g)) (* -1 (/ d g))))
          ((> 0 n) 
           (cons (* -1 (/ n g)) (* -1 (/ d g))))
          (else 
           (cons (/ n g) (/ d g))))))

rintaroさんの模範解答を眺めながら、最大公約数ロジックに負の数を渡すとどうなるのかという点への考慮が足りていないことに気づきました。また、正負のチェックは分子だけでよいという点も見逃していました。

(define (make-rat n d)
  (let ((g (abs (gcd n d))))
    (cond ((> 0 n)
           (cons (* -1 (/ n g)) (* -1 (/ d g))))
          (else
           (cons (/ n g) (/ d g))))))

(print-rat (make-rat 6 9))
(print-rat (make-rat -6 9))
(print-rat (make-rat 6 -9))
(print-rat (make-rat -6 -9))

=>2/3
=>2/-3
=>2/-3
=>2/3