Exercise 2.1
Exercise 2.1: Define a better version of make-rat that handles both positive and negative arguments. make-rat should normalize the sign so that if the rational number is positive, both the numerator and denominator are positive, and if the rational number is negative, only the numerator is negative.
The first chapter is finished, today began to study the second chapter, so far have not encountered any problems, this question is relatively simple, as long as you note that "the numerator and denominator at the same time for the positive, or the molecule for the negative, the denominator is positive, do not need to change the sign; molecules and denominators at the same time for the negative, or molecules and denominators for the positive, the denominator need to change the sign of the molecules and denominators". This can easily fulfill the requirements of the question.
; (make-rat ⟨n⟩ ⟨d ⟩) returns the rational number whose numerator is the integer ⟨n⟩ and whose denominator is the integer ⟨d ⟩.
(define (make-rat n d)
(let ((n (/ n (gcd n d)))
(d (/ d (gcd n d))))
; The numerator and denominator are both positive,Or the numerator is negative,Positive denominator,No need to change symbols
; The numerator and denominator are both negative,Or the numerator is positive,Negative denominator,Both numerators and denominators need to change sign
(if (or (and (positive? n) (positive? d))
(and (negative? n) (positive? d)))
(cons n d)
(cons (- 0 n) (- 0 d)))))
; (numer ⟨x⟩) returns the numerator of the rational number ⟨x⟩.
(define (numer x) (car x))
; (denom ⟨x⟩) returns the denominator of the rational number ⟨x⟩.
(define (denom x) (cdr x))
(define (add-rat x y)
(make-rat (+ (* (numer x) (denom y))
(* (numer y) (denom x)))
(* (denom x) (denom y))))
(define (sub-rat x y)
(make-rat (- (* (numer x) (denom y))
(* (numer y) (denom x)))
(* (denom x) (denom y))))
(define (mul-rat x y)
(make-rat (* (numer x) (numer y))
(* (denom x) (denom y))))
(define (div-rat x y)
(make-rat (* (numer x) (denom y))
(* (denom x) (numer y))))
(define (equal-rat? x y)
(= (* (numer x) (denom y))
(* (numer y) (denom x))))
(define (print-rat x)
(newline)
(display (numer x))
(display "/")
(display (denom x)))
(print-rat (make-rat -1 2))
(print-rat (make-rat 1 2))
(define neg-one-half (make-rat -1 2))
(define one-third (make-rat 1 3))
(print-rat (add-rat neg-one-half one-third))
(print-rat (add-rat neg-one-half neg-one-half))
(print-rat (sub-rat neg-one-half one-third))
(print-rat (mul-rat neg-one-half one-third))
(print-rat (div-rat neg-one-half one-third))
; Implementation results
-1/2
1/2
-1/6
-1/1
-5/6
-1/6
-3/2
You can see that there is still room for improvement here, -1/1 is written as -1, which can be achieved using gcd, but I won't change it for the time being, maybe one of the later questions will ask to do this, so we'll talk about it then.