SICP 연습문제 2.1 친절한 풀이

문제

양수뿐 아니라 음수까지 다룰 수 있는 make-rat을 정의하라. 새 make-rat은, 유리수가 양수라면 분자와 분모 모두 양수이고, 유리수가 음수라면 분자만 음수가 되도록 처리해야 한다.

문제로 부터 얻은 것

쉬워보이는 문제일수록 언제나 다양한 해답이 존재한다는 것을 알았습니다.
구글에 검색해 보시면 더 다양한 해답들을 보실 수 있습니다.

문제풀이

처음 문제를 읽고 무지성으로 짜본 make-rat은 아래와 같습니다.

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

(define (make-rat n d)
(define (negative? x) (< x 0))
(define g (gcd n d))
(if (negative? (* n d))
(cons (- (abs (/ n g))) (abs (/ d g)))
(cons (abs (/ n g)) (abs (/ d g)))))

(make-rat 51 -34)



대충 훑어봐도 로직을 간결하게 만드려는 최소한의 노력도 없이 덕지덕지 붙은 코드입니다.

조금 더 신경을 써서 로직을 개선해 보겠습니다.

(define (make-rat n d)
(define g (abs (gcd n d)))
(if (< d 0)
(cons (- (/ n g)) (- (/ d g)))
(cons (/ n g) (/ d g))))



스스로 만족하고 있는 코드입니다.
(d<0)이라면, n이 음수인지 양수인지에 상관없이 -n을 분자로 가져야 합니다.
반대의 경우는 n이 음수인지 양수인지에 상관없이 n을 분자로 가져야 합니다.
이 원리를 기반으로 짠 코드입니다.
정상적으로 쌍을 만드는 모습



인터넷을 찾아보니 조금 더 간추린 설계도 있었습니다.

(define (make-rat n d)
(define g (abs (gcd n d)))
(define (sign x) (if (< x 0) - +))
(cons ((sign d) (/ n g)) ((sign d) (/ d g))))

읽어주셔서 감사합니다.